13
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Android Advent Calendar 2019

Day 24

ColumnとRowで理解するJetpack Composeのレイアウト基礎

Last updated at Posted at 2019-12-24

はじめに

Cloud NextでJetpack Composeは発表され、先日Android Dev Summitでは、大幅なアップデート行われました。

Jetpack Composeのレイアウトを制御するコンポーネントは以下のような階層構造になっています。
下位の階層ほど汎用的なコンポーネントになっています。
上位のコンポーネントは、下位のコンポーネントをラッパーしたものになっており、指定できる機能が限定されています。

jc1.png

これらの階層構造から実際にそれぞれの役割がどのように異なるのかを理解していきたいと思いますが、今回はまずColumnとRowの実際の挙動を確認することで、ColumnとRowの役割を明確にすることでFlexとの違いを理解する第一歩としたいと思います。

Column基本

縦に内部の要素が並びます。

    Column {
        (1..50).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577164971.png

ColumnにLayoutModifierを指定

引数modifilerにはLayoutModifier型を指定して、カラムのサイズなどを指定できます。
指定しない場合は、Modifier.None が指定されます。

modifierにWidthを指定

カラムの幅が40dpになるのでボタンもそれに伴い縮びます。

    Column(modifier = Width(40.dp)){
        (1..50).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577166390.png

modifierにHeightを指定

カラムの高さが400dpになるので、一部のボタンが表示されません。

    Column(modifier = Height(400.dp)){
        (1..50).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577166678.png

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)
                    }
                }
            }
        }
    }

Screenshot_1577693774.png

  • 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)
                    }
                }
            }
        }
    }

Screenshot_1577693870.png

他には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)
        }
    }

Screenshot_1577169640.png

他にも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)
        }
    }

Screenshot_1577167692.png

arrangementにArrangement.Centerを指定

中央に並びます。

    Column(
        modifier = Expanded,
        arrangement = Arrangement.Center
    ){
        (1..3).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577167842.png

arrangementにArrangement.SpaceAroundを指定

子要素間に等間隔に並べます。開始地点と子要素、子要素と終了地点の間は子要素間のスペースの半分になります。

    Column(
        modifier = Expanded,
        arrangement = Arrangement.SpaceAround
    ){
        (1..3).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577167896.png

arrangementにArrangement.SpaceBetweenを指定

子要素間が等間隔に並びます。開始地点、終了地点のスペースはありません。

    Column(
        modifier = Expanded,
        arrangement = Arrangement.SpaceBetween
    ){
        (1..3).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577167953.png

arrangementにArrangement.SpaceEvenlyを指定

開始地点、子要素間、終了地点が等間隔に並びます。

    Column(
        modifier = Expanded,
        arrangement = Arrangement.SpaceEvenly
    ){
        (1..3).toList().map { it.toString() }.forEach { name ->
            Button(name)
        }
    }

Screenshot_1577167992.png

Rowとの違い

RowについてもColumnが縦に子要素を並べるのに対して、横に並べるだけで挙動は同じです。

Screenshot_1577165219.png

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を調査します。

13
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?