Jedna z zasad Compose mówi, że dzieci należy mierzyć tylko raz. Dwukrotne zmierzenie dzieci powoduje wyjątek w czasie działania. Czasami jednak przed zmierzeniem dzieci potrzebujesz pewnych informacji na ich temat.
Intrinsics umożliwia wysyłanie zapytań dotyczących dzieci, zanim zostaną one zmierzone.
W przypadku funkcji kompozycyjnej możesz poprosić o jej IntrinsicSize.Min lub IntrinsicSize.Max:
Modifier.width(IntrinsicSize.Min)– jaka jest minimalna szerokość, która umożliwia prawidłowe wyświetlanie 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 w układzie niestandardowym zapytasz o minIntrinsicHeight elementu Text z ograniczeniami width, zwróci on height elementu Text z tekstem narysowanym w jednym wierszu.
Funkcje pierwotne w praktyce
Możesz utworzyć komponent, który wyświetla na ekranie 2 teksty oddzielone separatorem:
Aby to zrobić, użyj elementu Row z 2 komponentami 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ż 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 Row i jego elementów podrzędnych.
Zastosowanie tego modyfikatora do kodu 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ść elementu Row jest określana w ten sposób:
- Wartość
minIntrinsicHeightelementu kompozycyjnegoRowjest maksymalną wartościąminIntrinsicHeightjego elementów podrzędnych. - Wartość
minIntrinsicHeightelementuDividerwynosi 0, ponieważ nie zajmuje on miejsca, jeśli nie podano żadnych ograniczeń. - Wartość
TextminIntrinsicHeightto wartość tekstu dla konkretnego elementuwidth. - 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 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 JavaScript jest wyłączony.
- Układy niestandardowe {:#custom-layouts}
- Linie wyrównania w Jetpack Compose
- Etapy Jetpack Compose