Compose'da akış düzenleri

FlowRow ve FlowColumn, Row ve Column bileşenlerine benzer ancak kapsayıcıda yer kalmadığında öğelerin bir sonraki satıra geçmesi bakımından farklılık gösterir. Bu işlem birden fazla satır veya sütun oluşturur. Bir satırdaki öğe sayısı, maxItemsInEachRow veya maxItemsInEachColumn ayarlanarak da kontrol edilebilir. Duyarlı düzenler oluşturmak için genellikle FlowRow ve FlowColumn kullanabilirsiniz. Öğeler bir boyut için çok büyükse içerik kesilmez. maxItemsInEach* ile Modifier.weight(weight) kombinasyonunu kullanmak, gerektiğinde bir satır veya sütunun genişliğini dolduran/genişleten düzenler oluşturmanıza yardımcı olabilir.

Çip veya filtreleme kullanıcı arayüzü için tipik örnek:

FlowRow'da 5 çip, yer kalmadığında bir sonraki satıra taşmayı gösterir.
Şekil 1. FlowRow örneği

Temel kullanım

FlowRow veya FlowColumn kullanmak için bu composable'ları oluşturun ve standart akışı izlemesi gereken öğeleri içine yerleştirin:

@Composable
private fun FlowRowSimpleUsageExample() {
    FlowRow(modifier = Modifier.padding(8.dp)) {
        ChipItem("Price: High to Low")
        ChipItem("Avg rating: 4+")
        ChipItem("Free breakfast")
        ChipItem("Free cancellation")
        ChipItem("£50 pn")
    }
}

Bu snippet, yukarıda gösterilen kullanıcı arayüzüyle sonuçlanır. İlk satırda yer kalmadığında öğeler otomatik olarak bir sonraki satıra geçer.

Akış düzeninin özellikleri

Akış düzenleri, uygulamanızda farklı düzenler oluşturmak için kullanabileceğiniz aşağıdaki özelliklere sahiptir.

Ana eksen düzeni: yatay veya dikey düzen

Ana eksen, öğelerin yerleştirildiği eksendir (örneğin, FlowRow öğesinde öğeler yatay olarak düzenlenir). FlowRow içindeki horizontalArrangement parametresi, boş alanın öğeler arasında nasıl dağıtılacağını kontrol eder.

Aşağıdaki tabloda, FlowRow için öğelerde horizontalArrangement ayarının örnekleri gösterilmektedir:

Yatay düzenleme FlowRow olarak ayarlandı

Sonuç

Arrangement.Start (Default)

Öğeler başlangıçta düzenlendi

Arrangement.SpaceBetween

Öğeler aralarında boşluk olacak şekilde düzenlenir.

Arrangement.Center

Öğeler ortada düzenlenmiş

Arrangement.End

Öğeler sonda düzenlenir

Arrangement.SpaceAround

Öğeler, etraflarında boşluk olacak şekilde düzenlenmiş.

Arrangement.spacedBy(8.dp)

Öğeler belirli bir dp ile aralıklı yerleştirilir

FlowColumn için verticalArrangement ile benzer seçenekler kullanılabilir. Varsayılan değer Arrangement.Top şeklindedir.

Çapraz eksen düzeni

Çapraz eksen, ana eksenin tersi yöndeki eksendir. Örneğin, FlowRow dilinde bu dikey eksendir. Kapsayıcı içindeki tüm içeriklerin çapraz eksende nasıl düzenleneceğini değiştirmek için FlowRow yerine verticalArrangement, FlowColumn yerine horizontalArrangement kullanın.

FlowRow için aşağıdaki tabloda, öğelerde farklı verticalArrangement ayarlama örnekleri gösterilmektedir:

FlowRow için dikey düzenleme ayarlandı

Sonuç

Arrangement.Top (Default)

Kapsayıcı üst düzenlemesi

Arrangement.Bottom

Kapsayıcı alt düzenlemesi

Arrangement.Center

Kapsayıcıyı ortalama düzeni

