android: Composableのレイアウト (1)
2024/10/04
Android Codelabs の Compose UIに関する最初のコースをやっている。
そして、やってみましょう的なところで詰まってしまった。
4. Compose 象限というページで、同じ構成のカードを文言だけ変更して4枚並べるというだけ。
ただそれだけだというのに。。。
ヒントとして Weight modifier
を使うことが書かれているので、どういう動作をするか簡単に見ておく。
このコースの途中にあった HappyBirthday サンプルにプレビューだけ突っ込んだ。
テーマ名がHappyBirthdayTheme
なところ以外は他でも使えるだろう。
@Preview(
name = "sample",
showBackground = true,
)
@Composable
fun SamplePreview() {
@Composable
fun innerCard(modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Text(text = "Happy Birthday Tom!")
Text(text = "from Jerry")
}
}
HappyBirthdayTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Red,
) {
Column {
innerCard(
modifier = Modifier
.background(Color.Blue)
.weight(0.5F)
)
Row {
innerCard(
modifier = Modifier
.background(Color.Green)
.weight(0.5F)
)
}
}
}
}
}
構成はこんな感じ。
HappyBirthday をベースにしていたので modifier などがちょっと違うが、今回見てみる内容と関係なさそうだったので気にしなくてよかろう。
図の AAA
が↑の innerCard
に当たる。
Column
でText
が2つ並んでいるだけである。
それをさらにColumn
で2つ並べている。
画面全体が見えないと分かりづらいのでSurface
でfillMaxSize()
している。
背景色は赤。
modifierとくになし
レイアウトに関する設定を特に行わないと、Text
はそれぞれ最初の領域を確保して左上に寄るようにレンダリングされた。
両方にfillMaxSize()
をつける
innerCard()
のmodifier
にfillMaxSize()
を付けて呼び出すと Column
のmodifier
として与えられる。
単に指定するだけだと、最初にレンダリングする部品が全部奪ってしまうようだ。
下だけfillMaxSize()
を付ける
先ほどは両方付けて先にレンダリングされる方?だけしか見えなかったので、今度は下の方にだけ付けてみた。
そうすると、先に上をレンダリングしたあとに下を最大にレンダリングしたのかこうなった。
両方にweight
を付ける
では両方に同じ重さのweight
を付けてみる。
横方向はそのままで縦の方向にweight
で指定した比率のレンダリングが行われた。
0.5F
のF
はC言語などと同じく単精度浮動小数点(Float
)定数ということだろう。
1
だと整数だからダメだし、1.0
だと倍精度(Double
)になるからそれはそれでダメなのだ。
上だけweight
を付ける
先ほどのfillMaxSize()
は片方だけ設定するとレンダリングされる順番のような感じだった。
weight
はどうなのかと上にだけ付けたが、こちらは下の方も描画された。
なんとなく、誰かがweight
を付けるとそれ以外の付けていない部品は最小限の大きさになるように見える。
間にもう1つ部品を入れて上2つにweight
を設定したが、一番下もレンダリングされた。
weight
が連続しない
weight
設定した部品に設定していない部品が挟まるとどうなるか。
特に関係なく、weight
での比率になりつつもweight
無しについてもレンダリングされる。
fillMaxWidth()
Column
で横に広げたい場合はfillMaxWidth()
か。
ColumnとRowが混ざる
Column
の中にColumn
を2つ入れていたが、その片方がRow
になったらどうなるのか。
まず、Row
に入れ込むだけだと特に変わりない。
両方にweight
を設定。
innerCard()
の引数なので、Row
に入れ込んだ方も最終的にはColumn
のmodifier
にweight
を設定していることになる。
これはどう解釈すると良いのか。
まず、weight
は直接設定したColumn
に対してではないというか、そのColumn
そのものに影響するわけではないことになる。
ありそうなのは、部品を配置しようとする上側の部品が配下の部品が持つweight
を見ている、という考え方だ。
先ほどは一番上のColumn
がその中に持つColumn
たちのweight
を見てサイズを決めていたのだ。
今回はRow
がその中のColumn
が持つweight
を見て、他に部品がないので横方向に目一杯引き延ばした、というわけだ。
そしてその上のColumn
は配下にRow
とColumn
を持っていて、weight
を設定していないRow
は最低限の大きさ、設定してあるColumn
は残りの領域を縦方向に目一杯引き延ばした、とすればつじつまがあう。
逆に下をRow
で囲むと、やはりそういうレンダリングになった。
おわりに
あってるかどうかわからんが、自分なりに解釈してみた。
しかしこれ、数個しかないからなんとかなるものの難しいな。
テストアプリくらいだったら何とかなる!と思いたい。