Oluşturma değiştiriciler

Değiştiriciler, bir bileşeni süslemenize veya geliştirmenize olanak tanır. Değiştiriciler aşağıdaki gibi işlemleri yapmanıza olanak tanır:

  • Bileşenin boyutunu, düzenini, davranışını ve görünümünü değiştirme
  • Erişilebilirlik etiketleri gibi bilgiler ekleme
  • Kullanıcı girişini işle
  • Bir öğeyi tıklanabilir, kaydırılabilir, sürüklenebilir veya yakınlaştırılabilir hale getirme gibi üst düzey etkileşimler ekleyin

Değiştiriciler, standart Kotlin nesneleridir. Modifier sınıfı işlevlerinden birini çağırarak bir düzenleyici oluşturun:

@Composable
private fun Greeting(name: String) {
    Column(modifier = Modifier.padding(24.dp)) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

Renkli bir arka plan üzerinde, metnin etrafında boşluk bırakılmış iki satırlık metin.

Bu işlevleri birleştirerek oluşturabilirsiniz:

@Composable
private fun Greeting(name: String) {
    Column(
        modifier = Modifier
            .padding(24.dp)
            .fillMaxWidth()
    ) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

Metnin arkasındaki renkli arka plan artık cihazın tüm genişliğini kaplıyor.

Yukarıdaki kodda, farklı değiştirici işlevlerinin birlikte kullanıldığına dikkat edin.

  • padding, bir öğenin etrafına boşluk ekler.
  • fillMaxWidth, composable'ın, üst öğesinden verilen maksimum genişliği doldurmasını sağlar.

Kompozit öğelerinizin tümünün bir modifier parametresi kabul etmesi ve bu değiştiriciyi kullanıcı arayüzü yayınlayan ilk alt öğesine iletmesi en iyi uygulamadır. Bu, kodunuzu daha yeniden kullanılabilir hale getirir ve davranışını daha tahmin edilebilir ve sezgisel hale getirir. Daha fazla bilgi için Compose API yönergelerine bakın: Öğeler bir Modifier parametresini kabul eder ve uygular.

Değiştiricilerin sırası önemlidir

Değiştirici işlevlerin sırası önemlidir. Her işlev, önceki işlev tarafından döndürülen Modifier değerinde değişiklik yaptığından sıra, nihai sonucu etkiler. Şimdi bir örnek inceleyelim:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

Kenarlardaki dolgu dahil olmak üzere alanın tamamı tıklamalara yanıt verir

Yukarıdaki kodda, padding değiştiricisi clickable değiştiricisinden sonra uygulandığı için çevreleyen dolgu dahil olmak üzere alanın tamamı tıklanabilir. Değiştirici sırası tersine çevrilirse padding tarafından eklenen boşluk kullanıcı girişine tepki vermez:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .padding(padding)
            .clickable(onClick = onClick)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

Düzenin kenarındaki dolgu artık tıklamalara yanıt vermiyor

Yerleşik değiştiriciler

Jetpack Compose, bir bileşeni süslemenize veya geliştirmenize yardımcı olacak yerleşik değiştiricilerin bir listesini sağlar. Aşağıda, düzenleri ayarlamak için kullanacağınız bazı yaygın değiştiriciler verilmiştir.

padding ve size

Oluşturma bölümünde sağlanan düzenler varsayılan olarak alt öğelerini sarmalar. Ancak size değiştiricisini kullanarak bir boyut ayarlayabilirsiniz:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(/*...*/)
        Column { /*...*/ }
    }
}

Belirttiğiniz boyut, düzenin üst öğesinden gelen kısıtlamaları karşılamıyorsa dikkate alınmayabilir. Gelen kısıtlamalardan bağımsız olarak birleştirilebilir boyutun sabitlenmesini istiyorsanız requiredSize değiştiricisini kullanın:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.requiredSize(150.dp)
        )
        Column { /*...*/ }
    }
}

Alt resim, üst öğesinden gelen kısıtlamalardan daha büyük

Bu örnekte, üst öğe height 100.dp olarak ayarlanmış olsa bile requiredSize değiştirici öncelikli olduğundan Image öğesinin yüksekliği 150.dp olur.

