Compose 레이아웃 모델을 사용하면 AlignmentLine
을 사용하여 맞춤 정렬 선을 만들 수 있습니다. 이 맞춤 정렬 선은 하위 요소를 정렬하고 위치를 지정할 때 상위 요소 레이아웃에 사용할 수 있습니다. 예를 들어 Row
는 하위 요소의 맞춤 정렬 선을 사용하여 하위 요소를 정렬할 수 있습니다.
레이아웃에서 특정 AlignmentLine
값을 제공하는 경우 레이아웃의 상위 요소는 대응하는 Placeable
인스턴스에 Placeable.get
연산자를 사용하여 이 값을 측정 후 읽어올 수 있습니다.
그러면 AlignmentLine
의 위치에 따라 상위 요소는 하위 요소의 위치 지정을 결정할 수 있습니다.
Compose의 일부 컴포저블에는 이미 정렬 선이 함께 제공됩니다. 예를 들어 BasicText
컴포저블은 FirstBaseline
및 LastBaseline
정렬 선을 노출합니다.
아래 예에서 firstBaselineToTop
이라는 맞춤 LayoutModifier
는 FirstBaseline
을 읽고 첫 번째 기준부터 시작하여 텍스트에 Text
를 추가합니다.
그림 1. 요소에 일반 패딩을 추가하는 것과 텍스트 요소의 기준에 패딩을 적용하는 것의 차이를 보여줌.
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
을 읽기 위해 측정 단계에서 placeable [FirstBaseline]
이 사용되었습니다.
맞춤 정렬 선 만들기
맞춤 Layout
컴포저블 또는 맞춤 LayoutModifier
를 만들 때 맞춤 정렬 선을 제공할 수 있습니다. 그러면 다른 상위 컴포저블이 그 정렬 선을 사용하여 그에 따라 하위 요소를 정렬하고 위치를 지정할 수 있습니다.
다음 예에서는 다른 컴포저블을 차트의 최대 및 최소 데이터 값에 정렬할 수 있도록 두 개의 정렬 선 MaxChartValue
와 MinChartValue
를 노출하는 맞춤 BarChart
컴포저블을 보여줍니다. 두 개의 텍스트 요소 Max와 Min이 맞춤 정렬 선의 가운데에 정렬되었습니다.
그림 2. 텍스트가 최대 및 최소 데이터 값에 정렬된 BarChart
컴포저블
맞춤 정렬 선은 프로젝트에서 최상위 수준의 변수로 정의됩니다.
/** * 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 레이아웃 시스템 좌표와 Canvas
좌표가 [0, 0]
을 나타내내므로 왼쪽 상단과 x
및 y
축은 아래쪽으로 양수이므로 MaxChartValue
값은 항상 MinChartValue
보다 작습니다. 따라서 병합 정책은 최대 차트 데이터 값 기준에는 min
이고, 최소 차트 데이터 값 기준에는 max
입니다.
맞춤 Layout
또는 LayoutModifier
를 만들 때, alignmentLines: Map<AlignmentLine, Int>
매개변수를 취하는 MeasureScope.layout
메서드에 맞춤 정렬 선을 지정합니다.
@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() ) ) {} } } } } }
이 컴포저블의 직접 및 간접 상위 요소는 정렬 선을 사용할 수 있습니다. 다음 컴포저블은 두 개의 Text
슬롯과 데이터 포인트를 매개변수로 취하는 맞춤 레이아웃을 만들고, 두 텍스트를 최대 및 최소 차트 데이터 값에 정렬합니다. 이 컴포저블의 미리보기는 그림 2와 같습니다.
@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) ) } }
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- Compose의 그래픽
- 맞춤 레이아웃{:#custom-layouts }
- Compose 레이아웃의 내장 기능 측정