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 wbudowane 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ść 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 język JavaScript jest wyłączony.
- Układy niestandardowe {:#custom-layouts}
- Linie wyrównania w Jetpack Compose
- Etapy Jetpack Compose
