Değiştiriciler, bir composable'ı süslemenize veya genişletmenize olanak tanır. Değiştiriciler, bu tür işlemleri yapmanıza olanak tanır:
- Birleştirilebilir öğenin boyutunu, düzenini, davranışını ve görünümünü değiştirme
- Erişilebilirlik etiketleri gibi bilgiler ekleyemez.
- 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. 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) } }
Bu işlevleri birleştirerek zincirleme bir yapı oluşturabilirsiniz:
@Composable private fun Greeting(name: String) { Column( modifier = Modifier .padding(24.dp) .fillMaxWidth() ) { Text(text = "Hello,") Text(text = name) } }
Yukarıdaki kodda, farklı değiştirici işlevlerin birlikte kullanıldığına dikkat edin.
padding, bir öğenin etrafına boşluk ekler.fillMaxWidth, composable'ın üst öğesinden kendisine verilen maksimum genişliği doldurmasını sağlar.
Tüm composable'larınızın bir modifier parametresi kabul etmesi ve bu değiştiriciyi kullanıcı arayüzü oluşturan ilk alt öğesine iletmesi en iyi uygulamadır.
Böylece kodunuz daha yeniden kullanılabilir hale gelir ve davranışı daha öngörülebilir ve sezgisel olur. Daha fazla bilgi için Compose API yönergelerindeki Öğeler bir Değiştirici parametresini kabul eder ve dikkate alır bölümüne bakın.
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 } }
Yukarıdaki kodda, padding değiştiricisi clickable değiştiricisinden sonra uygulandığı için çevreleyen dolgu dahil tüm alan tıklanabilir. Değiştiricilerin sırası tersine çevrilirse padding tarafından eklenen boşluk, kullanıcı girişine yanıt vermez:
@Composable fun ArtistCard(/*...*/) { val padding = 16.dp Column( Modifier .padding(padding) .clickable(onClick = onClick) .fillMaxWidth() ) { // rest of the implementation } }
Yerleşik değiştiriciler
Jetpack Compose, composable'ları süslemenize veya geliştirmenize yardımcı olacak yerleşik değiştiricilerin listesini sunar. Düzenlerinizi ayarlamak için kullanacağınız bazı yaygın değiştiriciler ş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şılamıyorsa dikkate alınmayabilir. Gelen kısıtlamalardan bağımsız olarak composable boyutunun 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 { /*...*/ } } }
Bu örnekte, üst öğe height 100.dp olarak ayarlanmış olsa bile Image öğesinin yüksekliği 150.dp olur. Bunun nedeni, requiredSize değiştiricisinin öncelikli olmasıdır.
Bir alt düzenin, üst öğenin izin verdiği tüm 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 { /*...*/ } } }
Bir öğenin her tarafına dolgu eklemek için padding değiştiricisini ayarlayın.
padding öğesinin start ve end parametreleri, düzen yönünü takip eder. Düzen yönünden bağımsız olarak sol veya sağ kenara dolgu eklemek için absolutePadding öğesini left ve right parametreleriyle kullanın.
Metin taban çizgisinin üstüne dolgu ekleyerek düzenin üst kısmından taban çizgisine belirli bir mesafe bırakmak 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) } } }
Ofset
Bir düzeni orijinal konumuna göre konumlandırmak için offset değiştiricisini ekleyin ve x ve y ekseninde ofseti ayarlayın.
Ofsetler pozitif veya negatif olabilir. 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) ) } } }
offset değiştirici, düzen yönüne göre yatay olarak uygulanır.
Soldan sağa bağlamda pozitif bir offset, öğ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 pozitif ofset değerinin öğeyi her zaman sağa kaydırdığı absoluteOffset değiştiriciye bakın.
offset değiştiricisi, 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 Compose performansı - Okumaları mümkün olduğunca erteleme 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 öğe Box kadar büyük yapmak istiyorsanız matchParentSize değiştiricisini kullanın. matchParentSize yalnızca BoxScope'de kullanılabilir.
Bu nedenle, yalnızca Box üst öğesinin alt öğesinde kullanılabilir.
Kapsam güvenliği, diğer composable'larda ve kapsamlarda çalışmayacak değiştiriciler eklemenizi önler ve deneme yanılma yoluyla zaman kazanmanızı sağlar.
Kapsamlı değiştiriciler, üst öğeyi alt öğe hakkında bilmesi gereken bazı bilgiler konusunda bilgilendirir. Bunlar genellikle üst veri değiştiriciler olarak da adlandırılır. Dahili yapıları genel amaçlı değiştiricilerden farklı olsa da kullanım açısından bu farklılıklar önemli değildir.
Box liginde matchParentSize. sırada
Yukarıda belirtildiği gibi, bir alt düzenin
Box boyutunu etkilemeden üst düzenle aynı boyutta olmasını istiyorsanız BoxmatchParentSize değiştiricisini kullanın.
matchParentSize yalnızca Box kapsamında kullanılabilir. Yani yalnızca Box bileşenlerinin doğrudan alt öğeleri için geçerlidir.
Aşağıdaki örnekte, alt öğe Spacer boyutunu üst öğesinden Box alır. Üst öğe de boyutunu en büyük alt öğeden (bu örnekte ArtistCard) alır.
@Composable fun MatchParentSizeComposable() { Box { Spacer( Modifier .matchParentSize() .background(Color.LightGray) ) ArtistCard() } }
matchParentSize yerine fillMaxSize kullanılsaydı Spacer, üst öğeye izin verilen tüm kullanılabilir alanı kaplar ve bu da üst öğenin genişleyerek tüm kullanılabilir alanı doldurmasına neden olurdu.
Row ve Column uygulamalarında weight
Dolgu ve boyut ile ilgili önceki bölümde gördüğünüz gibi, varsayılan olarak bir composable'ın boyutu, sarmaladığı içerik tarafından tanımlanır. Yalnızca RowScope ve ColumnScope içinde kullanılabilen weight değiştiricisini kullanarak bir composable'ın boyutunu üst öğesi içinde esnek olacak şekilde ayarlayabilirsiniz.
İki Box bileşeni içeren bir Row ele alalım.
İlk kutuya ikincinin iki katı weight verildiği için genişliği de iki katı olur. Row 210.dp genişliğinde, ilk Box 140.dp genişliğinde ve ikincisi 70.dp genişliğinde olduğundan:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.fillMaxWidth() ) { Image( /*...*/ modifier = Modifier.weight(2f) ) Column( modifier = Modifier.weight(1f) ) { /*...*/ } } }
Değiştiricileri ayıklama ve yeniden kullanma
Bir composable'ı süslemek veya genişletmek için birden fazla değiştirici birbirine bağlanabilir. Bu zincir, sıralı ve sabit bir tekli Modifier.Elements listesini temsil eden Modifier arayüzü aracılığıyla oluşturulur.
Her Modifier.Element; düzen, çizim ve grafik davranışları, hareketle ilgili tüm davranışlar, odak ve semantik davranışların yanı sıra cihaz giriş etkinlikleri gibi ayrı bir davranışı temsil eder. Sıralama önemlidir: İlk eklenen değiştirici öğeler ilk olarak uygulanır.
Bazen aynı değiştirici zinciri örneklerini değişkenlere ayırıp daha yüksek kapsamlara yükselterek birden fazla composable'da yeniden kullanmak faydalı olabilir. Bu, kodun okunabilirliğini artırabilir veya uygulamanızın performansını birkaç nedenden dolayı iyileştirebilir:
- Değiştiricilerin yeniden tahsisi, bunları kullanan composable'lar için yeniden oluşturma gerçekleştiğinde tekrarlanmaz.
- Değiştirici zincirleri çok uzun ve karmaşık olabilir. Bu nedenle, 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 ayırma işlemi, kod tabanında kod temizliğini, tutarlılığını ve sürdürülebilirliğini 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 veri benzeri nesneler olduğundan, yalnızca değiştiriciyi kaydetmenizde hiç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ıklama ve yeniden kullanma
Animasyon durumları veya scrollState gibi composable'ların içinde sık sık değişen durumları gözlemlerken önemli miktarda yeniden oluşturma işlemi yapılabilir. Bu durumda, değiştiricileriniz her yeniden oluşturma işleminde ve potansiyel olarak her kare için tahsis edilir:
@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 ve yeniden kullanabilirsiniz. Ardından, değiştiriciyi 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 dışı olabilir veya belirli bir composable ile kapsamlandırılabilir. Kapsamsız değiştiricileri, herhangi bir composable'ın dışında basit değişkenler olarak kolayca çıkarabilirsiniz:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp) @Composable fun AuthorField() { HeaderText( // ... modifier = reusableModifier ) SubtitleText( // ... modifier = reusableModifier ) }
Bu, özellikle Lazy düzenleriyle birleştirildiğinde faydalı olabilir. Çoğu durumda, potansiyel olarak önemli miktarda olan 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ıklama ve yeniden kullanma
Belirli composable'lar için kapsamı belirlenmiş değiştiricilerle çalışı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 // ... ) // ... }
Ayıklanan, kapsamlı değiştiricileri yalnızca aynı kapsamdaki doğrudan alt öğelere iletmeniz gerekir. Bunun neden önemli olduğu hakkında daha fazla bilgi 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 // ... ) } }
Ayıklanan değiştiricilerin daha fazla zincirlenmesi
.then() işlevini çağırarak ayıklanan değiştirici zincirlerinizi daha fazla 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 değiştiricilerin tam listesini sunuyoruz.
Değiştiricilerin kullanımıyla ilgili daha fazla alıştırma yapmak için Compose'da temel düzenler codelab'ini inceleyebilir veya Now in Android deposuna göz atabilirsiniz.
Özel değiştiriciler ve bunları oluşturma hakkında daha fazla bilgi için Özel düzenler - Düzen değiştiriciyi kullanma ile ilgili belgelere göz atın.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Compose düzeniyle ilgili temel bilgiler
- Düzenleyici işlemleri {:#editor-actions}
- Özel düzenler {:#custom-layouts }