시배's Android

Compose Docs | Alignment lines 본문

Android/Compose Docs

Compose Docs | Alignment lines

si8ae 2023. 9. 3. 18:43
 

Jetpack Compose의 정렬 선  |  Android Developers

Jetpack Compose의 정렬 선 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Compose 레이아웃 모델을 사용하면 AlignmentLine을 사용하여 맞춤 정렬 선을 만들 수 있습

developer.android.com

Alignment lines in Jetpack Compose

레이아웃 작성 모델을 사용하면 AlignmentLine을 사용하여 부모 레이아웃에서 자식을 정렬하고 배치하는 데 사용할 수 있는 사용자 지정 정렬선을 만들 수 있습니다. 예를 들어 Row는 자식의 사용자 지정 정렬선을 사용하여 자식을 정렬할 수 있습니다.
레이아웃이 특정 정렬선에 대한 값을 제공하면 레이아웃의 부모 레이아웃은 해당 배치가능 인스턴스에서 배치가능.get 연산자를 사용하여 측정한 후 이 값을 읽을 수 있습니다. 그런 다음 부모는 정렬 선의 위치에 따라 자식의 위치를 결정할 수 있습니다.
Compose의 일부 컴포저블에는 이미 정렬 선이 포함되어 있습니다. 예를 들어, BasicText 컴포저블은 FirstBaseline 및 LastBaseline 정렬선을 노출합니다.
아래 예시에서 firstBaselineToTop이라는 커스텀 레이아웃 모디파이어는 첫 번째 기준선부터 텍스트에 패딩을 추가하기 위해 첫 번째 기준선을 읽습니다.

fun Modifier.firstBaselineToTop(
    firstBaselineToTop: Dp,
) = layout { measurable, constraints ->
    // Measure the composable
    val placeable = measurable.measure(constraints)

    // Check the composable has a first baseline
    check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
    val firstBaseline = placeable[FirstBaseline]

    // Height of the composable with padding - first baseline
    val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
    val height = placeable.height + placeableY
    layout(placeable.width, height) {
        // Where the composable gets placed
        placeable.placeRelative(0, placeableY)
    }
}

@Preview
@Composable
private fun TextWithPaddingToBaseline() {
    MaterialTheme {
        Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
    }
}

이 예제에서 FirstBaseline을 읽기 위해 measurement 단계에서 [FirstBaseline] placeable이 사용됩니다.

Create custom alignment lines

커스텀 레이아웃 컴포저블 또는 커스텀 레이아웃 모디파이어를 만들 때 커스텀 정렬선을 제공하면 다른 부모 컴포저블이 이를 사용하여 자식들을 적절히 정렬하고 배치할 수 있습니다.

다음 예는 다른 컴포저블이 차트의 최대 및 최소 데이터 값에 맞춰 정렬할 수 있도록 두 개의 정렬 선인 MaxChartValue와 MinChartValue를 노출하는 사용자 지정 BarChart 컴포저블을 보여줍니다. 두 개의 텍스트 요소인 Max와 Min이 사용자 지정 맞춤선의 중앙에 정렬되었습니다.

/**
 * AlignmentLine defined by the maximum data value in a [BarChart]
 */
private val MaxChartValue = HorizontalAlignmentLine(merger = { old, new ->
    min(old, new)
})

/**
 * AlignmentLine defined by the minimum data value in a [BarChart]
 */
private val MinChartValue = HorizontalAlignmentLine(merger = { old, new ->
    max(old, new)
})

예제를 만드는 사용자 정의 정렬 선은 자식을 세로로 정렬하는 데 사용되므로 HorizontalAlignmentLine 유형입니다. 여러 레이아웃에서 이러한 정렬선에 대한 값을 제공하는 경우 병합 정책이 매개변수로 전달됩니다. Compose 레이아웃 시스템 좌표와 캔버스 좌표는 [0, 0]을 나타내므로 왼쪽 상단 모서리와 x축 및 y축은 아래쪽으로 양수이므로 MaxChartValue 값은 항상 MinChartValue보다 작아집니다. 따라서 병합 정책은 최대 차트 데이터 값 기준선의 경우 최소이고 최소 차트 데이터 값 기준선의 경우 최대입니다.
사용자 지정 레이아웃 또는 레이아웃 수정자를 만들 때, 사용자 지정 정렬선을 alignmentLines를 받는 측정범위.레이아웃 메서드에서 지정합니다: Map<AlignmentLine, Int> 매개 변수를 사용합니다.

