Eine der Regeln von „Compose“ besagt, dass Sie Ihre untergeordneten Elemente nur einmal erfassen sollten. bei zweimaligen Messungen einer Laufzeitausnahme. Es gibt jedoch Situationen, in denen Sie vor dem Messen einige Informationen zu Ihren Kindern benötigen.
Mit 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 aufgrund dieser Breite der minimale/maximale mit der Sie Ihre Inhalte richtig darstellen 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 nach der minIntrinsicHeight
eines Text
mit unendlicher height
fragen, wird die height
des Text
zurückgegeben, als wäre der Text in einer einzigen Zeile gezeichnet.
Intrinsik in Aktion
Angenommen, wir möchten ein Composeable erstellen, in dem zwei Texte auf dem Bildschirm angezeigt werden, die durch eine Trennlinie getrennt sind, so wie hier:
Wie können wir das tun? Wir können einen Row
mit zwei Text
s in der Mitte haben, die sich so weit wie möglich ausdehnen, und einen 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 Divider
den gesamten Bildschirm einnimmt und
wollen wir das nicht:
Das liegt daran, dass Row
jedes Kind einzeln misst und die Höhe von Text
nicht verwendet werden kann, um die Divider
einzuschränken. Wir möchten, dass die Divider
den verfügbaren Platz mit einer bestimmten Höhe. Dafür können wir den
height(IntrinsicSize.Min)
-Modifikator
height(IntrinsicSize.Min)
legt fest, dass seine untergeordneten Elemente so groß sind wie
ihre minimale intrinsische Höhe haben. Da sie rekursiv ist, fragt sie Row
ab
Kinder minIntrinsicHeight
.
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
-Beschränkung des Row
-Elements die maximale
minIntrinsicHeight
der Text
. Divider
erweitert dann seinen height
auf die height
-Einschränkung, die durch Row
vorgegeben ist.
Intrinsics in benutzerdefinierten Layouts
Wenn Sie einen benutzerdefinierten Layout
- oder layout
-Modifikator erstellen, sind intrinsische Messwerte
werden anhand von Schätzungen automatisch berechnet. Dementsprechend wird der
Berechnungen möglicherweise nicht für alle Layouts korrekt sind. Diese APIs bieten Optionen, um diese Standardwerte zu überschreiben.
So legst du die intrinsischen Messwerte deiner benutzerdefinierten Layout
fest:
minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
und maxIntrinsicHeight
der
MeasurePolicy
wenn Sie sie 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. } ) }
Beim Erstellen des benutzerdefinierten layout
-Modifikator die zugehörigen Methoden überschreiben
in der LayoutModifier
-Oberfläche.
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