Compose'un kurallarından biri de alt öğelerinizi yalnızca bir kez ölçmenizdir. Alt öğeleri iki kez ölçmek, çalışma zamanı istisnasına neden olur. Bununla birlikte, ölçümden önce çocuklarınızla ilgili bazı bilgilere ihtiyaç duyduğunuz zamanlar vardır.
Intrinsics, çocukları ölçülmeden önce sorgulamanızı sağlar.
Bir composable'a intrinsicWidth
veya intrinsicHeight
vermesini isteyebilirsiniz:
(min|max)IntrinsicWidth
: Bu yükseklik göz önüne alındığında, içeriğinizi doğru şekilde boyayabileceğiniz minimum/maksimum genişlik nedir?(min|max)IntrinsicHeight
: Bu genişliğe göre içeriğinizi doğru şekilde boyayabileceğiniz minimum/maksimum yükseklik nedir?
Örneğin, sonsuz width
içeren bir Text
öğesinin minIntrinsicHeight
değerine bakarsanız metin tek bir satırda çizilmiş gibi Text
height
değerini döndürür.
Temel özelliklerin işleyiş şekli
Ekranda iki metni aşağıdaki gibi ayırıcıyla ayrılmış bir şekilde görüntüleyen bir composable oluşturmak istediğinizi varsayalım:
Bunu nasıl yapabiliriz? İçinde olabildiğince çok genişleyen iki Text
ve ortasında bir Divider
olan bir Row
olabilir. Divider
öğesinin yüksekliği en yüksek Text
ve ince (width = 1.dp
) olmasını istiyoruz.
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) Divider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
Bunu önizlediğimizde, Divider
öğesinin tüm ekrana genişlediğini görürüz ve istediğimiz şey bu değildir:
Bunun nedeni, Row
özelliğinin her bir alt öğeyi ayrı olarak ölçmesi ve Text
yüksekliğinin Divider
özelliğini sınırlandırmak için kullanılamamasıdır. Divider
öğesinin, mevcut alanı belirli bir yükseklikle doldurmasını isteriz. Bunun için height(IntrinsicSize.Min)
değiştiricisini kullanabiliriz .
height(IntrinsicSize.Min)
, çocuklarını doğal olarak en kısa boyda olmak
zorunda kalacak şekilde boyutlandırır. Yinelemeli olduğundan Row
ve alt öğelerini minIntrinsicHeight
sorgulayacak.
Bu komut, kodumuza uygulandığında beklendiği gibi çalışacaktır:
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier.height(IntrinsicSize.Min)) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) Divider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } } // @Preview @Composable fun TwoTextsPreview() { MaterialTheme { Surface { TwoTexts(text1 = "Hi", text2 = "there") } } }
Önizlemeyle:
Row
composable'ın minIntrinsicHeight
alt öğesi, alt öğeleri arasında maksimum minIntrinsicHeight
olacak. Divider
öğesinin minIntrinsicHeight
değeri, hiçbir sınırlama verilmediğinde yer kaplamadığı için 0'dır. Text
minIntrinsicHeight
değeri, belirli bir width
değeri verilen metnin değeri olur. Bu nedenle, Row
öğesinin height
kısıtlaması, Text
değerlerinin maksimum minIntrinsicHeight
değeri olur. Divider
, daha sonra height
öğesini Row
tarafından belirtilen height
kısıtlamasına genişletir.
Özel düzenlarınızdaki iç öğeler
Özel bir Layout
veya layout
değiştiricisi oluştururken doğal ölçümler yaklaşık değerlere göre otomatik olarak hesaplanır. Bu nedenle, hesaplamalar tüm düzenler için doğru olmayabilir. Bu API'ler, bu varsayılanları geçersiz kılma seçenekleri sunar.
Özel Layout
öğenizin içsel ölçümlerini belirtmek için MeasurePolicy
arayüzünü oluştururken minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
ve maxIntrinsicHeight
öğelerini geçersiz kılın.
@Composable fun MyCustomComposable( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( content = content, modifier = modifier, measurePolicy = object : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. } ) }
Özel layout
değiştiricinizi oluştururken LayoutModifier
arayüzünde ilgili yöntemleri geçersiz kılın.
fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier { override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. }
Sizin için önerilenler
- Not: Bağlantı metni JavaScript kapalıyken görüntülenir
- Özel düzenler {:#custom-layouts }
- Jetpack Compose'da hizalama çizgileri
- Jetpack Oluşturma Aşamaları