@Composable
private fun BarChart(
    dataPoints: List<Int>,
    modifier: Modifier = Modifier,
) {
    val maxValue: Float = remember(dataPoints) { dataPoints.maxOrNull()!! * 1.2f }

    BoxWithConstraints(modifier = modifier) {
        val density = LocalDensity.current
        with(density) {
            // ...
            // Calculate baselines
            val maxYBaseline = // ...
            val minYBaseline = // ...
            Layout(
                content = {},
                modifier = Modifier.drawBehind {
                    // ...
                }
            ) { _, constraints ->
                with(constraints) {
                    layout(
                        width = if (hasBoundedWidth) maxWidth else minWidth,
                        height = if (hasBoundedHeight) maxHeight else minHeight,
                        // Custom AlignmentLines are set here. These are propagated
                        // to direct and indirect parent composables.
                        alignmentLines = mapOf(
                            MinChartValue to minYBaseline.roundToInt(),
                            MaxChartValue to maxYBaseline.roundToInt()
                        )
                    ) {}
                }
            }
        }
    }
}

이 컴포저블의 직접 및 간접 부모는 정렬선을 사용할 수 있습니다. 다음 컴포저블은 두 개의 텍스트 슬롯과 데이터 포인트를 매개변수로 사용하여 두 텍스트를 최대 및 최소 차트 데이터 값에 정렬하는 사용자 정의 레이아웃을 생성합니다. 

@Composable
private fun BarChartMinMax(
    dataPoints: List<Int>,
    maxText: @Composable () -> Unit,
    minText: @Composable () -> Unit,
    modifier: Modifier = Modifier,
) {
    Layout(
        content = {
            maxText()
            minText()
            // Set a fixed size to make the example easier to follow
            BarChart(dataPoints, Modifier.size(200.dp))
        },
        modifier = modifier
    ) { measurables, constraints ->
        check(measurables.size == 3)
        val placeables = measurables.map {
            it.measure(constraints.copy(minWidth = 0, minHeight = 0))
        }

        val maxTextPlaceable = placeables[0]
        val minTextPlaceable = placeables[1]
        val barChartPlaceable = placeables[2]

        // Obtain the alignment lines from BarChart to position the Text
        val minValueBaseline = barChartPlaceable[MinChartValue]
        val maxValueBaseline = barChartPlaceable[MaxChartValue]
        layout(constraints.maxWidth, constraints.maxHeight) {
            maxTextPlaceable.placeRelative(
                x = 0,
                y = maxValueBaseline - (maxTextPlaceable.height / 2)
            )
            minTextPlaceable.placeRelative(
                x = 0,
                y = minValueBaseline - (minTextPlaceable.height / 2)
            )
            barChartPlaceable.placeRelative(
                x = max(maxTextPlaceable.width, minTextPlaceable.width) + 20,
                y = 0
            )
        }
    }
}
@Preview
@Composable
private fun ChartDataPreview() {
    MaterialTheme {
        BarChartMinMax(
            dataPoints = listOf(4, 24, 15),
            maxText = { Text("Max") },
            minText = { Text("Min") },
            modifier = Modifier.padding(24.dp)
        )
    }
}

'Android > Compose Docs' 카테고리의 다른 글

Compose Docs | ConstraintLayout  (0) 2023.09.06
Compose Docs | Instrinsic measurements  (0) 2023.09.05
Compose Docs | Build adaptive layouts  (0) 2023.08.28
Compose Docs | Custom layouts  (0) 2023.08.26
Compose Docs | Layout  (0) 2023.08.16