Bir alt düzenin, üst öğenin izin verdiği tüm yüksekliği doldurmasını istiyorsanız fillMaxHeight değiştiricisini ekleyin (Oluşturma'da fillMaxSize ve fillMaxWidth de sağlanır):

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.fillMaxHeight()
        )
        Column { /*...*/ }
    }
}

Resim yüksekliği, üst öğesi kadar büyük

Bir öğenin etrafına dolgu eklemek için bir padding değiştirici ayarlayın.

Düzenin üst kısmından referans değere kadar belirli bir mesafeye ulaşmak için metin temel çizgisinin üstüne dolgu eklemek istiyorsanız paddingFromBaseline değiştiricisini kullanın:

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(
                text = artist.name,
                modifier = Modifier.paddingFromBaseline(top = 50.dp)
            )
            Text(artist.lastSeenOnline)
        }
    }
}

Üstünde dolgu bulunan metin

Zaman farkı

Bir düzeni orijinal konumuna göre konumlandırmak için offset değiştiricisini ekleyip x ve y ekseninde ofseti ayarlayın. Ofsetler hem pozitif hem de pozitif olmayan olabilir. padding ile offset arasındaki fark, bir bileşiğe offset eklendiğinde ölçümlerinin değişmemesidir:

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(artist.name)
            Text(
                text = artist.lastSeenOnline,
                modifier = Modifier.offset(x = 4.dp)
            )
        }
    }
}

Metin, üst kapsayıcısının sağ tarafına kaydırıldı

offset değiştiricisi, düzen yönüne göre yatay olarak uygulanır. Soldan sağa bağlamda pozitif offset, öğeyi sağa kaydırırken sağdan sola bir bağlamda öğeyi sola kaydırır. Sayfa düzeni yönünü dikkate almadan bir ofset ayarlamanız gerekiyorsa pozitif bir ofset değerinin öğeyi her zaman sağa kaydırdığı absoluteOffset değiştiriciye bakın.

offset değiştirici, iki aşırı yükleme sağlar: Ofsetleri parametre olarak alan offset ve lambda alan offset. Bunların her birinin ne zaman kullanılacağı ve performans için nasıl optimize edileceği hakkında daha ayrıntılı bilgi edinmek için Oluşturma performansı - Okuma işlemlerini mümkün olduğunca erteleme bölümünü okuyun.

Oluşturma'da kapsam güvenliği

Oluşturma'da, yalnızca belirli derlenebilir öğelerin alt öğelerine uygulandığında kullanılabilen değiştiriciler vardır. Oluşturma, özel kapsamlar aracılığıyla bunu zorunlu kılar.

Örneğin, Box boyutunu etkilemeden bir alt öğeyi Box öğesi kadar büyük yapmak istiyorsanız matchParentSize değiştiricisini kullanın. matchParentSize yalnızca BoxScope üzerinde kullanılabilir. Bu nedenle, yalnızca Box üst öğesi altındaki bir alt öğede kullanılabilir.

Kapsam güvenliği, diğer bileşimlerde ve kapsamlarda çalışmayacak değiştiriciler eklemenizi önler ve deneme yanılma sürecinden tasarruf etmenizi sağlar.

Kapsamlı değiştiriciler, ebeveyni çocuk hakkında bilmesi gereken bazı bilgiler hakkında bilgilendirir. Bunlara genellikle üst veri değiştiriciler denir. Bu işlevlerin iç yapısı, genel amaçlı değiştiricilerden farklıdır ancak kullanım açısından bu farklılıklar önemli değildir.

matchParentSize Box içinde başlıyor

Yukarıda belirtildiği gibi, bir alt düzenin Box boyutunu etkilemeden Box üst düzeniyle aynı boyutta olmasını istiyorsanız matchParentSize değiştiricisini kullanın.

matchParentSize'ün yalnızca Box kapsamında kullanılabildiğini unutmayın. Yani yalnızca Box bileşenlerinin doğrudan alt öğeleri için geçerlidir.

Aşağıdaki örnekte, Spacer alt öğesi boyutunu Box üst öğesinden alır. Box ise boyutunu en büyük alt öğeden (bu örnekte ArtistCard) alır.

