Jetpack Compose'da hizalama çizgileri

Oluştur düzen modeli, AlignmentLine ile özel öğeler oluşturmanızı sağlar üst düzenlerin yerleşimlerini hizalayıp konumlandırmak için kullanabileceği hizalama çizgileri Örneğin, Row hizalamak için alt öğelerin özel hizalama çizgilerini kullanabilir.

Bir düzen belirli bir AlignmentLine için değer sağladığında, düzenin ebeveynler, Placeable.get kullanarak ölçümden sonra bu değeri okuyabilir operatörümüzün Placeable örneği. AlignmentLine adlı cihazın konumuna bağlı olarak ebeveynler şunları yapabilir: ardından çocukların yerine nasıl karar verilir?

Compose'daki bazı composable'lar zaten hizalama satırlarıyla birlikte gelir. Örneğin, BasicText composable, FirstBaseline ve LastBaseline hizalama satırlarını ortaya çıkarır.

Aşağıdaki örnekte, özel bir LayoutModifier firstBaselineToTop, Text öğesine dolgu eklemek için FirstBaseline öğesini okur başlangıçtaki temel değerden başlayarak.

Şekil 1. Bir öğeye normal dolgu ekleme arasındaki farkı gösterir. ve bir Metin öğesinin temel çizgisine dolgu uygulanır.

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 bölümünü okumak için, Ölçüm aşamasında placeable [FirstBaseline] kullanılır.

Özel hizalama çizgileri oluşturma

Özel bir Layout oluştururken doğrudan Google Analytics composable'dan composable veya özel bir LayoutModifier diğer üst composable'ların bunları hizalamak için kullanabilmesi için özel hizalama satırları uygun şekilde konumlandırmaktır.

Aşağıdaki örnekte iki farklı öğe oluşturan özel bir BarChart composable, MaxChartValue ve MinChartValue hizalama çizgilerini gösterir. Böylece diğer composable'lar aynı olmalıdır. İki metin Maks ve Min öğeleri, özel grubun ortasına hizalandı. çizgilerini çizin.

Şekil 2. BarChart composable, metin maksimum hizalı ve minimum veri değeridir.

Özel hizalama çizgileri 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 kullanılacak özel hizalama çizgileri şu türdedir: HorizontalAlignmentLine, olduğu gibi alt öğeleri dikey olarak hizalamak için kullanılırlar. Birleştirme politikası parametresini kullanabilirsiniz. Farklı Oluştur düzen sistem koordinatları ve Canvas koordinatlar [0, 0], sol üst köşeyi ve x ile y eksenini temsil eder aşağıya doğru inceleyebilirsiniz. Bu nedenle, MaxChartValue değeri her zaman şundan küçük olacaktır: MinChartValue. Bu nedenle birleşme politikası, maksimum grafik için min veri değeri referans değeri ve minimum grafik veri değeri temel çizgisi için max.

Özel Layout veya LayoutModifier oluştururken özel hizalamayı belirtin MeasureScope.layout içindeki satırlar alignmentLines: Map<AlignmentLine, Int> gerekir. parametresinden sonra bir değer girin.

@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 composable'ın doğrudan ve dolaylı üst öğeleri, hizalamayı tüketebilir çizgi şeklinde görünür. Aşağıdaki composable'ın oluşturduğu özel bir düzen parametre iki Text alanlarını ve veri noktalarını kullanır ve iki metni reklam ile hizalar hem maksimum hem de minimum grafik verisi değerleridir. Bu composable'ın önizlemesi: gösterilmektedir.

@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)
        )
    }
}

ziyaret edin.