FlowColumn için horizontalArrangement ile benzer seçenekler mevcuttur. Varsayılan çapraz eksen düzenlemesi Arrangement.Start şeklindedir.

Bağımsız öğe hizalama

Satırdaki öğeleri farklı hizalamalarla konumlandırmak isteyebilirsiniz. Bu, verticalArrangement ve horizontalArrangement değerlerinden farklıdır çünkü öğeleri mevcut satır içinde hizalar. Bunu Modifier.align() ile uygulayabilirsiniz.

Örneğin, bir FlowRow içindeki öğelerin yükseklikleri farklı olduğunda satır, en büyük öğenin yüksekliğini alır ve öğelere Modifier.align(alignmentOption) uygular:

Dikey hizalama FlowRow olarak ayarlandı

Sonuç

Alignment.Top (Default)

Öğeler üst tarafa hizalandı

Alignment.Bottom

Öğeler alt tarafa hizalandı

Alignment.CenterVertically

Öğeler ortaya hizalanır.

FlowColumn için benzer seçenekler mevcuttur. Varsayılan hizalama Alignment.Start şeklindedir.

Satır veya sütundaki maksimum öğe sayısı

maxItemsInEachRow veya maxItemsInEachColumn parametreleri, bir sonraki satıra geçmeden önce ana eksende izin verilecek maksimum öğe sayısını tanımlar. Varsayılan değer Int.MAX_INT olup boyutları satıra sığdığı sürece mümkün olduğunca çok öğeye izin verir.

Örneğin, maxItemsInEachRow ayarı, ilk düzende yalnızca 3 öğe olmasını zorunlu kılar:

Maksimum değer ayarlanmadı

maxItemsInEachRow = 3

Akış satırında maksimum değer ayarlanmadı Akış satırında maksimum öğe sayısı ayarlandı

Öğe ağırlıkları

Ağırlık, bir öğeyi faktörüne ve yerleştirildiği satırdaki kullanılabilir alana göre büyütür. Önemli bir nokta olarak, bir öğenin genişliğini hesaplamak için ağırlıkların kullanılma şekli açısından FlowRow ile Row arasında bir fark vardır. Rows için ağırlık, Row içindeki tüm öğelere göre belirlenir. FlowRow ile ağırlık, FlowRow kapsayıcısındaki tüm öğelere değil, öğenin yerleştirildiği satırdaki öğelere göre belirlenir.

Örneğin, bir çizgi üzerinde her biri farklı ağırlıklara (1f, 2f, 1f ve 3f) sahip 4 öğeniz varsa toplam ağırlık 7f olur. Bir satır veya sütundaki kalan alan 7f ile bölünür. Ardından, her bir öğenin genişliği şu formülle hesaplanır: weight * (remainingSpace / totalWeight).

Izgara benzeri bir düzen oluşturmak için Modifier.weight ve maksimum öğe sayısını FlowRow veya FlowColumn ile birlikte kullanabilirsiniz. Bu yaklaşım, cihazınızın boyutuna göre ayarlanan duyarlı düzenler oluşturmak için kullanışlıdır.

Ağırlıkları kullanarak elde edebileceğiniz sonuçlara dair birkaç farklı örnek aşağıda verilmiştir. Öğelerin eşit boyutta olduğu bir ızgara buna örnek gösterilebilir:

Akış satırıyla oluşturulan ızgara
Şekil 2. Izgara oluşturmak için FlowRow kullanma

Eşit öğe boyutlarına sahip bir tablo oluşturmak için aşağıdakileri yapabilirsiniz:

val rows = 3
val columns = 3
FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = rows
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .weight(1f)
        .clip(RoundedCornerShape(8.dp))
        .background(MaterialColors.Blue200)
    repeat(rows * columns) {
        Spacer(modifier = itemModifier)
    }
}

Önemli bir nokta: Başka bir öğe ekleyip bunu 9 yerine 10 kez tekrarlarsanız son öğe, tüm satırın toplam ağırlığı 1f olduğundan son sütunun tamamını kaplar:

