Düzen oluşturma modeli, AlignmentLine
'i kullanarak alt yerleşimleri hizalamak ve konumlandırmak için üst düzenler tarafından kullanılabilecek özel hizalama satırları oluşturabilirsiniz. Örneğin Row
, alt öğelerini hizalamak için alt çizgilerin özel hizalama çizgilerini kullanabilir.
Bir düzen, belirli bir AlignmentLine
için bir değer sağladığında, düzenin ebeveynleri bu değeri, ilgili Placeable
örneğindeki Placeable.get
operatörünü kullanarak ölçümden sonra okuyabilir.
Daha sonra, AlignmentLine
, pozisyona göre çocukların konumuna karar verebilir.
Oluştur'daki bazı besteler zaten hizalama çizgileriyle gelir. Örneğin, BasicText
kombinasyonu FirstBaseline
ve LastBaseline
hizalama satırlarını gösterir.
Aşağıdaki örnekte, firstBaselineToTop
adlı özel LayoutModifier
, ilk satırdan başlayarak Text
öğesine dolgu eklemek için FirstBaseline
metnini okur.
Şekil 1. Bir öğeye normal dolgu ekleme ile bir Metin öğesinin referansına dolgu uygulama arasındaki farkı gösterir.
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)) } }
Örnekteki FirstBaseline
öğesini okumak için ölçüm aşamasında placeable [FirstBaseline]
kullanılır.
Özel hizalama çizgileri oluşturun
Özel bir Layout
veya özel LayoutModifier
oluştururken özel hizalama satırları sağlayabilirsiniz. Böylece diğer üst öğeler, alt öğelerini uygun şekilde hizalamak ve konumlandırmak için kullanabilir.
Aşağıdaki örnekte, MaxChartValue
ve MinChartValue
olmak üzere iki hizalama çizgisi gösteren özel bir BarChart
bileşimi gösterilmektedir. Böylece diğer besteler, grafiğin maksimum ve minimum veri değerine hizalanabilir. Max ve Min olmak üzere iki metin öğesi, özel hizalama çizgilerinin ortasına hizalandı.
Şekil 2. BarChart
maksimum ve minimum veri değerine hizalı metinle birleştirilebilir.
Özel hizalama satırları, projenizdeki üst düzey değişkenler olarak tanımlanır.
/** * 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) })
Örneğimizi oluşturmak için özel hizalama çizgileri HorizontalAlignmentLine
türündedir. Çocukların dikey olarak hizalanması için kullanılır. Birden fazla düzenin bu hizalama satırları için bir değer sağlaması durumunda, bir birleştirme politikası parametre olarak iletilir. Yazma düzeni sistem koordinatları ve Canvas
koordinatları [0, 0]
değerini temsil ettiğinden sol üst köşe ile x
ve y
ekseni aşağı doğrudur. Bu nedenle MaxChartValue
değeri her zaman MinChartValue
değerinden küçük olur. Bu nedenle, birleştirme politikası maksimum grafik veri değeri referans değeri için min
ve minimum grafik veri değeri referans değeri için max
'dir.
Özel bir Layout
veya LayoutModifier
oluştururken MeasureScope.layout
yönteminde bir alignmentLines: Map<AlignmentLine, Int>
parametresi alan özel hizalama satırları belirtin.
@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() ) ) {} } } } } }
Bu bestenin doğrudan ve dolaylı ebeveynleri hizalama çizgilerini tüketebilir. Aşağıdaki oluşturulabilir, iki Text
slotu ve veri noktası parametresi olarak alan ve iki metni maksimum ve minimum grafik veri değerlerine uygun hale getiren özel bir düzen oluşturur. Bu bestenin önizlemesi, Şekil 2'de gösterilmiştir.
@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) ) } }