@Composable
fun MatchParentSizeComposable() {
    Box {
        Spacer(
            Modifier
                .matchParentSize()
                .background(Color.LightGray)
        )
        ArtistCard()
    }
}

Kapsayıcıyı dolduran gri arka plan

matchParentSize yerine fillMaxSize kullanılsaydı Spacer, üst öğe için izin verilen kullanılabilir alanın tamamını alır, bunun sonucunda da üst öğe genişletip mevcut tüm alanı doldurur.

Ekranı kaplayan gri arka plan

Row ve Column konumunda weight

Önceki Dolgu ve boyut bölümünde gördüğünüz gibi, varsayılan olarak composable boyutu, sarmaladığı içeriğe göre tanımlanır. Yalnızca RowScope ve ColumnScope'de kullanılabilen weight değiştiriciyi kullanarak bir composable boyutunu üst öğesi içinde esnek olacak şekilde ayarlayabilirsiniz.

İki Box bileşeni içeren bir Row alalım. İlk kutuya ikinci kutunun weight değerinin iki katı, dolayısıyla genişliğin iki katı verilir. Row 210.dp genişliğinde olduğundan ilk Box 140.dp genişliğinde, ikincisi ise 70.dp genişliğindedir:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.fillMaxWidth()
    ) {
        Image(
            /*...*/
            modifier = Modifier.weight(2f)
        )
        Column(
            modifier = Modifier.weight(1f)
        ) {
            /*...*/
        }
    }
}

Resim genişliği, metin genişliğinin iki katı

Değiştiricileri ayıklama ve yeniden kullanma

Bir bileşiği süslemek veya geliştirmek için birden fazla değiştirici birlikte zincirlenebilir. Bu zincir, tek bir Modifier.Elements öğesinin sıralı ve değiştirilemez bir listesini temsil eden Modifier arayüzü aracılığıyla oluşturulur.

Her Modifier.Element, düzen, çizim ve grafik davranışları, tüm hareketle ilgili, odak ve anlambilim davranışları ve cihaz giriş etkinlikleri gibi bağımsız bir davranışı temsil eder. Sıralama önemlidir: Önce eklenen değiştirici öğeler önce uygulanır.

Bazen aynı değiştirici zinciri örneklerini birden fazla bileşimde yeniden kullanmak, bunları değişkenlere ayırarak ve daha yüksek kapsamlara taşıyarak yararlı olabilir. Google Analytics birkaç nedenden dolayı kod okunabilirliğini iyileştirebilir veya uygulamanızın performansını iyileştirebilir:

  • Değiştiricileri kullanan composable'lar için yeniden düzenleme gerçekleştiğinde, bu öğelerin yeniden ayrılması tekrarlanmaz
  • Değiştirici zincirleri çok uzun ve karmaşık olabilir. Bu nedenle, aynı zincir örneğini yeniden kullanmak, Compose çalışma zamanında zincirleri karşılaştırırken yapması gereken iş yükünü azaltabilir.
  • Bu ayıklama işlemi, kod tabanında kod temizliğini, tutarlılığı ve sürdürülebilirliği destekler.

Değiştiricileri yeniden kullanmayla ilgili en iyi uygulamalar

Kendi Modifier zincirlerinizi oluşturun ve bunları birden fazla birleştirilebilir bileşende yeniden kullanmak için ayıklayın. Veri benzeri nesneler oldukları için değiştiricileri yalnızca kaydetmenizde herhangi bir sakınca yoktur:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

Sık değişen durumu gözlemlerken değiştiricileri ayıklayıp yeniden kullanma

Animasyon durumları veya scrollState gibi, bileşenler içinde sık sık değişen durumlar gözlemlendiğinde önemli miktarda yeniden derleme yapılabilir. Bu durumda, değiştiricileriniz her yeniden oluşturma işleminde ve muhtemelen her kare için ayrılır:

@Composable
fun LoadingWheelAnimation() {
    val animatedState = animateFloatAsState(/*...*/)

    LoadingWheel(
        // Creation and allocation of this modifier will happen on every frame of the animation!
        modifier = Modifier
            .padding(12.dp)
            .background(Color.Gray),
        animatedState = animatedState
    )
}

