Özel düzenler

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

Üst öğeler, alt öğeleri için kısıtlamaları tanımlar. Bir öğeden bu kısıtlamalar dahilinde boyutunu tanımlaması istenir. Sınırlamalar, bir öğenin minimum ve maksimum width ve height değerlerini kısıtlar. Bir öğenin alt öğeleri varsa boyutunun belirlenmesine yardımcı olmak 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 öğelerinin kendisine göre nasıl yerleştirileceğini tanımlama fırsatına sahip olur.

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ştir

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

Kapsamların kullanımı, alt öğelerinizi ne zaman ölçebileceğinizi ve yerleştirebileceğinizi tanımlar. Bir düzen ölçümü yalnızca ölçüm ve düzen geçişi sırasında yapılabilir. Bir alt öğe yalnızca düzen geçişi sırasında (yalnızca ölçüldükten sonra) yerleştirilebilir. MeasureScope ve PlacementScope gibi Compose kapsamları nedeniyle bu işlem, 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. Parametreler, ölçebileceğiniz öğeyi measurable olarak iletir ve bu composable'ın gelen kısıtlamalarını (constraints olarak iletilir) içerir. Özel bir düzen değiştiricisi şöyle görünebilir:

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

Ekranda bir Text gösterelim ve metnin ilk satırının üstten referans çizgisine olan mesafeyi kontrol edelim. paddingFromBaseline değiştiricisinin yaptığı tam olarak budur. Biz bunu örnek olarak uyguluyoruz. Bunun için layout değiştiricisini kullanarak composable'ı ekrana manuel olarak yerleştirin. Text üst dolgusu 24.dp olarak ayarlandığında istenen davranış şöyledir:

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

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

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 aşağıda açıklanmıştır:

  1. measurable lambda parametresinde, ölçülebilir parametreyle temsil edilen Text değerini measurable.measure(constraints) çağırarak ölçersiniz.
  2. composable'ın boyutunu, layout(width, height) yöntemini çağırarak belirtirsiniz. Bu yöntem, sarmalanmış öğeleri yerleştirmek için kullanılan bir lambda da verir. Bu durumda, son referans çizgisi ile eklenen üst dolgu arasındaki yüksekliktir.
  3. placeable.place(x, y) yöntemini çağırarak ekrandaki sarmalanmış öğeleri konumlandırırsınız. Sarmalanan öğeler yerleştirilmezse görünmezler. y konumu, üst dolguya, yani metnin ilk referansının konumuna karşılık gelir.

Bunun beklendiği gibi çalıştığını doğrulamak için şu 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 çok önizlemesi; biri öğeler arasındaki normal dolguyu, diğeri ise bir referans değerden diğerine dolguyu gösterir

Özel düzenler oluşturma

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, çocukları manuel olarak ölçmenizi ve düzenlemenizi sağlar. Column ve Row gibi tüm üst düzey düzenler Layout composable ile oluşturulmuştur.

Şimdi Column öğesinin çok temel bir sürümünü oluşturalım. Ç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. constraints ise üst öğeden gelen kısıtlamalardır. MyBasicColumn, önceki mantıkla ş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) kısıtlanır ve önceki composable'ın yPosition parametresine göre yerleştirilir.

Özel composable'ın nasıl kullanılacağı aşağıda açıklanmıştır:

@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 üzerine yığılmış birkaç metin öğesi.

Düzen yönü

LocalLayoutDirection bestesini yerel değiştirerek composable'ın düzen yönünü değiştirin.

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

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

Özel düzenler çalışırken

Oluşturma penceresindeki temel düzenler bölümünde düzenler ve değiştiriciler hakkında daha fazla bilgi edinebilir, Özel düzenler oluşturan örnekler oluşturma bölümünde özel düzenleri uygulamalı olarak görebilirsiniz.

Daha fazla bilgi

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

Videolar