Oluşturma değiştiriciler

Değiştiriciler, composable'ları süslemenize veya geliştirmenize olanak tanır. Değiştiriciler, aşağıdakiler gibi işlemleri yapmanıza olanak tanır:

  • Composable'ın 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şleme
  • Bir öğeyi tıklanabilir, kaydırılabilir, sürüklenebilir veya yakınlaştırılabilir hale getirme gibi üst düzey etkileşimler ekleme

Değiştiriciler, standart Kotlin nesneleridir. Aşağıdaki Modifier sınıf işlevlerinden birini çağırarak değiştirici 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 dolgu bulunan iki satırlık metin.

Bu işlevleri birbirine bağlayarak 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 tam genişliğine kadar uzanıyor.

Yukarıdaki kodda, birlikte kullanılan farklı değiştirici işlevlere dikkat edin.

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

Birleştirilebilir işlevlerinizin modifier parametresini kabul etmesi ve bu değiştiriciyi kullanıcı arayüzü yayan ilk alt öğesine iletmesi en iyi uygulamadır. Bu sayede kodunuz daha fazla kullanılabilir ve davranışları daha tahmin edilebilir ve sezgisel hale gelir. Daha fazla bilgi için Compose API kuralları, Öğeler, değiştirici parametresini kabul eder ve buna uyar başlıklı makaleyi inceleyin.

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 üzerinde değişiklik yaptığından sıra, nihai sonucu etkiler. Bununla ilgili bir örneğe bakalım:

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

Kenarlardaki dolgu da dahil olmak üzere tüm alan tıklamalara yanıt veriyor.

padding değiştiricisi, clickable değiştiricisinden sonra uygulandığı için yukarıdaki kodda, etrafındaki dolgu da dahil olmak üzere tüm alan tıklanabilir. Değiştiricilerin 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, composable'ları süslemenize veya geliştirmenize yardımcı olmak için yerleşik değiştiricilerin bir listesini sunar. Düzenlerinizi ayarlamak için kullanacağınız bazı yaygın değiştiriciler aşağıda verilmiştir.

padding ve size

Varsayılan olarak, Compose'da sağlanan düzenler alt öğelerini sarmalar. Ancak, size değiştiricisini kullanarak bir boyut belirleyebilirsiniz:

@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 sabit olmasını 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 öğeden gelen kısıtlamalardan daha büyük

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

Bir alt düzenin, üst öğe tarafından izin verilen tüm kullanılabilir yüksekliği doldurmasını istiyorsanız fillMaxHeight değiştiricisini ekleyin (Compose, fillMaxSize ve fillMaxWidth değiştiricilerini de sağlar):

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

Resmin yüksekliği üst öğesi kadar büyük

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

Düzenin üst kısmından taban çizgisine belirli bir mesafe olacak şekilde metin taban ç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 ekleyin ve x ile y ekseninde dengelemeyi ayarlayın. Ofsetler pozitif veya pozitif olmayan değerler olabilir. padding ile offset arasındaki fark, bir composable'a offset eklemenin ölçülerini değiştirmemesidir:

@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üzene göre yatay olarak uygulanır. Soldan sağa bağlamda pozitif bir offset değeri öğeyi sağa kaydırırken sağdan sola bağlamda öğeyi sola kaydırır. Düzen yönünü dikkate almadan bir ofset ayarlamanız gerekiyorsa absoluteOffset değiştiricisini inceleyin. Bu değiştiricide pozitif ofset değeri, öğeyi her zaman sağa kaydırır.

offset değiştiricisi iki aşırı yükleme sağlar: offset, ofsetleri parametre olarak alır ve offset, lambda alır. Bunların her birini ne zaman kullanacağınız ve performansı optimize etme hakkında daha ayrıntılı bilgi için Performansı oluşturma - Okumaları mümkün olduğunca erteleme bölümünü inceleyin.

Oluşturma özelliğinde güvenlik kapsamı

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

Örneğin, Box boyutunu etkilemeden Box çocuğun ebeveyn kadar büyük olmasını istiyorsanız matchParentSize değiştiricisini kullanın. matchParentSize yalnızca BoxScope'da kullanılabilir. Bu nedenle, yalnızca Box üst öğesi olan bir çocukta kullanılabilir.

Kapsam güvenliği, diğer composable'larda ve kapsamlarda çalışmayacak değiştiriciler eklemenizi önler ve deneme yanılma sürecinde zaman kazanmanızı sağlar.

Kapsamlı değiştiriciler, ebeveyni çocuğun bilmesi gereken bazı bilgiler hakkında bilgilendirir. Bunlara genellikle üst veri değiştiriciler de denir. Bu değiştiricilerin iç işleyişi genel amaçlı değiştiricilerden farklı olsa da 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 üst düzenle aynı boyutta olmasını istiyorsanız Box boyutunu etkilemeden Box değiştiricisini kullanın.matchParentSize

