Özel düzenler

Compose'da kullanıcı arayüzü öğeleri, çağrıldığında bir kullanıcı arayüzü parçası yayan, daha sonra ekranda oluşturulan bir kullanıcı arayüzü ağacına eklenen composable işlevlerle temsil edilir. Her kullanıcı arayüzü öğesinin bir üst öğesi ve birçok alt öğesi vardır. Her öğe ayrıca, (x, y) konumu ve boyut olarak belirtilen (width ve height) üst öğesinin içinde yer alır.

Üst öğeler, alt öğeleri için kısıtlamaları tanımlar. Bu kısıtlamalar dahilinde bir öğeden boyutunu tanımlaması istenir. Kısıtlamalar, bir öğenin minimum ve maksimum width ve height değerlerini kısıtlar. Bir öğenin alt öğeleri varsa boyutunu belirlemeye yardımcı olmak için her bir alt öğeyi ölçebilir. Bir öğe kendi boyutunu belirleyip bildirdikten sonra, Özel düzen oluşturma bölümünde ayrıntılı olarak açıklandığı gibi, alt öğelerinin kendisine göre nasıl yerleştirileceğini tanımlayabilir.

Kullanıcı arayüzü ağacındaki her bir düğümü düzenlemek üç adımlı bir süreçtir. Her bir düğüm:

  1. Çocukları ölçün
  2. Kendi boyutuna karar verme
  3. Alt öğelerini yerleştir

Düğüm düzeninin üç adımı: alt öğeleri ölçme, boyuta karar verme, alt öğeleri yerleştirme

Kapsamların kullanımı, alt öğeleri ne zaman ölçebileceğinizi ve yerleştirebileceğinizi tanımlar. Düzen ölçümü, yalnızca ölçüm ve düzen geçişleri sırasında yapılabilir. Alt öğeler yalnızca düzen geçişleri sırasında (ve yalnızca ölçüldükten sonra) yerleştirilebilir. MeasureScope ve PlacementScope gibi Compose kapsamları nedeniyle bu, derleme sırasında uygulanır.

Düzen değiştiriciyi kullanma

Bir öğenin ölçülme ve düzenlenme şeklini değiştirmek için layout değiştiricisini kullanabilirsiniz. Layout bir lambdadır. Parametreleri, ölçebileceğiniz öğeyi, measurable olarak iletilen öğeyi ve bu composable'ın constraints olarak iletilen gelen kısıtlamalarını içerir. Özel bir düzen değiştirici şöyle görünebilir:

fun Modifier.customLayoutModifier() =
    layout { measurable, constraints ->
        // ...
    }

Ekranda bir Text gösterelim ve üstten ilk metin satırının temel çizgisine kadar olan mesafeyi kontrol edelim. paddingFromBaseline değiştiricisi tam olarak bu şekilde çalışıyor. Bunu bir örnek olarak burada uyguluyoruz. Bunun için composable'ı ekrana manuel olarak yerleştirmek üzere layout değiştiricisini kullanın. Text üst dolgusunun 24.dp olarak ayarlandığı istenen davranış aşağıdaki gibidir:

Öğeler arasındaki boşluğu belirleyen normal kullanıcı arayüzü dolgusu ile bir referans değerden diğerine boşluğu ayarlayan metin dolgusu arasındaki farkı gösterir

Bu boşluğu oluşturmak için gereken kodu aşağıda görebilirsiniz:

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

Bu kodda neler olduğu şöyledir:

  1. measurable lambda parametresinde, measurable.measure(constraints) yöntemini çağırarak ölçülebilir parametreyle temsil edilen Text değerini ölçersiniz.
  2. layout(width, height) yöntemini çağırarak composable'ın boyutunu belirtirsiniz. Bu yöntem, sarmalanmış öğeleri yerleştirmek için kullanılan bir lambda da sağlar. Bu örnekte, son referans değer ile eklenen üst dolgu arasındaki yüksekliktir.
  3. placeable.place(x, y) yöntemini çağırarak sarmalanmış öğeleri ekrana konumlandırabilirsiniz. Sarmalanmış öğeler yerleştirilmezse görünmez. ykonumu, üst dolguya, yani metnin ilk temel çizgisinin konumuna karşılık gelir.

Bunun beklendiği gibi çalıştığını doğrulamak için bu değiştiriciyi Text üzerinde kullanın:

@Preview
@Composable
fun TextWithPaddingToBaselinePreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
    }
}

@Preview
@Composable
fun TextWithNormalPaddingPreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.padding(top = 32.dp))
    }
}

Metin öğelerinin birden çok önizlemesi; biri öğeler arasındaki normal dolguyu, diğeri bir referans değerden diğerine dolgu gösterir

Özel düzenler oluşturun

layout değiştiricisi yalnızca çağrı composable'ı değiştirir. Birden fazla composable'ı ölçmek ve düzenlemek için bunun yerine Layout composable'ı kullanın. Bu composable, alt öğeleri manuel olarak ölçüp yerleştirmenizi sağlar. Column ve Row gibi tüm üst düzey düzenler, Layout composable ile oluşturulur.

Column öğesinin çok temel bir sürümünü oluşturalım. Çoğu özel düzen bu kalıbı kullanır:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // measure and position children given constraints logic here
        // ...
    }
}

layout değiştiricisine benzer şekilde measurables, ölçülmesi gereken alt öğelerin listesidir ve constraints, üst öğedeki kısıtlamalardır. Öncekiyle aynı mantığa göre, MyBasicColumn aşağıdaki gibi uygulanabilir:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each children
            measurable.measure(constraints)
        }

        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Track the y co-ord we have placed children up to
            var yPosition = 0

            // Place children in the parent layout
            placeables.forEach { placeable ->
                // Position item on the screen
                placeable.placeRelative(x = 0, y = yPosition)

                // Record the y co-ord placed up to
                yPosition += placeable.height
            }
        }
    }
}

Alt composable'lar Layout kısıtlamalarıyla (minHeight kısıtlamaları olmadan) sınırlandırılır ve önceki composable'ın yPosition değerine göre yerleştirilir.

Bu özel composable'ın kullanım şekli şöyledir:

@Composable
fun CallingComposable(modifier: Modifier = Modifier) {
    MyBasicColumn(modifier.padding(8.dp)) {
        Text("MyBasicColumn")
        Text("places items")
        Text("vertically.")
        Text("We've done it by hand!")
    }
}

Bir sütunda bir sonrakinin üst tarafına yığılmış çeşitli metin öğeleri.

Düzen yönü

LocalLayoutDirection bileşimini yerel olarak değiştirerek bir composable'ın düzen yönünü değiştirin.

composable'ları ekrana manuel olarak yerleştiriyorsanız LayoutDirection, layout değiştiricisinin veya Layout composable'ının LayoutScope öğesinin bir parçasıdır.

layoutDirection kullanırken place ile composable'ı yerleştirin. place, placeRelative yönteminden farklı olarak düzen yönüne (soldan sağa veya sağdan sola) göre değişmez.

Özel düzenlerin işleyiş şekli

Oluşturma'daki temel düzenler bölümünden düzenler ve değiştiriciler hakkında daha fazla bilgi edinebilir ve Özel düzenler oluşturan örnekler oluşturma bölümünde özel düzenlerin işleyiş şeklini görebilirsiniz.

Daha fazla bilgi

Compose'daki özel düzenler hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara bakın.

Videolar