Jedna z zasad Compose mówi, że elementy podrzędne należy mierzyć tylko raz. Dwukrotne mierzenie elementów podrzędnych powoduje wyjątek w czasie działania. Czasami jednak przed pomiarem elementów podrzędnych potrzebujesz pewnych informacji na ich temat.
Intrinsics umożliwia wysyłanie zapytań do elementów podrzędnych, zanim zostaną one zmierzone.
W przypadku elementu kompozycyjnego możesz poprosić o jego IntrinsicSize.Min lub IntrinsicSize.Max:
Modifier.width(IntrinsicSize.Min)– jaka jest minimalna szerokość potrzebna do prawidłowego wyświetlania treści?Modifier.width(IntrinsicSize.Max)– jaka jest maksymalna szerokość potrzebna do prawidłowego wyświetlania treści?Modifier.height(IntrinsicSize.Min)– jaka jest minimalna wysokość potrzebna do prawidłowego wyświetlania treści?Modifier.height(IntrinsicSize.Max)– jaka jest maksymalna wysokość potrzebna do prawidłowego wyświetlania treści?
Jeśli na przykład w układzie niestandardowym poprosisz o minIntrinsicHeight elementu Text z nieskończonymi ograniczeniami width, zwróci on height elementu Text z tekstem narysowanym w jednym wierszu.
Intrinsics w praktyce
Możesz utworzyć funkcję kompozycyjną, która wyświetla na ekranie 2 teksty oddzielone separatorem:
Aby to zrobić, użyj elementu Row z 2 elementami kompozycyjnymi Text, które wypełniają dostępną przestrzeń, oraz elementu Divider pośrodku. Element Divider powinien być tak wysoki jak najwyższy element Text i cienki (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 ) } }
Element Divider rozszerza się na cały ekran, co nie jest pożądanym zachowaniem:
Dzieje się tak, ponieważ element Row mierzy każdy element podrzędny osobno, a wysokości elementu Text nie można użyć do ograniczenia elementu Divider.
Aby element Divider wypełniał dostępną przestrzeń o określonej wysokości, użyj modyfikatora height(IntrinsicSize.Min).
height(IntrinsicSize.Min) zmienia rozmiar elementów podrzędnych tak, aby były tak wysokie jak ich minimalna wysokość intrinsics. Ponieważ ten modyfikator jest rekurencyjny, wysyła zapytanie o minIntrinsicHeight elementu Row i jego elementów podrzędnych.
Zastosowanie tego modyfikatora w kodzie sprawia, że działa on zgodnie z oczekiwaniami:
@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") } } }
W podglądzie:
Wysokość elementu Row jest określana w ten sposób:
minIntrinsicHeightelementu kompozycyjnegoRowto maksymalna wartośćminIntrinsicHeightjego elementów podrzędnych.minIntrinsicHeightelementuDividerwynosi 0, ponieważ nie zajmuje on miejsca, jeśli nie podano żadnych ograniczeń.minIntrinsicHeightelementuTextto wysokość tekstu dla określonejwidth.- Dlatego ograniczenie
heightelementuRowstaje się maksymalną wartościąminIntrinsicHeightelementówText. - Następnie element
Dividerrozszerza swojąheightdo ograniczeniaheightpodanego przez elementRow.
Intrinsics w układach niestandardowych
Podczas tworzenia niestandardowego modyfikatora Layout lub layout pomiary intrinsics są obliczane automatycznie na podstawie przybliżeń. Dlatego obliczenia mogą nie być prawidłowe w przypadku wszystkich układów. Te interfejsy API oferują opcje zastępowania tych wartości domyślnych.
Aby określić pomiary intrinsics niestandardowego elementu Layout, podczas jego tworzenia zastąp wartości
minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth, i
maxIntrinsicHeight interfejsu MeasurePolicy.
@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. } ) }
Podczas tworzenia niestandardowego modyfikatora layout zastąp powiązane metody w interfejsie 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. }
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Układy niestandardowe {:#custom-layouts}
- Linie wyrównania w Jetpack Compose
- Fazy Jetpack Compose