matchParentSize öğesinin yalnızca Box kapsamında kullanılabildiğini unutmayın. Bu nedenle, yalnızca Box composable'larının doğrudan alt öğeleri için geçerlidir.

Aşağıdaki örnekte, Spacer alt öğesi boyutunu Box üst öğesinden alıyor. Box üst öğesi ise boyutunu bu örnekteki en büyük alt öğeler olan ArtistCard öğelerinden alıyor.

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

Kapsayıcısını dolduran gri arka plan

matchParentSize yerine fillMaxSize kullanılsaydı Spacer, üst öğeye izin verilen tüm alanı kaplar ve üst öğenin genişleyerek tüm alanı doldurmasına neden olurdu.

Ekranı kaplayan gri arka plan

Row ve Column içinde weight

Doldurma ve boyut ile ilgili önceki bölümde gördüğünüz gibi, bir composable'ın boyutu varsayılan olarak sarmaladığı içerik tarafından tanımlanır. weight Modifier'ı kullanarak composable boyutunu, yalnızca RowScope ve ColumnScope içinde kullanılabilen üst öğesinde esnek olacak şekilde ayarlayabilirsiniz.

İki Box composable'ı içeren bir Row alalım. İlk kutu, ikinci kutunun weight katı genişliğe sahiptir. 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

Birden fazla değiştirici, bir composable'ı süslemek veya geliştirmek için birlikte kullanılabilir. Bu zincir, tek Modifier.Elements öğelerinin sıralı ve değişmez 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 semantik davranışlar ile cihaz giriş etkinlikleri gibi ayrı bir davranışı temsil eder. Sıralama önemlidir: Önce eklenen değiştirici öğeler önce uygulanır.

Bazen aynı değiştirici zinciri örneklerini değişkenlere ayırıp daha yüksek kapsamlara taşıyarak birden fazla composable'da yeniden kullanmak faydalı olabilir. Bu özellik, birkaç nedenden dolayı kodun okunabilirliğini artırabilir veya uygulamanızın performansını iyileştirmeye yardımcı olabilir:

  • Değiştiricilerin yeniden atanması, bunları kullanan composable'lar için yeniden oluşturma gerçekleştiğinde tekrarlanmaz.
  • Değiştirici zincirleri çok uzun ve karmaşık olabileceğinden aynı zincir örneğini yeniden kullanmak, Compose çalışma zamanının bunları karşılaştırırken yapması gereken iş yükünü azaltabilir.
  • Bu çıkarma işlemi, kod tabanında kod temizliğini, tutarlılığı ve sürdürülebilirliği artırır.

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. Değiştiriciler, veriye benzer nesneler olduğundan yalnızca bir değiştiriciyi kaydetmeniz sorun teşkil etmez:

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

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

Animasyon durumları veya scrollState gibi, composable'lar içindeki sık değişen durumlar gözlemlenirken önemli miktarda yeniden oluşturma işlemi yapılabilir. Bu durumda, değiştiricileriniz her yeniden oluşturmada ve muhtemelen her karede 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 çıkarabilir, yeniden kullanabilir ve composable'a şu şekilde 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
    )
}

Kapsamı belirlenmemiş değiştiricileri ayıklama ve yeniden kullanma

Değiştiriciler, kapsamı kaldırılmış veya belirli bir composable ile sınırlandırılmış olabilir. Kapsamı belirlenmemiş değiştiriciler söz konusu olduğunda, bunları composable'ların dışında basit değişkenler olarak kolayca ayıklayabilirsiniz:

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

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

Bu özellik, özellikle tembel düzenlerle birlikte kullanıldığında faydalı olabilir. Çoğu durumda, önemli miktarda olabilecek tüm öğelerinizin tam olarak 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 çıkarma ve yeniden kullanma

Belirli composable'larla sınırlı değiştiricilerle uğraşırken bunları mümkün olan en yüksek seviyeye çıkarabilir ve uygun yerlerde 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
        // ...
    )
    // ...
}

Yalnızca çıkarılan ve kapsamı belirlenen değiştiricileri aynı kapsamdaki doğrudan alt öğelere iletmeniz gerekir. Bunun neden önemli olduğuyla ilgili 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
            // ...
        )
    }
}

Çıkarılan değiştiricilerin daha fazla zincirlenmesi

.then() işlevini çağırarak çıkarılan 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ştiricilerin sırasının önemli olduğunu unutmayın.

Daha fazla bilgi

Parametreleri ve kapsamlarıyla birlikte tüm değiştiricilerin listesini sunuyoruz.

Değiştiricileri kullanma konusunda daha fazla pratik yapmak için Basic layouts in Compose codelab (Compose'da temel düzenler codelab'i) modülünü inceleyebilir veya Now in Android repository'ye (Android'de yenilikler deposu) göz atabilirsiniz.

Ö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ümana göz atın.