Una delle regole di Compose è che i figli devono essere misurati una sola volta; misurare i figli due volte genera un'eccezione di runtime. Tuttavia, a volte hai bisogno di alcune informazioni sui tuoi figli prima di misurarli.
Gli intrinseci ti consentono di eseguire query sui bambini prima che vengano effettivamente misurati.
Per un componente componibile, puoi chiedere il IntrinsicSize.Min
o il IntrinsicSize.Max
:
Modifier.width(IntrinsicSize.Min)
- Qual è la larghezza minima necessaria per visualizzare correttamente i tuoi contenuti?Modifier.width(IntrinsicSize.Max)
- Qual è la larghezza massima necessaria per visualizzare correttamente i contenuti?Modifier.height(IntrinsicSize.Min)
- Qual è l'altezza minima necessaria per visualizzare correttamente i contenuti?Modifier.height(IntrinsicSize.Max)
- Qual è l'altezza massima necessaria per visualizzare correttamente i tuoi contenuti?
Ad esempio, se chiedi il minIntrinsicHeight
di un Text
con vincoli width
infiniti in un layout personalizzato, viene restituito il height
del Text
con il testo disegnato su una sola riga.
Funzioni intrinseche in azione
Puoi creare un composable che visualizzi due testi sullo schermo separati da un divisore:
Per farlo, utilizza un Row
con due componibili Text
che riempiono lo spazio
disponibile e un Divider
al centro. Divider
deve essere alto quanto
il Text
più alto e deve essere sottile (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 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
Il Divider
si espande a tutto lo schermo, il che non è il comportamento desiderato:
Ciò accade perché Row
misura ogni bambino singolarmente e l'altezza di
Text
non può essere utilizzata per vincolare Divider
.
Per fare in modo che Divider
riempia lo spazio disponibile con un'altezza specifica,
utilizza il modificatore height(IntrinsicSize.Min)
.
height(IntrinsicSize.Min)
dimensiona i relativi elementi secondari in modo che siano alti quanto la loro altezza intrinseca minima. Poiché questo modificatore è ricorsivo, esegue query sul
minIntrinsicHeight
di Row
e dei relativi elementi secondari.
L'applicazione di questo modificatore al codice fa sì che funzioni come previsto:
@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") } } }
Con anteprima:
L'altezza di Row
è determinata come segue:
- L'
minIntrinsicHeight
del composableRow
è il valore massimominIntrinsicHeight
dei suoi elementi secondari. - Il valore
minIntrinsicHeight
dell'elementoDivider
è 0, in quanto non occupa spazio se non vengono forniti vincoli. - Il
Text
minIntrinsicHeight
è quello del testo per unwidth
specifico. - Pertanto, il vincolo
height
dell'elementoRow
diventa il valore massimominIntrinsicHeight
deiText
. - Il
Divider
espande quindi il suoheight
al vincoloheight
fornito dalRow
.
Intrinseci nei layout personalizzati
Quando crei un modificatore Layout
o layout
personalizzato, le misurazioni intrinseche
vengono calcolate automaticamente in base alle approssimazioni. Pertanto, i calcoli potrebbero non essere corretti per tutti i layout. Queste API offrono opzioni
per ignorare questi valori predefiniti.
Per specificare le misurazioni intrinseche del tuo Layout
personalizzato, esegui l'override di
minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
e
maxIntrinsicHeight
dell'interfaccia MeasurePolicy
durante la creazione.
@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. } ) }
Quando crei il modificatore layout
personalizzato, esegui l'override dei metodi correlati
nell'interfaccia LayoutModifier
.
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. }
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Layout personalizzati {:#custom-layouts}
- Linee di allineamento in Jetpack Compose
- Fasi di Jetpack Compose