Eine der Regeln von Compose besagt, dass Sie Ihre untergeordneten Elemente nur einmal messen sollten. Wenn Sie sie zweimal messen, wird eine Laufzeitausnahme ausgelöst. Es gibt jedoch Situationen, in denen Sie vor der Messung einige Informationen zu Ihren Kindern benötigen.
Mithilfe von „Intrinsics“ können Sie untergeordnete Elemente abfragen, bevor sie tatsächlich gemessen werden.
Sie können für ein Composeable die intrinsicWidth
oder intrinsicHeight
anfordern:
(min|max)IntrinsicWidth
: Was ist bei dieser Breite die Mindest-/Maximalbreite, mit der Sie Ihre Inhalte richtig malen können?(min|max)IntrinsicHeight
: Was ist bei dieser Höhe die Mindest-/Höchsthöhe, bei der Sie Ihre Inhalte richtig malen 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.
Intrinsische Funktionen 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. Die Divider
soll so hoch wie die höchste Text
sein und dünn (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 ) HorizontalDivider( 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 das Divider
auf den gesamten Bildschirm maximiert wird. Das ist nicht das, was wir wollen:
Dies liegt daran, dass Row
jedes untergeordnete Element einzeln misst und die Größe von Text
nicht zur Einschränkung von Divider
verwendet werden kann. Wir möchten, dass das Divider
den verfügbaren Raum mit einer bestimmten Höhe füllt. Dazu können wir den Modifikator height(IntrinsicSize.Min)
verwenden .
height(IntrinsicSize.Min)
legt die Größe seiner untergeordneten Elemente fest, die so hoch sein müssen wie ihre minimale intrinsische Höhe. Da sie rekursiv ist, werden Row
und seine untergeordneten Elemente minIntrinsicHeight
abgefragt.
Wenn wir das auf unseren Code anwenden, funktioniert er 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 ) HorizontalDivider( 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:
Der Wert für minIntrinsicHeight
des Row
-Elements ist der maximale Wert für minIntrinsicHeight
seiner untergeordneten Elemente. Das minIntrinsicHeight
des Divider
-Elements ist 0, da es keinen Platz beansprucht, wenn keine Einschränkungen angegeben sind. Das minIntrinsicHeight
des Text
entspricht dem des Textes, der eine bestimmte width
hat. Daher ist die height
-Einschränkung des Row
-Elements die maximale minIntrinsicHeight
der Text
-Werte. Divider
erweitert dann sein height
auf die durch Row
vorgegebene Einschränkung height
.
Intrinsics in benutzerdefinierten Layouts
Wenn Sie einen benutzerdefinierten Layout
- oder layout
-Modifikator erstellen, werden die intrinsischen Messwerte automatisch anhand von Näherungen 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
- Phasen von Jetpack Compose