👍

Jetpack compose で constraint layout

2024/05/28に公開

前回の記事はこちら
https://zenn.dev/heartrails/articles/6d2dae5157436c

前回はレイアウト組むところでカードの高さを固定にしてちょっとズルをしてたので、色々な端末フォントサイズなどに対応できるようにもう少し工夫しました。

前回のレイアウトからの改善したいところ

  • フォントサイズや表示サイズを大きくした場合に、途中でレイアウトが見切れないようにしたい
  • カードの高さをフォントサイズに合わせて可変にするので、上に被さってくる AnimatedVisibility 部分をカード高さピッタリに合わせたい

Constraintlayout

compose multiplatform では ConstraintLayout はまだ使えないので(有志のライブラリはあるが、公式対応はまだ)泣く泣く Android の方に layout を移し、普通の Jetpack Compose で組むことに。

実際のカードレイアウト部分

OutlinedCard(
    modifier = Modifier.heightIn(minCardHeight.dp),
)

height -> heightIn に変更。min高さ希望を伝えている

ConstraintLayout(
    modifier = Modifier
        .fillMaxWidth()
        .background(MaterialTheme.colorScheme.surface),
) {
    val (box, button) = createRefs()
    val dividerGuideline = createGuidelineFromEnd(minCardHeight.dp)

    val boxModifier = Modifier.constrainAs(box) {
        top.linkTo(parent.top)
        start.linkTo(parent.start)
        end.linkTo(dividerGuideline)
        bottom.linkTo(parent.bottom)
        width = Dimension.fillToConstraints
    }
...

Constraint の指定部分。
参考 : https://developer.android.com/develop/ui/compose/layouts/constraintlayout?hl=ja

ここでのポイントは width = Dimension.fillToConstraints を入れとくこと。
これがないと、制約効いてない!なんでなんで・・になる。。

参考 : https://zenn.dev/sobya/articles/600436577121d6

AnimatedVisibility 部分をカード高さピッタリに合わせたい のところ

Box (
    modifier = boxModifier
        .clickable { onClick() }
        .height(IntrinsicSize.Min)
) {
    // 左側のメインコンテンツに入れたいlayoutをこの辺に
    // 重なる AnimatedView もこの辺に入れる
}

ここでの重要ポイントは height(IntrinsicSize.Min)
これがないと被さってくるアニメーションの描画の大きさが良い感じにフィットしてくれない。

参考 : https://developer.android.com/develop/ui/compose/layouts/intrinsic-measurements?hl=ja

ポイントのとこだけ抜粋したらだいぶわかりずらい・・・

コード全体はこちら

https://github.com/maripiyoko/kmp-sample/pull/2/files#diff-8a47f1a850d76f409ae2aaaa946db27e99e435eeaaa14a4956721ea3981bb20f

出来上がりのアニメーション

余談(@Previewについて)

compose multiplatform でレイアウトを組んでた時は Fleet でプレビューできるが、
Android jetpack compose で @Preview したい時は Android Studio を使わないとダメのようです。

ちなみにどちらも @Preview したい時は
androidx.compose.ui:ui-tooling-preview を入れないといけない。
Android と Common で dependency の記載場所が違うのでちょっとだけハマる。
参考 : https://developer.android.com/develop/ui/compose/tooling?hl=ja

ハートレイルズ

Discussion