レイアウトによっては子のサイズに合わせて親のサイズに制約をかけたいことがあります。そういったケースでは IntrinsicSize.Max
や IntrinsicSize.Min
で対応できることがあります。
言葉だとうまく説明できない感じなので、例を見ながら確認していきます。
使用例
例えば、以下のようなコンテンツの横幅に合わせて Divider
を表示したい場合を考えてみます。
これを単純に実装しようとすると以下のようになると思います。
Column {
Text(text = "Upside Down Cake")
Divider()
Text(text = "Tiramisu")
Divider()
Text(text = "Snow Cone")
Divider()
Text(text = "Red Velvet Cake")
Divider()
}
これ実行すると、想定どおりにはならず Divider
が横幅いっぱいに表示されます。( Divider
にはデフォルトで fillMaxWidth
があるので省略してます)
これは子要素の幅が最大のものに合わせられると正しく表示されることになります。
IntrinsicSize.Max / IntrinsicSize.Min
子要素を最小/最大ものに合わせたい場合は IntrinsicSize.Max
や IntrinsicSize.Min
を使えます。
Column(
modifier = Modifier.width(IntrinsicSize.Max) // IntrinsicSize.Maxを指定
) {
Text(text = "Upside Down Cake")
Divider()
Text(text = "Tiramisu")
Divider()
Text(text = "Snow Cone")
Divider()
Text(text = "Red Velvet Cake")
Divider()
}
こうすることで、以下のように希望するような表示になります。
これを IntrinsicSize.Max
ではなく、 IntrinsicSize.Min
を使用すると、逆に子要素を最小のサイズに合わせるようにします。
Text
の最小サイズは1単語のサイズになります。そのため、この例だと1単語として一番長い Tiramisu の単語の幅に合わせられることになります。
Column(
modifier = Modifier.width(IntrinsicSize.Min)
) {
// ...
}
使用例2
他の例として、コンテンツの高さに応じて線を引きたいときにも使用できます。
Row(
modifier = Modifier.height(IntrinsicSize.Max) // コンテンツの高さする
) {
Divider(
modifier = Modifier
.width(1.dp)
.fillMaxHeight()
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(text = "Upside Down Cake")
Text(text = "Tiramisu")
Text(text = "Snow Cone")
Text(text = "Red Velvet Cake")
}
}
カスタムレイアウト対応
カスタムレイアウトを使用している場合は正しく実装しないとクラッシュすることがあります。
例えば、以下のように layout
のModifierを使用してる場合や、 Layout
のComposableを使用してるときです。
Row(
modifier = Modifier.height(IntrinsicSize.Max)
) {
// ...
// layoutのModifierを使用
Box(
modifier = Modifier
.layout { measurable, constraints ->
// ...
}
)
// LayoutのComposable
Layout(
content = {
// ...
}
) { measurables, constraints ->
// ...
}
}
layout
のModifierと Layout
のComposableで対応が若干異なります。
layout Modifier
そのまま layout
Modifierでは対応ができないので、 LayoutModifier
を使用する必要があります。この例だと maxIntrinsicHeight
をOverrideして対応する値を返します。
Row(
modifier = Modifier.height(IntrinsicSize.Max)
) {
// ...
Box(
modifier = Modifier
.then(
object : LayoutModifier {
override fun MeasureScope.measure(
measurable: Measurable,
constraints: Constraints
): MeasureResult {
// layout Modifierと同じ実装
}
override fun IntrinsicMeasureScope.maxIntrinsicHeight(
measurable: IntrinsicMeasurable,
width: Int
): Int {
// コンテンツが正しく描画できる最大の高さを返す(dpじゃなくてpx)
}
}
)
)
}
Layout Composable
Layout
Composableの場合は、 MeasurePolicy を使用して対応します。こちらも同様に maxIntrinsicHeight
をOverrideして対応します。
Row(
modifier = Modifier.height(IntrinsicSize.Max)
) {
// ...
Layout(
content = {
// ...
},
measurePolicy = object : MeasurePolicy {
override fun MeasureScope.measure(
measurables: List<Measurable>,
constraints: Constraints
): MeasureResult {
// Layoutの通常の実装
}
override fun IntrinsicMeasureScope.maxIntrinsicHeight(
measurables: List<IntrinsicMeasurable>,
width: Int
): Int {
// コンテンツが正しく描画できる最大の高さを返す(dpじゃなくてpx)
}
}
)
}