【Android】Jetpack Compose のBox Composable を使用し、要素を重ねて表示する方法

boxshadowというか要素の重なりというか、下の画像のような装飾を実現したくいろいろ試した。これがベストには思えないが、一応それっぽいものができたのでメモっておく。

コード

構造だけ抜き出すと下のようになる。

・Box(Parent)
 ・Box(Back)
 ・Box(Front / Main )

  ・Content

      Box(
                Modifier
                    .fillMaxWidth()
                    .height(IntrinsicSize.Max)
            ) {

//                このボックスが後ろ側
                Box(
                    Modifier
                        .fillMaxSize()
                        .padding(top = 4.dp, start = 4.dp)
                        .border(
                            width = Border,
                            color = Color.Black,
                        )
                        .background(Color.White)
                )

//でこっちが前側
                Box(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(bottom = 10.dp, end = 10.dp)
                        .border(
                            width = Border,
                            color = Color.Black,
                        )
                ){
                    Column(
                        Modifier
                            .background(Color.White)
                            .fillMaxSize()) {
                        Text(text = "Main Contents")
                        Text(text = "Main Contents")
                        Text(text = "Main Contents")
                    }
                }
            }

詰まった点

子の高さを親いっぱいにする(子要素の中で一番高さのある要素Aに他の子の高さも合わせる)ので詰まった。

親に .height(IntrinsicSize.Max)  を当てて子には.fillMaxHeight() (下のコードではfillMaxSizeを使っている)を指定することでうまくいった。

テンプレート化して再利用する

枠だけテンプレート化して使いまわし、内部は個々別々の内容にしたい。Slot機能があるのでそれを利用する。

テンプレート側のコード。

ほとんど同じだけど

@Composable
fun Template(
    content: @Composable () -> Unit = {}
) {
    Box(
        Modifier
            .fillMaxWidth()
            .height(IntrinsicSize.Max)
    ) {
//                このボックスが後ろ側のボーダーになる
        Box(
            Modifier
                .fillMaxSize()
                .padding(top = 10.dp, start = 6.dp)
                .border(
                    width = Border,
                    color = Color.Black,
                    //                  shape = RoundedCornerShape(Shape)
                )
                .background(Color.White)
        )
        Box(
            modifier = Modifier
//                        .align(Alignment.TopStart)
                .fillMaxSize()
                .padding(bottom = 10.dp, end = 10.dp)
                .border(
                    width = Border,
                    color = Color.Black,
                    //                  shape = RoundedCornerShape(Shape)
                )
        ) {
            Column(
                Modifier
                    .background(Color.White)
                    .fillMaxSize()
            ) {
//                ここに渡されたcontentが収まる
                content()
            }
        }
    }
}

呼び出す際はこんな感じ

            Template() {
                Column() {
                    Text(text = "this is slotted text")
                    Text(text = "this is slotted text")
                    Text(text = "this is slotted text")
                    Text(text = "this is slotted text")

                }
            }

結果はこう。

参考
https://developer.android.com/jetpack/compose/layout
https://stackoverflow.com/questions/70984692/set-height-of-child-elements-equal-to-highest-other-element-that-are-contained-b

コメント

タイトルとURLをコピーしました