Bunun yerine, değiştiricinin aynı örneğini oluşturup ayıklayabilir, yeniden kullanabilir ve aşağıdaki gibi birleştirilebilir öğeye iletebilirsiniz:

// Now, the allocation of the modifier happens here:
val reusableModifier = Modifier
    .padding(12.dp)
    .background(Color.Gray)

@Composable
fun LoadingWheelAnimation() {
    val animatedState = animateFloatAsState(/*...*/)

    LoadingWheel(
        // No allocation, as we're just reusing the same instance
        modifier = reusableModifier,
        animatedState = animatedState
    )
}

Kapsamsız değiştiricileri ayıklayıp yeniden kullanma

Değiştiricilerin kapsamı kaldırılabilir veya belirli bir composable'ın kapsamı ayarlanabilir. Kapsamlı olmayan değiştiriciler söz konusu olduğunda, bunları herhangi bir composable'ın dışına basit değişken olarak kolayca ayıklayabilirsiniz:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

@Composable
fun AuthorField() {
    HeaderText(
        // ...
        modifier = reusableModifier
    )
    SubtitleText(
        // ...
        modifier = reusableModifier
    )
}

Bu, özellikle Tembel düzenlerle birleştirildiğinde yararlı olabilir. Çoğu durumda, önemli olabilecek tüm öğelerinizin tamamen aynı değiştiricilere sahip olmasını istersiniz:

val reusableItemModifier = Modifier
    .padding(bottom = 12.dp)
    .size(216.dp)
    .clip(CircleShape)

@Composable
private fun AuthorList(authors: List<Author>) {
    LazyColumn {
        items(authors) {
            AsyncImage(
                // ...
                modifier = reusableItemModifier,
            )
        }
    }
}

Kapsamlı değiştiricileri ayıklayıp yeniden kullanma

Kapsamı belirli composable'lara ayarlanmış değiştiricilerle çalışırken, bunları mümkün olan en üst düzeye çıkarabilir ve uygun olduğunda yeniden kullanabilirsiniz:

Column(/*...*/) {
    val reusableItemModifier = Modifier
        .padding(bottom = 12.dp)
        // Align Modifier.Element requires a ColumnScope
        .align(Alignment.CenterHorizontally)
        .weight(1f)
    Text1(
        modifier = reusableItemModifier,
        // ...
    )
    Text2(
        modifier = reusableItemModifier
        // ...
    )
    // ...
}

Ayıklanan, kapsamlı değiştiricileri yalnızca aynı kapsamlı, doğrudan alt öğelere iletmeniz gerekir. Bunun neden önemli olduğu hakkında daha fazla bilgi için Oluşturma'da kapsam güvenliği bölümüne bakın:

Column(modifier = Modifier.fillMaxWidth()) {
    // Weight modifier is scoped to the Column composable
    val reusableItemModifier = Modifier.weight(1f)

    // Weight will be properly assigned here since this Text is a direct child of Column
    Text1(
        modifier = reusableItemModifier
        // ...
    )

    Box {
        Text2(
            // Weight won't do anything here since the Text composable is not a direct child of Column
            modifier = reusableItemModifier
            // ...
        )
    }
}

Ayıklanan değiştiricilerin daha fazla zincirlenmesi

.then() işlevini çağırarak ayıklanan değiştirici zincirlerinizi daha da zincirleyebilir veya ekleyebilirsiniz:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

// Append to your reusableModifier
reusableModifier.clickable { /*...*/ }

// Append your reusableModifier
otherModifier.then(reusableModifier)

Değişkenlerin sırasının önemli olduğunu unutmayın.

Daha fazla bilgi

Parametreleri ve kapsamlarıyla birlikte değişkenleri içeren tam bir liste sunuyoruz.

Değiştiricilerin nasıl kullanılacağıyla ilgili daha fazla alıştırma için Compose codelab'deki temel düzenler veya Now in Android repository (Android deposunda) konusuna da bakabilirsiniz.

Özel değiştiriciler ve bunların nasıl oluşturulacağı hakkında daha fazla bilgi için Özel düzenler - Düzen değiştiriciyi kullanma başlıklı dokümanları inceleyin.