Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。
そのライブラリ中のSpacerについて、構成や使用方法などをまとめます。
※環境:Android Studio Hedgehog | 2023.1.1 Patch 2
Kotlin 1.9.0
Compose Compiler 1.5.1
androidx.compose.foundation 1.5.0
UIの概要
Spacerは空きスペースを確保するUI要素です。
@Preview_mdpi @Composable fun ColumnSpacerSample() { Column(modifier = Modifier.size(320.dp, 240.dp)) { Image( painter = painterResource(R.drawable.leaf1), contentDescription = null, modifier = Modifier.height(100.dp), contentScale = ContentScale.None ) Spacer(modifier = Modifier.height(30.dp)) Image( painter = painterResource(R.drawable.leaf2), contentDescription = null, modifier = Modifier.height(100.dp), contentScale = ContentScale.None ) } }
関数の引数
Spacerの状態(装飾、演出など)は、引数により指定できます。
表示するコンテンツ(図形や文字など)を持たないので、与えるべき状態はmodifierのみです。
@Composable @NonRestartableComposable fun Spacer(modifier: Modifier) { ... }
引数 | 概要 | |
---|---|---|
modifier | Modifier | UI全般のCompose修飾子 |
関数の構成
関数は内部にLayout関数(Composable関数)のみを持ちます。
Layoutは「自身のサイズを決定する機能」をシステムへ登録する関数です。この機能はSpacerMeasurePolicyで定義されており、描画処理のLayoutフェーズで実行されます。
※描画処理については「Jetpack Compose:Composeによるアプリ画面の描画」を参照
@Composable @NonRestartableComposable fun Spacer(modifier: Modifier) { Layout({}, measurePolicy = SpacerMeasurePolicy, modifier = modifier) } private object SpacerMeasurePolicy : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { return with(constraints) { val width = if (hasFixedWidth) maxWidth else 0 // widthの算出 val height = if (hasFixedHeight) maxHeight else 0 // heightの算出 layout(width, height) {} // サイズを通知 } } }
Spacerのサイズ(widthまたはheight)は、制約Constraints(許されるサイズの範囲)が固定化された時(hasFixedXXX==true)に決まります。
固定化されなければ、サイズは0になり、空きスペースは確保されません。
固定化する条件は次のCompose修飾子を実行したときになります。
- Modifier#size
- Modifier#width / #height
- Modifier#fillMaxWidth / #fillMaxHeight
応用例1:Divider
backgroundの配色されたSpacerを、Divider(仕切り)として用いた例です。
@Preview_mdpi @Composable fun ColumnSpacerSample() { Column(modifier = Modifier.size(320.dp, 240.dp)) { Image( painter = painterResource(R.drawable.leaf1), ... ) Spacer( modifier = Modifier .height(2.dp) .fillMaxWidth() .background(Color.LightGray) ) Image( painter = painterResource(R.drawable.leaf2), ... ) } }
@Preview_mdpi @Composable fun RowSpacerSample() { Row(modifier = Modifier.size(320.dp, 240.dp)) { Image( painter = painterResource(R.drawable.leaf1), ... ) Spacer( modifier = Modifier .fillMaxHeight() .width(2.dp) .background(Color.LightGray) ) Image( painter = painterResource(R.drawable.leaf2), ... ) } }
※既にマテリアルデザインの指標に準拠したDividerがライブラリで提供されています。詳細は「Compose UI:Divider」を参照。
応用例2:Canvas
Jetpack Composeのライブラリで提供されるCanvas(Composable関数)は、Spacerを応用したUI要素です。
CanvasはSpacerによって確保された空きスペースへ、Modifier#drawBehindを使って図形の描画を可能にしています。
@Composable fun Canvas(modifier: Modifier, onDraw: DrawScope.() -> Unit) = Spacer(modifier.drawBehind(onDraw))
CanvasはSpacerと同様に、制約Constraintsが固定化(例は120×120)されている必要があります。
@Preview_mdpi @Composable fun CanvasSample() { Box(modifier = Modifier.size(320.dp, 240.dp)) { Canvas( modifier = Modifier .size(120.dp) // 120x120へ固定化 .background(Color.LightGray) ) { drawRect( // 矩形:DrawScopeに定義された描画関数 Color.Blue, topLeft = Offset(10.dp.toPx(), 10.dp.toPx()), size = Size(100.dp.toPx(), 100.dp.toPx()) ) drawCircle( // 円:DrawScopeに定義された描画関数 Color.Red, radius = 50.dp.toPx() ) } } }
関連記事: