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 butuhkan untuk menampilkan konten dengan benar?Modifier.height(IntrinsicSize.Min)
- Berapa tinggi minimum yang Anda butuhkan 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
Anda dapat membuat composable yang menampilkan dua teks di layar yang dipisahkan oleh pemisah:
Untuk melakukannya, gunakan Row
dengan dua composable Text
yang mengisi ruang yang tersedia, dan Divider
di tengah. Divider
harus setinggi
Text
tertinggi, dan harus 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 ) } }
Divider
meluas ke seluruh layar, yang bukan merupakan perilaku yang diinginkan:
Hal ini terjadi karena Row
mengukur setiap turunan secara individual, dan tinggi
Text
tidak dapat digunakan untuk membatasi Divider
.
Agar Divider
mengisi ruang yang tersedia dengan ketinggian tertentu,
gunakan pengubah height(IntrinsicSize.Min)
.
height(IntrinsicSize.Min)
mengukur ukuran turunannya agar setinggi tinggi intrinsik minimumnya. Karena pengubah ini bersifat rekursif, pengubah ini membuat kueri
minIntrinsicHeight
dari Row
dan turunannya.
Menerapkan pengubah ini ke kode Anda akan membuatnya 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:
Tinggi Row
ditentukan sebagai berikut:
minIntrinsicHeight
composableRow
adalahminIntrinsicHeight
maksimum dari turunannya.minIntrinsicHeight
elemenDivider
adalah 0, karena tidak menempati ruang jika tidak ada batasan yang diberikan.Text
minIntrinsicHeight
adalah teks untukwidth
tertentu.- Oleh karena itu, batasan
height
Row
elemen akan menjadiminIntrinsicHeight
maksimum dariText
. Divider
kemudian memperluasheight
-nya ke batasanheight
yang diberikan olehRow
.
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