【Jetpack Compose】Modifierの種類と使い方!カスタムで作成する方法
この記事からわかること
- Kotlin/Android Jetpack Composeの使い方
- Modifierの種類
- サイズ調整や位置、余白、影、枠線、背景色、タップジェスチャー
- カスタムModifierの作成方法
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Narwhal Feature Drop
- Kotlin:2.1.10
- Material3
- AGP:8.9.2
- Gradle:8.11.1
- Mac M1:Sequoia 15.6.1
Jetpack Compose自体の基本的な使用方法に関しては以下の記事を参考にしてください。
Modifier
公式リファレンス:Compose modifiers
公式リファレンス:Modifierオブジェクト
ModifierオブジェクトはJetpack ComposeにおいてUI要素のサイズやレイアウト、ジェスチャー、その他の特性を変更または設定するためのオブジェクトです。デフォルトで定義されているTextなどのComposable関数の引数の1つとして渡せるようになっており、柔軟にUIを制御することが可能になっています。
@Composable
fun Text(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
fontSize: TextUnit = TextUnit.Unspecified,
// 〜〜〜〜〜省略
)
Modifierには様々な拡張関数が用意されており呼び出す際にはModifier.メソッド名形式で呼び出していき、メソッドチェーンで異なる拡張関数を呼び出すことができるようになっています。
Text(
"Hello World!!",
// 横幅と高さを200dpにする
Modifier.width(200.dp).height(200.dp)
)
Modifierをメソッドチェーンで続けられる仕組み
例えばModifier.widthの定義を確認してみます。ここでのthisはModifier自体でそこからthenメソッドを呼び出しています。そしてそのthenメソッドにSizeElementインスタンスを渡している形になっています。SizeElementもModifierを継承したものと思えばOKです。
@Stable
fun Modifier.width(width: Dp) = this.then(
SizeElement(
minWidth = width,
maxWidth = width,
enforceIncoming = true,
inspectorInfo = debugInspectorInfo {
name = "width"
value = width
}
)
)
続いてthenの定義を確認してみると以下のようになっています。ここでは引数で受け取ったModifierが同じものならそのまま、異なるものならModifierを連結して返却しています。このようにModifierを複数リスト形式のような形で保持させることでメソッドチェーンで呼び出されて際にリストに追加していくような仕組みになっているようです。
infix fun then(other: Modifier): Modifier =
if (other === Modifier) this else CombinedModifier(this, other)
呼び出し順番が大事
ComposeのModifierは呼び出す順番によって反映され方が大きく異なってきます。仕組みとしては後に呼んだものが前に呼んだものの結果に影響するようになっており、Swift UIのモディファイアとは逆の形になっています。
Text("Hello")
.padding() // テキストの周りに余白
.background(Color.red) // テキストの周りの余白も含めた領域に赤背景
.padding() // 背景の外側にさらに余白
Text(
"Hello",
modifier = Modifier
.padding(8.dp) // 背景の外側にさらに余白
.background(Color.Red) // テキストの周りの余白も含めた領域に赤背景
.padding(4.dp) // テキストの周りに余白
)
実際にプレビューで見てみるとUIも以下のようになります。
@Preview(showBackground = true)
@Composable
fun ModifierOrderPreview() {
Column(
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.padding(16.dp)
) {
// Case 1: size → background → padding
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Red)
.padding(16.dp),
contentAlignment = Alignment.Center
) {
Text("Case 1", color = Color.White)
}
// Case 2: padding → size → background
Box(
modifier = Modifier
.padding(16.dp)
.size(100.dp)
.background(Color.Red),
contentAlignment = Alignment.Center
) {
Text("Case 2", color = Color.White)
}
// Case 3: background → padding → size
Box(
modifier = Modifier
.background(Color.Red)
.padding(16.dp)
.size(100.dp),
contentAlignment = Alignment.Center
) {
Text("Case 3", color = Color.White)
}
}
}
サイズ調整
Viewのサイズを調整するためのモディファイアは複数用意されています。sizeなら横幅と高さを一括に、widthやheightなら横幅と高さをそれぞれ指定することができます。
Modifier.size(100.dp) // 幅と高さを100dpに設定
Modifier.width(200.dp) // 横幅を200dpに設定
Modifier.height(50.dp) // 高さを50dpに設定
Modifier.fillMaxSize() // 親要素のサイズまで広がる
Modifier.wrapContentSize() // 要素の内容に応じたサイズに調整
fillMaxSizeはViewを親要素のサイズに合わせて最大まで広がります。wrapContentSizeではView内にあるコンテンツを表示するのに必要なサイズ分だけ広がります。
位置や余白を調整
Viewに余白を設けたい場合はpaddingを使用します。指定したViewの内部に指定分の余白を付与するものですが、メソッドチェーンで呼び出す順番などでマージン的な使い方も可能です。
Modifier.padding(16.dp) // 内側の余白を設定
Modifier.offset(x = 10.dp, y = 20.dp) // 任意の位置にオフセット
Modifier.align(Alignment.Center) // 親の中央に配置(Box内など)
alignはBoxなどで囲われている場合に自身が親要素内のどこに配置されるかを指定するモディファイアです。
背景色変更
Viewの背景色を変更するにはbackgroundを指定します。
Modifier.background(Color.Blue) // 背景色を設定
透明度を変更
Viewの透明度を変更するにはgraphicsLayerを指定します。
Modifier. graphicsLayer(alpha = 0.5f) // 透明度を設定
枠線を追加
Viewに枠線を追加するにはborderを指定します。引数には枠線の太さとカラーを指定します。
Modifier.border(2.dp, Color.Red) // 赤い枠線を追加
角丸の枠線にするにはさらに形を渡せばOKです。
Modifier.border(2.dp, Color.Red, shape = RoundedCornerShape(16.dp))
形状を変更
Viewの形状を変更するにはclipを指定します。引数には変更したい形を指定します。
Modifier.clip(CircleShape) // 円形に切り抜き
Modifier.clip(RoundedCornerShape(8.dp)) // 角丸四角形に切り抜き
影をつける
Viewにドロップシャドウ(影)を付与するにはshadowを指定します。
Modifier.shadow(8.dp) // ドロップシャドウを追加
ジェスチャーを追加
Viewにタップジェスチャーを付与するにはclickableを使用します。クロージャーには実行したい処理を渡します。
// クリックイベントを追加
Modifier.clickable {
println("Clicked!")
}
他にもドラッグ操作を追加するdraggableやスクロール操作を追加するscrollableなどがあります。
@Preview(showBackground = true)
@Composable
fun DraggableExample() {
var offsetX = remember { mutableStateOf(0f) } // X座標だけを管理
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Red)
.offset { IntOffset(offsetX.value.toInt(), 0) } // ドラッグした位置にビューを移動
.draggable(
state = rememberDraggableState { delta ->
// deltaはドラッグの移動量
offsetX.value += delta // 水平方向のみ更新
},
orientation = Orientation.Horizontal // 水平方向にのみドラッグ
)
) {
Text(text = "HELLO", color = Color.White, modifier = Modifier.align(Alignment.Center))
}
}
カスタムモディファイアを実装する
既存のモディファイアではなく、独自のモディファイアを作成することも可能です。その場合はthenを使用して以下のように実装すればOKです。
fun Modifier.customPadding(value: Dp): Modifier = this.then(
Modifier.padding(value * 2)
)
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。






