Eine der Regeln von Compose besteht darin, dass Sie Ihre untergeordneten Elemente nur einmal messen sollten. Bei zweimaligen Messungen von untergeordneten Elementen wird eine Laufzeitausnahme ausgelöst. Manchmal benötigen Sie jedoch Informationen über Ihre Kinder, bevor Sie sie messen.
Mit Intrinsik können Sie Kinder abfragen, bevor sie tatsächlich gemessen werden.
Bei einer zusammensetzbaren Funktion können Sie nach intrinsicWidth
oder intrinsicHeight
fragen:
(min|max)IntrinsicWidth
: Wie hoch ist angesichts dieser Höhe die minimale/maximale Breite, mit der du deine Inhalte richtig darstellen kannst?(min|max)IntrinsicHeight
: Wie hoch ist angesichts dieser Breite die minimale/maximale Höhe, mit der du deine Inhalte richtig darstellen kannst?
Wenn Sie beispielsweise die minIntrinsicHeight
einer Text
mit unendlichem width
abfragen, wird der height
des Text
zurückgegeben, als ob der Text in einer einzelnen Zeile gezeichnet wäre.
Intrinsik in der Praxis
Stellen Sie sich vor, wir möchten eine zusammensetzbare Funktion erstellen, die zwei Texte auf dem Bildschirm anzeigt, die durch eine Trennlinie wie die folgende voneinander getrennt sind:
Wie gehen wir vor? Wir können ein Row
mit zwei Text
-Elementen verwenden, das sich so weit wie möglich erweitert, und einem Divider
in der Mitte. Die Divider
soll so hoch wie die höchste Text
und dünn sein (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 ) 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
den gesamten Bildschirm einnimmt, und das ist nicht das gewünschte Ergebnis:
Dies liegt daran, dass Row
jedes untergeordnete Element einzeln misst und die Höhe von Text
nicht zur Einschränkung von Divider
verwendet werden kann. Wir möchten, dass Divider
den verfügbaren Bereich mit einer bestimmten Höhe füllt. Dazu können wir den height(IntrinsicSize.Min)
-Modifikator verwenden .
height(IntrinsicSize.Min)
gibt die Größe der untergeordneten Elemente an, die so groß wie ihre minimale Größe sind. Da es rekursiv ist, werden Row
und die untergeordneten minIntrinsicHeight
abgefragt.
Wenn Sie 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 der Vorschau:
Der minIntrinsicHeight
der zusammensetzbaren Funktion Row
ist der maximale minIntrinsicHeight
ihrer untergeordneten Elemente. Der minIntrinsicHeight
des Divider
-Elements ist 0, da er keinen Platz einnimmt, wenn keine Einschränkungen angegeben sind. Der Text
minIntrinsicHeight
entspricht dem Text mit einem bestimmten width
. Daher ist die Einschränkung height
des Row
-Elements der maximale minIntrinsicHeight
der Text
-Werte. Divider
erweitert dann seine height
um die durch Row
vorgegebene Einschränkung height
.
Intrinsik in Ihren benutzerdefinierten Layouts
Beim Erstellen eines benutzerdefinierten Layout
- oder layout
-Modifikators werden intrinsische Messungen automatisch anhand von Näherung 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 Messungen des benutzerdefinierten Layout
angeben möchten, überschreiben Sie beim Erstellen die minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
und maxIntrinsicHeight
der MeasurePolicy
-Oberfläche.
@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