Jedną z zasad Compose jest to, że elementy podrzędne należy mierzyć tylko raz. Dwukrotne zmierzenie elementów podrzędnych powoduje wyjątek czasu działania. Czasami jednak przed pomiarem dzieci potrzebujesz pewnych informacji na ich temat.
Funkcje wewnętrzne umożliwiają wysyłanie zapytań do elementów podrzędnych, 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 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ść, która pozwoli prawidłowo wyświetlać treści?Modifier.height(IntrinsicSize.Max)– jaka jest maksymalna wysokość, która jest potrzebna do prawidłowego wyświetlania treści?
Jeśli na przykład zapytasz o minIntrinsicHeight elementu Text z nieskończonymi ograniczeniami width w niestandardowym układzie, zwróci on height elementu Text z tekstem narysowanym w jednym wierszu.
Funkcje pierwotne w akcji
Możesz utworzyć element kompozycyjny, który wyświetla na ekranie 2 teksty oddzielone separatorem:
Aby to zrobić, użyj elementu Row z 2 komponentami kompozycyjnymi Text, które wypełniają dostępne miejsce, i elementem Divider pośrodku. Divider powinien być tak wysoki jak najwyższy Text i powinien być 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 ) } }
Divider rozszerza się na cały ekran, co nie jest pożądanym zachowaniem:
Dzieje się tak, ponieważ Row mierzy każdy element podrzędny osobno, a wysokości Text nie można użyć do ograniczenia Divider.
Aby Divider wypełniał dostępną przestrzeń o określonej wysokości, użyj modyfikatora height(IntrinsicSize.Min).
height(IntrinsicSize.Min) dostosowuje rozmiar elementów podrzędnych, aby ich wysokość była równa minimalnej wysokości wewnętrznej. Ten modyfikator jest rekurencyjny, więc wysyła zapytanie do minIntrinsicHeight elementu 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 kompozycyjnegoRowto maksymalna wartośćminIntrinsicHeightjego elementów podrzędnych. - Wartość
minIntrinsicHeightelementuDividerwynosi 0, ponieważ nie zajmuje on miejsca, jeśli nie podano ograniczeń. TextminIntrinsicHeightto tekst dla konkretnego elementuwidth.- Dlatego ograniczenie
heightelementuRowstaje się maksymalną wartościąminIntrinsicHeightelementówText. - Następnie
Dividerrozszerzaheightdo ograniczeniaheightpodanego przezRow.
Wymiary wewnętrzne w niestandardowych układach
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 tworzenia zastąp właściwoś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