Eine der Regeln von Compose besagt, dass untergeordnete Elemente nur einmal gemessen werden sollten. Wenn untergeordnete Elemente zweimal gemessen werden, wird eine Laufzeit-Ausnahme ausgelöst. Es gibt jedoch Situationen, in denen Sie einige Informationen zu Ihren Kindern benötigen, bevor Sie sie messen können.
Mit intrinsischen Faktoren können Sie Kinder abfragen, bevor sie tatsächlich gemessen werden.
Sie können ein Composable nach seinem IntrinsicSize.Min oder IntrinsicSize.Max fragen:
Modifier.width(IntrinsicSize.Min): Welche Mindestbreite ist erforderlich, damit Ihre Inhalte richtig angezeigt werden?Modifier.width(IntrinsicSize.Max): Welche maximale Breite benötigen Sie, um Ihre Inhalte richtig darzustellen?Modifier.height(IntrinsicSize.Min)– Welche Mindesthöhe ist erforderlich, damit Ihre Inhalte richtig angezeigt werden?Modifier.height(IntrinsicSize.Max): Welche maximale Höhe benötigen Sie, um Ihre Inhalte richtig darzustellen?
Wenn Sie beispielsweise die minIntrinsicHeight eines Text mit unendlich vielen width-Einschränkungen in einem benutzerdefinierten Layout abfragen, wird die height des Text zurückgegeben, wobei der Text in einer einzigen Zeile dargestellt wird.
Intrinsische Funktionen in Aktion
Sie können eine Composable erstellen, die zwei Texte auf dem Bildschirm anzeigt, die durch eine Trennlinie getrennt sind:
Verwenden Sie dazu ein Row mit zwei Text-Composables, die den verfügbaren Platz ausfüllen, und ein Divider in der Mitte. Die Divider sollte so hoch wie die höchste Text sein 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 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
Das Divider wird auf den gesamten Bildschirm maximiert. Das ist nicht das gewünschte Verhalten:
Das liegt daran, dass Row jedes untergeordnete Element einzeln misst und die Höhe von Text nicht verwendet werden kann, um die Divider einzuschränken.
Wenn das Divider stattdessen den verfügbaren Platz mit einer bestimmten Höhe ausfüllen soll, verwenden Sie den Modifikator height(IntrinsicSize.Min).
height(IntrinsicSize.Min) legt die Höhe der untergeordneten Elemente auf die Mindesthöhe fest. Da dieser Modifikator rekursiv ist, werden die minIntrinsicHeight der Row und ihrer untergeordneten Elemente abgefragt.
Wenn Sie diesen Modifikator auf Ihren 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 ) 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") } } }
Mit Vorschau:
Die Höhe von Row wird so bestimmt:
- Der
minIntrinsicHeightdes zusammensetzbarenRowist der maximaleminIntrinsicHeightseiner untergeordneten Elemente. - Der
minIntrinsicHeightdesDivider-Elements ist 0, da es keinen Platz einnimmt, wenn keine Einschränkungen angegeben sind. - Der
TextminIntrinsicHeightist der Text für einen bestimmtenwidth. - Daher wird die
height-Einschränkung desRow-Elements zum maximalenminIntrinsicHeightderText. - Die
Dividererweitert dann ihreheightauf die durch dieRowvorgegebeneheight-Einschränkung.
Intrinsics in benutzerdefinierten Layouts
Wenn Sie einen benutzerdefinierten Layout- oder layout-Modifikator erstellen, werden die intrinsischen Messungen automatisch auf Grundlage von Schätzungen berechnet. Daher sind die Berechnungen möglicherweise nicht für alle Layouts korrekt. Diese APIs bieten Optionen zum Überschreiben dieser Standardwerte.
Wenn Sie die intrinsischen Messungen Ihres benutzerdefinierten Layout angeben möchten, überschreiben Sie beim Erstellen die minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth und maxIntrinsicHeight der MeasurePolicy-Schnittstelle.
@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. } ) }
Wenn Sie einen benutzerdefinierten layout-Modifikator erstellen, überschreiben Sie 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: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Benutzerdefinierte Layouts {:#custom-layouts}
- Ausrichtungslinien in Jetpack Compose
- Jetpack Compose-Phasen