Eine der Regeln von Compose besteht darin, dass Sie Ihre untergeordneten Elemente nur einmal messen sollten. Bei zweimaliger Messung von untergeordneten Elementen wird eine Laufzeitausnahme ausgelöst. Manchmal benötigen Sie jedoch Informationen über Ihre Kinder, bevor Sie sie messen.
Mit Intrinsics können Sie untergeordnete Elemente abfragen, bevor sie tatsächlich gemessen werden.
Bei einer zusammensetzbaren Funktion können Sie nach intrinsicWidth
oder intrinsicHeight
fragen:
(min|max)IntrinsicWidth
: Was ist angesichts dieser Breite die minimale/maximale Breite, mit der Sie Ihre Inhalte richtig darstellen können?(min|max)IntrinsicHeight
: Was ist angesichts dieser Höhe die minimale/maximale Höhe, die Sie Ihre Inhalte angemessen darstellen können?
Wenn Sie beispielsweise das minIntrinsicHeight
einer Text
mit unendlichem height
fragen, wird das height
des Text
zurückgegeben, als ob der Text in einer einzelnen Zeile gezeichnet wurde.
Intrinsik in Aktion
Stellen Sie sich vor, wir möchten eine zusammensetzbare Funktion erstellen, die zwei Texte auf dem Bildschirm getrennt durch eine Trennlinie anzeigt:
Wie können wir das tun? Wir können eine Row
mit zwei Text
-Elementen haben, die so weit wie möglich erweitert werden, und einer Divider
in der Mitte. Divider
soll so hoch wie das höchste Text
und dünn (width = 1.dp
) sein.
@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 ) Divider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
In der Vorschau sehen wir, dass Divider
auf den gesamten Bildschirm maximiert wird. Das ist nicht das, was wir möchten:
Dies liegt daran, dass Row
jedes untergeordnete Element einzeln misst und die Größe von Text
nicht verwendet werden kann, um Divider
einzuschränken. Wir möchten, dass Divider
den verfügbaren Platz
mit einer bestimmten Höhe füllt. Dazu können wir den height(IntrinsicSize.Min)
-Modifikator verwenden .
Bei height(IntrinsicSize.Min)
wird festgelegt, dass seine untergeordneten Elemente so hoch sein müssen wie ihre Mindesthöhe. Da sie rekursiv ist, werden Row
und die untergeordneten minIntrinsicHeight
abgefragt.
Wenn wir dies auf unseren Code anwenden, funktioniert es wie erwartet:
@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 ) Divider( 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") } } }
Mit Vorschau:
minIntrinsicHeight
der zusammensetzbaren Funktion der Row
ist das Maximum von minIntrinsicHeight
der untergeordneten Elemente. Das minIntrinsicHeight
des Divider
-Elements ist 0, da es keinen Platz belegt, wenn keine Einschränkungen angegeben sind. Das Text
-minIntrinsicHeight
ist der Text des Texts für eine bestimmte width
. Daher ist die Einschränkung height
des Row
-Elements die maximale minIntrinsicHeight
der Text
. Divider
erweitert dann sein height
auf die durch Row
vorgegebene Einschränkung height
.
Intrinsische Elemente in Ihren benutzerdefinierten Layouts
Wenn Sie einen benutzerdefinierten Layout
- oder layout
-Modifikator erstellen, werden intrinsische Messwerte automatisch auf der Grundlage von Näherungswerte berechnet. Daher sind die Berechnungen möglicherweise nicht für alle Layouts korrekt. Diese APIs bieten Optionen zum Überschreiben dieser Standardeinstellungen.
Wenn Sie die intrinsischen Messwerte Ihrer benutzerdefinierten Layout
angeben möchten, überschreiben Sie minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
und maxIntrinsicHeight
der MeasurePolicy
-Oberfläche beim Erstellen.
@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. } ) }
Überschreiben Sie beim Erstellen des benutzerdefinierten layout
-Modifikators die zugehörigen Methoden in der LayoutModifier
-Schnittstelle.
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. }
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Benutzerdefinierte Layouts {:#custom-layouts }
- Ausrichtungslinien in Jetpack Compose
- Jetpack-Compose-Phasen