Salah satu aturan Compose adalah Anda seharusnya hanya mengukur turunan satu kali; mengukur turunan dua kali akan memunculkan pengecualian runtime. Namun, ada kalanya Anda memerlukan beberapa informasi tentang turunan Anda sebelum mengukurnya.
Intrinsik memungkinkan Anda membuat kueri turunan sebelum benar-benar diukur.
Ke composable, Anda dapat meminta IntrinsicSize.Min
atau IntrinsicSize.Max
:
Modifier.width(IntrinsicSize.Min)
- Berapa lebar minimum yang Anda perlukan untuk menampilkan konten dengan benar?Modifier.width(IntrinsicSize.Max)
- Berapa lebar maksimum yang Anda perlukan untuk menampilkan konten dengan benar?Modifier.height(IntrinsicSize.Min)
- Berapa tinggi minimum yang Anda perlukan untuk menampilkan konten dengan benar?Modifier.height(IntrinsicSize.Max)
- Berapa tinggi maksimum yang Anda perlukan untuk menampilkan konten dengan benar?
Misalnya, jika Anda meminta minIntrinsicHeight
dari Text
dengan batasan
width
yang tidak terbatas dalam tata letak kustom, variabel ini akan menampilkan height
dari Text
dengan teks yang digambar dalam satu baris.
Cara kerja intrinsik
Bayangkan kita ingin membuat composable yang menampilkan dua teks di layar yang dipisahkan oleh pemisah seperti ini:
Bagaimana cara melakukannya? Kita dapat memiliki Row
dengan dua Text
di dalamnya yang meluas sebanyak mungkin dan Divider
di tengah. Kita ingin Divider
setinggi
Text
tertinggi dan tipis (width = 1.dp
).
@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 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
Jika melihat pratinjau ini, kita melihat bahwa Divider
meluas ke seluruh layar dan
bukan itu yang kita inginkan:
Hal ini terjadi karena Row
mengukur setiap turunan secara individual dan tinggi Text
tidak dapat digunakan untuk membatasi Divider
. Kita ingin Divider
mengisi ruang yang tersedia dengan ketinggian tertentu. Untuk itu, kita dapat menggunakan pengubah height(IntrinsicSize.Min)
.
height(IntrinsicSize.Min)
mengukur ukuran turunannya yang dipaksa untuk setinggi instrinsik minimum mereka. Karena bersifat berulang, ini akan membuat kueri Row
dan turunannya minIntrinsicHeight
.
Menerapkannya ke kode kita akan berfungsi seperti yang diharapkan:
@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 ) VerticalDivider( 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") } } }
Dengan pratinjau:
minIntrinsicHeight
Row
composable akan menjadi minIntrinsicHeight
maksimum dari turunannya. Divider
minIntrinsicHeight
elemen adalah 0 karena tidak menempati ruang jika tidak ada batasan yang
diberikan; Text
minIntrinsicHeight
akan menjadi teks yang ditentukan width
tertentu. Oleh karena itu, batasan height
Row
elemen akan menjadi minIntrinsicHeight
maksimum dari Text
. Divider
kemudian akan memperluas height
-nya ke
batasan height
yang ditentukan oleh Row
.
Intrinsik di tata letak kustom
Saat membuat pengubah Layout
atau layout
kustom, pengukuran intrinsik
dihitung secara otomatis berdasarkan perkiraan. Oleh karena itu,
penghitungan mungkin tidak tepat untuk semua tata letak. API ini menawarkan opsi
untuk mengganti perilaku default tersebut.
Untuk menentukan pengukuran intrinsik Layout
kustom Anda,
ganti minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
,
dan maxIntrinsicHeight
dari antarmuka MeasurePolicy
saat membuatnya.
@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. } ) }
Saat membuat pengubah layout
kustom, ganti metode terkait
di antarmuka LayoutModifier
.
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. }
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Tata letak kustom {:#custom-layouts }
- Garis perataan di Jetpack Compose
- Fase Jetpack Compose