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) } }
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) } }
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 } }
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 } }
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 { /*...*/ } } }
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 { /*...*/ } } }
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) } } }
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) ) } } }
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() } }
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.
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) ) { /*...*/ } } }
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.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir.
- Oluşturma düzeniyle ilgili temel bilgiler
- Düzenleyici işlemleri {:#editor-actions}
- Özel düzenler {:#custom-layouts }