Oluşturma değiştiriciler

Değiştiriciler, bir composable'ı süslemenizi veya zenginleştirmenizi sağlar. Değiştiriciler şu tür işlemler 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ş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 dolgu içeren iki satır metin.

İşlevleri birbirine bağlayarak oluşturmak için şu zincirleri kullanabilirsiniz:

@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 gösteriyor.

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

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

Tüm composable'larınızın bir modifier parametresini kabul etmesi ve bu değiştiriciyi, kullanıcı arayüzü yayan ilk alt öğesine iletmeniz önerilir. 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 öğesinde değişiklikler 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
    }
}

Kenarların çevresindeki dolgu dahil olmak üzere tüm alan tıklamalara yanıt verir

Yukarıdaki kodda, padding değiştiricisi clickable değiştiriciden sonra uygulandığı için etrafındaki dolgu da dahil olmak üzere alanın tamamı 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ının etrafındaki dolgu artık tıklamalara yanıt vermiyor

Yerleşik değiştiriciler

Jetpack Compose, bir composable'ı dekore etmenize veya zenginleştirmenize yardımcı olacak yerleşik değiştiricilerden oluşan bir liste sunuyor. Düzenlerinizi ayarlamak için kullanacağınız yaygın değiştiricilerden bazıları şunlardır:

padding ve size

Varsayılan olarak, Compose'da sağlanan düzenler 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şılamazsa dikkate alınmayabileceğini unutmayın. Gelen kısıtlamalardan bağımsız olarak composable boyutunun sabitlenmesini zorunlu tutuyorsanız requiredSize değiştiriciyi 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, height üst öğesi 100.dp olarak ayarlanmış olsa bile requiredSize değiştiricisi öncelikli hale geldiğinden Image öğesinin yüksekliği 150.dp olur.

Bir alt düzenin üst öğe tarafından izin verilen tüm mevcut yüksekliği doldurmasını istiyorsanız fillMaxHeight değiştiricisini ekleyin (Oluşturma, fillMaxSize ve fillMaxWidth özelliklerini de sunar):

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

Resim yüksekliği, üst resmin yüksekliği kadar olmalıdır

Bir öğenin etrafına dolgu eklemek için padding değiştiricisini 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)
        }
    }
}

Dolgulu 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. Kaydırmalar pozitif olduğu kadar pozitif olmayabilir de. padding ile offset arasındaki fark, bir composable'a offset eklemenin ölçümlerini 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ü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. Düzen yönünü dikkate almadan belirli bir ofset ayarlamanız gerekiyorsa pozitif ofset değerinin öğeyi her zaman sağa kaydırdığı absoluteOffset değiştiriciye bakın.

offset değiştiricisi, ofsetleri parametre olarak alan offset ve lambda alan offset adlı iki aşırı yükleme sağlar. Bunların her birinin ne zaman kullanılacağı ve performans için nasıl optimizasyon yapılacağıyla ilgili ayrıntılı bilgi için Performans oluştur - Okumaları mümkün olduğunca uzun ertele bölümünü okuyun.

Compose'da kapsam güvenliği

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

Örneğin, Box boyutunu etkilemeden bir alt öğeyi üst Box kadar büyük yapmak isterseniz matchParentSize değiştiriciyi kullanın. matchParentSize, yalnızca BoxScope dilinde kullanılabilir. Bu nedenle, yalnızca Box üst grubundaki bir alt yayıncıda kullanılabilir.

Kapsam güvenliği, diğer composable'larda ve kapsamlarda çalışmayacak değiştiriciler eklemenizi engeller, deneme ve yanılma sırasında zaman kazandırır.

Kapsamlı değiştiriciler, üst öğeyi ebeveynin alt öğe hakkında bilmesi gereken bazı bilgiler hakkında bilgilendirir. Bunlara genellikle ebeveyn veri değiştiricileri olarak da adlandırılır. Dahili öğeler, genel amaçlı değiştiricilerden farklıdır ancak kullanım açısından bakıldığında bu farklılıklar önemli değildir.

Box dahilinde matchParentSize tarihinde başlıyor

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

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

Aşağıdaki örnekte Spacer alt öğesi, boyutunu Box olan üst öğesinden alır. Bu da kendi boyutunu en büyük alt öğeden (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ılmışsa Spacer, üst öğe için izin verilen kullanılabilir alanın tamamını alır, bunun sonucunda üst öğe genişletilir ve kullanılabilir tüm alanı doldurur.

Ekranı kaplayan gri arka plan

Row ve Column içinde 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 ürünlerinde kullanılabilen weight Değiştiriciyi kullanarak üst öğesi içinde composable'ı esnek olacak şekilde ayarlayabilirsiniz.

İki Box composable içeren bir Row düşünelim. İlk kutu, ikincinin weight değerinin iki katı olduğundan genişliğin iki katı olur. Row, 210.dp genişliğinde olduğundan ilk Box 140.dp genişliğinde ve ikincisi 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 çıkarma ve yeniden kullanma

Bir composable'ı süslemek veya zenginleştirmek için birden fazla değiştirici bir araya getirilebilir. Bu zincir, tek Modifier.Elements'ten oluşan sıralı ve sabit bir listeyi temsil eden Modifier arayüzü aracılığıyla oluşturulur.

Her Modifier.Element; düzen, çizim ve grafik davranışları, hareketle ilgili tüm, odaklanma ve anlamsal davranışlar gibi bireysel bir davranışı ve cihaz giriş etkinliklerini temsil eder. Bunların sıralaması önemlidir: Önce eklenen değiştirici öğeler uygulanır.

Bazen aynı değiştirici zincir örneklerinin birden fazla composable'da yeniden kullanılması faydalı olabilir. Bunun için bu örnekleri değişkenlere ayırıp daha yüksek kapsamlara kaldırmanız gerekir. 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 potansiyel olarak çok uzun ve karmaşık olabilir. Bu nedenle, aynı zincirin tekrar kullanılması, Compose çalışma zamanının zincirleri karşılaştırırken yapması gereken iş yükünü hafifletebilir
  • Bu ayıklama işlemi, kod tabanı genelinde kod temizliğini, tutarlılığını ve sürdürülebilirliğini teşvik eder

Değiştiricileri yeniden kullanmak için en iyi uygulamalar

Kendi Modifier zincirlerinizi oluşturun ve bunları ayıklayarak derlenebilir birden çok bileşende yeniden kullanın. Değiştiriciler verilere benzer nesneler olduğundan bunları kaydedebilirsiniz:

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

Sık sık değişen durumu gözlemlerken değiştiricileri çıkarma ve yeniden kullanma

composable'ların içinde animasyon durumları veya scrollState gibi sık sık değişen durumları gözlemlerken önemli miktarda yeniden düzenleme yapılabilir. Bu durumda, değiştiricileriniz her yeniden oluşturmada ve potansiyel olarak 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şturabilir, ayıklayabilir, yeniden kullanabilir ve şu şekilde composable'a aktarabilirsiniz:

// 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 çıkarma ve 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 çıkarma ve 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
        // ...
    )
    // ...
}

Çıkarılan, kapsamlı değiştiricileri yalnızca aynı kapsamlı, doğrudan alt öğelere iletmeniz gerekir. Bunun neden önemli olduğuna dair daha fazla referans için Compose'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ştiricilerde daha fazla zincirleme

.then() işlevini çağırarak ayıklanan değiştirici zincirlerinizi daha fazla zincir halinde ekleyebilir 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 değiştiricilerin tam listesini 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 ile ilgili belgelere göz atın.