Son öğe, ızgarada tam boyutlu gösterilir
Şekil 3. Son öğenin tam genişliği kapladığı bir tablo oluşturmak için FlowRow kullanma

Ağırlıkları, Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) veya Modifier.fillMaxWidth(fraction) gibi diğer Modifiers ile birleştirebilirsiniz. Bu değiştiricilerin tümü, FlowRow (veya FlowColumn) içindeki öğelerin duyarlı boyutlandırılmasına olanak tanımak için birlikte çalışır.

Ayrıca, iki öğenin her birinin genişliğin yarısını, bir öğenin ise sonraki sütunun tam genişliğini kapladığı, farklı öğe boyutlarından oluşan dönüşümlü bir tablo da oluşturabilirsiniz:

Akış satırı içeren alternatif ızgara
Şekil 4. FlowRow (farklı boyutlarda satırlar)

Bunu aşağıdaki kodla yapabilirsiniz:

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 2
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .clip(RoundedCornerShape(8.dp))
        .background(Color.Blue)
    repeat(6) { item ->
        // if the item is the third item, don't use weight modifier, but rather fillMaxWidth
        if ((item + 1) % 3 == 0) {
            Spacer(modifier = itemModifier.fillMaxWidth())
        } else {
            Spacer(modifier = itemModifier.weight(0.5f))
        }
    }
}

Kesirli boyutlandırma

Modifier.fillMaxWidth(fraction) özelliğini kullanarak bir öğenin kaplaması gereken kapsayıcının boyutunu belirtebilirsiniz. Bu, Modifier.fillMaxWidth(fraction) özelliğinin Row veya Column için geçerli olan işleyiş şeklinden farklıdır. Row/Column öğeleri, kapsayıcı genişliğinin tamamını değil, kalan genişliğin bir yüzdesini kaplar.

Örneğin, aşağıdaki kod FlowRow ve Row kullanıldığında farklı sonuçlar verir:

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 3
) {
    val itemModifier = Modifier
        .clip(RoundedCornerShape(8.dp))
    Box(
        modifier = itemModifier
            .height(200.dp)
            .width(60.dp)
            .background(Color.Red)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .fillMaxWidth(0.7f)
            .background(Color.Blue)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .weight(1f)
            .background(Color.Magenta)
    )
}

FlowRow: Tüm kapsayıcı genişliğinin 0,7 kesirli orta öğesi.

Akış satırıyla kesirli genişlik

Row: Ortadaki öğe, kalan Row genişliğin yüzde 0,7'sini kaplıyor.

Satırla birlikte kesirli genişlik

fillMaxColumnWidth() ve fillMaxRowHeight()

FlowColumn veya FlowRow içindeki bir öğeye Modifier.fillMaxColumnWidth() ya da Modifier.fillMaxRowHeight() uygulandığında, aynı sütun veya satırdaki öğelerin sütun/satırdaki en büyük öğeyle aynı genişliği ya da yüksekliği kaplaması sağlanır.

Örneğin, bu örnekte Android tatlılarının listesini görüntülemek için FlowColumn kullanılmıştır. Öğelere Modifier.fillMaxColumnWidth() uygulandığında ve uygulanmadığında her öğenin genişliğindeki farkı görebilirsiniz.

FlowColumn(
    Modifier
        .padding(20.dp)
        .fillMaxHeight()
        .fillMaxWidth(),
    horizontalArrangement = Arrangement.spacedBy(8.dp),
    verticalArrangement = Arrangement.spacedBy(8.dp),
    maxItemsInEachColumn = 5,
) {
    repeat(listDesserts.size) {
        Box(
            Modifier
                .fillMaxColumnWidth()
                .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp))
                .padding(8.dp)
        ) {

            Text(
                text = listDesserts[it],
                fontSize = 18.sp,
                modifier = Modifier.padding(3.dp)
            )
        }
    }
}

Her öğeye Modifier.fillMaxColumnWidth() uygulandı

fillMaxColumnWidth

Genişlik değişikliği ayarlanmadı (öğeler sarmalanıyor)

Maksimum sütun genişliği doldurma ayarlanmadı