Closed4
ComposeのLayoutを調べてみる

参考になる記事

インターフェースはこんな感じ
@UiComposable
@Composable
inline fun Layout(
content: @Composable @UiComposable () -> Unit,
modifier: Modifier = Modifier,
measurePolicy: MeasurePolicy
) {
何に使われているか
ColumnとかRowとかの内部で使われている。
@Composable
inline fun Column(
modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
content: @Composable ColumnScope.() -> Unit
) {
val measurePolicy = columnMeasurePolicy(verticalArrangement, horizontalAlignment)
Layout( // ←使われている
content = { ColumnScopeInstance.content() },
measurePolicy = measurePolicy,
modifier = modifier
)
}
MeasurePolicyを定義しておくと、contentsをそれに沿って画面に配置してくれる。
例えばRow用のMeasurePolicyはライブラリ内で定義している。

書いてみた
@Composable
fun LayoutTest() {
Layout(
content = {
Text("Hoge")
Text("Piyo")
},
modifier = Modifier.fillMaxSize(),
measurePolicy = { measurables, constraints ->
layout(constraints.minWidth, constraints.maxHeight) {
measurables[0].measure(constraints).place(IntOffset.Zero)
measurables[1].measure(constraints).place(IntOffset.Zero)
}
}
)
}
どんな風に描画されるか
なぜそのように描画されるか
layout(constraints.minWidth, constraints.maxHeight) {
measurables[0].measure(constraints).place(IntOffset.Zero)
measurables[1].measure(constraints).place(IntOffset.Zero)
}
measurable[0]は"Hoge"を表している
measurable[1]は"Piyo"を表している
place(IntOffset.Zero)で(x,y)=(0,0)
に配置している。

Alignmentで位置を計算できる
@Composable
fun LayoutTest() {
Layout(
content = {
Text(
text = "Hoge",
modifier = Modifier
.background(Color.Red)
.wrapContentSize() // [1]
)
Text(
text = "Piyo",
modifier = Modifier
.background(Color.Blue)
.wrapContentSize() // [1]
)
},
modifier = Modifier.fillMaxSize(),
measurePolicy = { measurables, constraints ->
layout(constraints.minWidth, constraints.maxHeight) {
val hoge = measurables[0].measure(Constraints())// [2] 制約なし
val hogePosition = Alignment.TopCenter.align(
size = IntSize(hoge.width, hoge.height), // [3] wrapoContentのサイズが得られる
space = IntSize(constraints.maxWidth, constraints.maxHeight),
layoutDirection,
)
hoge.place(hogePosition)
val piyo = measurables[1].measure(Constraints())
val piyoPosition = hogePosition.copy(y = hogePosition.y + 100) // [4] piyoの下に100だけ移動
piyo.place(piyoPosition)
}
}
)
}
このスクラップは2023/10/01にクローズされました