Jedna z zasad Compose mówi, że elementy podrzędne należy mierzyć tylko raz. Dwukrotne pomiary powodują wyjątek w czasie działania. Czasami jednak przed zmierzeniem dzieci potrzebujesz pewnych informacji na ich temat.
Pomiar wbudowany umożliwia wysyłanie zapytań o elementy podrzędne przed ich rzeczywistym pomiarem.
W przypadku funkcji kompozycyjnej możesz poprosić o IntrinsicSize.Min lub IntrinsicSize.Max:
Modifier.width(IntrinsicSize.Min)– Jaka jest minimalna szerokość, która jest potrzebna do prawidłowego wyświetlania treści?Modifier.width(IntrinsicSize.Max)– Jaka jest maksymalna szerokość, której potrzebujesz, aby prawidłowo wyświetlać 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ść, której potrzebujesz, aby prawidłowo wyświetlać treści?
Jeśli na przykład zapytasz o minIntrinsicHeight elementu Text z ograniczeniami width w układzie niestandardowym, zwróci on height elementu Text z tekstem narysowanym w jednym wierszu.
Funkcje pierwotne w akcji
Możesz utworzyć komponent, który wyświetla na ekranie 2 teksty oddzielone separatorem:
W tym celu użyj elementu Row z 2 komponentami Text, które wypełniają dostępną przestrzeń, oraz elementu Divider pośrodku. Divider powinna być tak wysoka jak najwyższa Text i cienka (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ż Row mierzy każde dziecko osobno, a wysokość Text nie może być używana do ograniczania Divider.
Aby element Divider wypełniał dostępne miejsce o określonej wysokości, użyj modyfikatora height(IntrinsicSize.Min).
height(IntrinsicSize.Min) dostosowuje wysokość elementów podrzędnych do ich minimalnej wysokości wewnętrznej. Ten modyfikator jest rekurencyjny, więc wysyła zapytanie o minIntrinsicHeight elementu Row i jego elementów podrzędnych.
Zastosowanie tego modyfikatora w kodzie sprawi, że będzie on działać 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") } } }
Z podglądem:
Wysokość Row jest określana w ten sposób:
- Wartość
Rowelementu kompozycyjnegominIntrinsicHeightjest maksymalną wartościąminIntrinsicHeightjego elementów podrzędnych. - Wartość
minIntrinsicHeightelementuDividerwynosi 0, ponieważ nie zajmuje on miejsca, jeśli nie podano żadnych ograniczeń. TextminIntrinsicHeightto tekst dla konkretnegowidth.- Dlatego ograniczenie
heightelementuRowstaje się maksymalną wartościąminIntrinsicHeightelementówText. - Wtedy
Dividerrozszerza swójheightdo ograniczeniaheightpodanego przezRow.
Wartości wewnętrzne w układach niestandardowych
Podczas tworzenia niestandardowego modyfikatora Layout lub layout pomiary wewnętrzne 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 ustawień domyślnych.
Aby określić pomiary wewnętrzne 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