はじめに
Cloud NextでJetpack Composeは発表され、先日Android Dev Summitでは、大幅なアップデート行われました。
Jetpack Composeのレイアウトを制御するコンポーネントは以下のような階層構造になっています。
下位の階層ほど汎用的なコンポーネントになっています。
上位のコンポーネントは、下位のコンポーネントをラッパーしたものになっており、指定できる機能が限定されています。
これらの階層構造から実際にそれぞれの役割がどのように異なるのかを理解していきたいと思いますが、今回はまずColumnとRowの実際の挙動を確認することで、ColumnとRowの役割を明確にすることでFlexとの違いを理解する第一歩としたいと思います。
Column基本
縦に内部の要素が並びます。
Column {
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
ColumnにLayoutModifierを指定
引数modifilerにはLayoutModifier型を指定して、カラムのサイズなどを指定できます。
指定しない場合は、Modifier.None が指定されます。
modifierにWidthを指定
カラムの幅が40dpになるのでボタンもそれに伴い縮びます。
Column(modifier = Width(40.dp)){
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
modifierにHeightを指定
カラムの高さが400dpになるので、一部のボタンが表示されません。
Column(modifier = Height(400.dp)){
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
WidthとHeightを指定する場合は、Sizeを利用します。
Column(modifier = Size(width = 400.dp, height = 100.dp)){
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
modifierにExpandedを指定
利用できるスペースをすべて使うように拡大されます。
わかりやすいように背景のカラーを設定します。
- None
Surface(color = Color.Gray) {
Column(modifier = Modifier.None) { // 指定しない場合はNoneになる
Surface(color = Color.Black) {
Column(modifier = Width(100.dp)) {
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
}
}
}
- Expanded
Surface(color = Color.Gray) {
Column(modifier = Expanded) {
Surface(color = Color.Black) {
Column(modifier = Width(100.dp)) {
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
}
}
}
他にはExpandedHeight、ExpandedWidthも存在します。
wrapを用いて複数のmodifierの指定
最初に書いた方が優先されるので、以下の例ではSizeで指定した高さ10px、はHeightで指定した高さ100.dpに上書きされます。
Column(modifier = Height(100.dp) wraps Size(width = 100.dp , height = 10.dp)){
(1..50).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
他にもModifierが用意されていそうですが、すべてを一覧で確認するドキュメントが見つからなかったためわかりませんでした。
ColumnにArrangementを指定
arrangementは配置を意味します。
デフォルトでは Arrangement.Begin
が指定されています。
以降の例では、Column自体が内部のコンテンツのサイズに縮まってしまうと表示結果に違いがでないため、modifilerにExpandedを指定して説明します。
arrangementにArrangement.Endを指定
終端に並びます。
Column(
modifier = Expanded,
arrangement = Arrangement.End
){
(1..3).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
arrangementにArrangement.Centerを指定
中央に並びます。
Column(
modifier = Expanded,
arrangement = Arrangement.Center
){
(1..3).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
arrangementにArrangement.SpaceAroundを指定
子要素間に等間隔に並べます。開始地点と子要素、子要素と終了地点の間は子要素間のスペースの半分になります。
Column(
modifier = Expanded,
arrangement = Arrangement.SpaceAround
){
(1..3).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
arrangementにArrangement.SpaceBetweenを指定
子要素間が等間隔に並びます。開始地点、終了地点のスペースはありません。
Column(
modifier = Expanded,
arrangement = Arrangement.SpaceBetween
){
(1..3).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
arrangementにArrangement.SpaceEvenlyを指定
開始地点、子要素間、終了地点が等間隔に並びます。
Column(
modifier = Expanded,
arrangement = Arrangement.SpaceEvenly
){
(1..3).toList().map { it.toString() }.forEach { name ->
Button(name)
}
}
Rowとの違い
RowについてもColumnが縦に子要素を並べるのに対して、横に並べるだけで挙動は同じです。
Flexとの違い
FlexにはColumnに存在しないMainAxisAlignmentとCrossAxisAlignmentが存在します。
MainAxisAlignmentは内部的にはArrangementを持っており、また FlexはFlexLayoutの arrangement = mainAxisAlignment.arrangement
を渡していることからも同じ役割であることがわかります。
CrossAxisAlignmentは、新規に追加されている値で、おそらくColumnの場合は横方向、Rowの場合は縦方向にレイアウトの制御を行うものだと考えられます。
まとめ
Columnを例にLayoutModifierとArrangementについて説明しました。
Column, RowとFlexの違いはCrossAxisAlignmentにあることがわかりました。
次回はFlex、FlexColumn、FlexRowを調査します。