Özel düzenler

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

Ebeveynler, alt öğeleri için kısıtlamaları tanımlar. Öğeden, bu kısıtlamalar dahilinde boyutunu tanımlaması istenir. Kısıtlamalar, bir öğenin minimum ve maksimum width ve height değerlerini sınırlar. Bir öğenin alt öğeleri varsa boyutunu belirlemek için her bir alt öğeyi ölçebilir. Bir öğe kendi boyutunu belirleyip bildirdikten sonra, Özel düzenler oluşturma bölümünde ayrıntılı olarak açıklandığı gibi, alt öğelerini kendisine göre nasıl yerleştireceğini tanımlama fırsatı elde eder.

Kullanıcı arayüzü ağacındaki her bir düğümü düzenlemek üç adımlı bir işlemdir. Her düğüm:

  1. Çocukları ölçme
  2. Kendi boyutuna karar verme
  3. Alt öğelerini yerleştirme
Düğüm düzeninin üç adımı: alt öğeleri ölçme, boyuta karar verme, alt öğeleri yerleştirme
Şekil 1. Düğüm düzeninin üç adımı, alt öğeleri ölçmek, boyuta karar vermek ve alt öğeleri yerleştirmektir.

Kapsamların kullanımı, çocuklarınızı ne zaman ölçebileceğinizi ve yerleştirebileceğinizi tanımlar. Düzen ölçümü yalnızca ölçüm ve düzen aşamalarında yapılabilir. Alt öğeler ise yalnızca düzen aşamalarında (ve yalnızca ölçüldükten sonra) yerleştirilebilir. MeasureScope ve PlacementScope gibi Compose kapsamları nedeniyle bu, derleme süresinde zorunlu kılınır.

Düzen değiştiriciyi kullanma

Bir öğenin nasıl ölçüleceğini ve düzenleneceğini değiştirmek için layout değiştiricisini kullanabilirsiniz. Layout bir lambda'dır. Parametreleri arasında, measurable olarak iletilen ölçebileceğiniz öğe ve constraints olarak iletilen bu composable'ın gelen kısıtlamaları yer alır. Özel düzen değiştirici şu şekilde görünebilir:

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

Ekranda bir Text gösterir ve üst kısımdan ilk metin satırının taban çizgisine olan mesafeyi kontrol eder. paddingFromBaseline değiştiricisi tam olarak bunu yapar. Burada örnek olarak uyguluyorsunuz. Bunu yapmak için layout değiştiricisini kullanarak composable'ı ekrana manuel olarak yerleştirin. Üst dolgunun 24.dp olarak ayarlandığı Text için sonuç davranışı şu şekildedir:

Öğeler arasındaki boşluğu ayarlayan normal kullanıcı arayüzü dolgusu ile bir taban çizgisinden diğerine olan boşluğu ayarlayan metin dolgusu arasındaki farkı gösterir.
Şekil 2. paddingFromBaseline içeren metin uygulandı.

Bu boşluğu oluşturmak için gereken kod:

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 şunlar gerçekleşir:

  1. measurable lambda parametresinde, ölçülebilir parametreyle temsil edilen Text değerini measurable.measure(constraints) işlevini çağırarak ö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 durumda, son taban çizgisi ile eklenen üst dolgu arasındaki yüksekliktir.
  3. Sarmalanmış öğeleri ekrana yerleştirmek için placeable.place(x, y) işlevini çağırırsınız. Sarmalanmış öğeler yerleştirilmezse görünür olmaz. y konumu, üst dolguya karşılık gelir: metnin ilk taban çizgisinin konumu.

Bu özelliğin beklendiği gibi çalıştığını doğrulamak için bu değiştiriciyi bir 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 fazla önizlemesi; birinde öğeler arasındaki normal dolgu, diğerinde ise bir taban çizgisinden diğerine olan dolgu gösteriliyor.
3.şekil Değiştirici, Text composable'ına uygulanır ve önizlenir.

Özel düzenler oluşturma

layout değiştiricisi yalnızca çağrılan composable'ı değiştirir. Birden fazla composable'ı ölçmek ve düzenlemek için Layout composable'ını kullanın. Bu composable, alt öğeleri manuel olarak ölçmenize ve düzenlemenize olanak tanır. Column ve Row gibi tüm üst düzey düzenler Layout composable ile oluşturulur.

Bu örnekte, Column uygulamasının çok basit bir sürümü oluşturulur. Çoğu özel düzen şu kalıbı izler:

@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 öğeden gelen kısıtlamalardır. Öncekiyle aynı mantığı kullanarak MyBasicColumn şu şekilde 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 nasıl kullanılacağı aşağıda gösterilmiştir:

@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 üst üste yerleştirilmiş birkaç metin öğesi.
Şekil 4. Özel Column uygulaması.

Düzen yönü

LocalLayoutDirection yerel bileşenini 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 bileşenleri place kullanarak yerleştirin. placeRelative yönteminin aksine place, düzen yönüne (soldan sağa veya sağdan sola) göre değişmez.

Özel düzenler iş başında

Compose'da temel düzenler bölümünde düzenler ve değiştiriciler hakkında daha fazla bilgi edinin ve Özel düzenler oluşturan Compose örnekleri bölümünde özel düzenlerin nasıl kullanıldığını inceleyin.

Daha fazla bilgi

Compose'da özel düzenler hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynakları inceleyin.

Videolar