STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

Jetpack Compose の Padding vs Spacer

Padding を使うのか Spacerを使うのか

こんにちは!STORES 決済 Androidエンジニアのみっちゃんです!

JetpackComposeでUIを作るときに、Composable同士の間に余白を置きたい時はpaddingSpacerを使って実現できます。

最近、STORES 決済 Android アプリではAndroidViewからJetpackComposeへ移行しているのですが、チームメンバー全員がCompose経験豊富なわけではなく、実装やレビュー時に「ここはpaddingを使った方がいいのか?Spacerなのか...??」と自信を持って実装・レビューできない!という問題がありました。

これを解決するために、どういう時にpaddingを使い、どういう時にSpacerを使うのかチーム内ルールを決めました!

使い分け

paddingを使いたい時

余白の対象が親子関係にある場合

コンポーザブルとその親となるレイアウトコンテナの間にスペースが必要な場合はpaddingを使用するのが適切です。

例えば下の画像のようにhogefoofugaの三つのテキストを縦に並べて、 赤矢印の部分に余白を与える場合を考えます。

hogefoofugaの三つのテキストComposableの親に、それらを縦に並べる役割のColumnがいます。赤矢印の余白は子Composableと親Composableとの間の余白なのでpaddingを使って以下のように実装できます。

@Composable
fun Hoge() {
   Column(
        modifier = Modifier
           .fillMaxWidth()
           .padding(vertical = 8.dp, horizontal = 4.dp) // Tips: paddingでColumnとその内部の要素間に余白を作る
    ) {
           Text(text = "hoge")
           Text(text = "foo")
           Text(text = "fuga")
    }
}

clickableな領域を考慮したい

なぜ親子関係のComposable同士の間に余白を置きたい場合はpaddingを使うと良いのでしょう。
それは、clickableな領域も考慮に入れて余白を設定できるからです。

例えば下の画像のように、>の画像だけでなくその周辺も余白をつけ、余白部分も含めてタップ可能にしたいとします。

このような場面では、先に.clickable{}を呼び出した後、続けてpaddingを呼び出して余白を設定すると良いです。

@Composable
fun GoBrowserImage() {
     Image(
        modifier = Modifier
           .clickable { /* do something */ }   // Tips: 先にclickableを呼び出す
           .padding(8.dp),    // Tips: その後にpaddingで余白の設定をする                    
        painter = painterResource(
           id = com.coiney.android.core.R.drawable.cy__icon_chevron_right_blue
        ),
        contentDescription = null
     )
}

hogefoofugaの三つのテキストを縦に並べるサンプルコードの場合だと、以下の実装のようにclickablepaddingを追加することによって余白領域も含めてタップ可能にすることができます。

@Composable
fun Hoge() {
   Column(
        modifier = Modifier
           .fillMaxWidth()
           .clickable { /* do something */ } 
           .padding(vertical = 8.dp, horizontal = 4.dp)
    ) {
           Text(text = "hoge")
           Text(text = "foo")
           Text(text = "fuga")
    }
}

Spacerを使いたい時

余白の対象が兄弟関係にある場合

一方でSpacerは、ColumnRowなどのレイアウトコンテナ内にある兄弟Composable同士の間に余白を追加したい時に使用します。

例えば下の画像のようにテキストComposable同士の間に赤矢印で示された余白を入れたいとします。

hogefoofugaは全てColumn内にあり、兄弟関係のComposableなのでSpacerを使って余白を配置します。

@Composable
fun Hoge() {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clickable { }
            .padding(vertical = 8.dp, horizontal = 4.dp)
    ) {
        Text(text = "hoge")
        Spacer(modifier = Modifier.height(12.dp)) // Tips: SpacerでColumn内のText間同士の間に隙間を作る
        Text(text = "foo")
        Spacer(modifier = Modifier.height(12.dp)) // Tips: SpacerでColumn内のText間同士の間に隙間を作る
        Text(text = "fuga")
    }
}

順番を簡単に変えられる

なぜ兄弟関係にあるコンポーザブルの間に余白を追加する場合はSpacerを使うと良いのでしょうか。
それは、コンポーネントの順番を変えたい場合に変更が容易だからです。

上記の場合だと、例えばfooテキストの位置をfugaと交代したいなど、コンポーネントの順番を変えたい時があると思います。

もしpaddingで余白を開けるアプローチをしていた場合、paddingをテキストコンポーザブル自身に設定しているので、配置の順番を変えることによってpaddingの付け替えをする手間が発生します。しかしSpacerで余白を追加していればその手間が必要なくなります。

参考記事

おわり

今後もSTORES 決済 Android のCompose移行を進めるにあたり不便がないよう、共通認識をどんどん整理していきます!頑張るぞい!