0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

端末の形状を頻繁に参照したくなったので、compositionLocalWithComputedDefaultOfを使って定義した

0
Posted at

はじめに

スマホは画面の四隅が丸くなっています。一方で、Composable はデフォルトでは四角いです。画面遷移アニメーションを作っている時にその形状の差を埋めたいと考えました。これを実現するには、各画面の Composable も端末に合わせて形状を変更する必要があります。

角丸を適用した時の画面遷移アニメーションの例

アプローチ

角丸の半径は WindowInsets.getRoundedCorner(position: Int)1 により取得できます。今回は、LayoutDirection を考慮した上で取得した半径を使って Shape を作成します。

この形状をさまざまな場所から参照するため、ここでは compositionLocalWithComputedDefaultOf を使って実装します。compositionLocalWithComputedDefaultOf を使うことで、デフォルト値に LocalView などを参照できます。

実装コード

Scaffold(
    modifier = Modifier
        .clip(shape = LocalWindowShape.current),
) {
    // ...
}
val LocalWindowShape = compositionLocalWithComputedDefaultOf<Shape> {
    val view = LocalView.currentValue
    val insets = view.rootWindowInsets
    val topLeftCorner = insets?.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT)
    val topRightCorner = insets?.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT)
    val bottomRightCorner = insets?.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT)
    val bottomLeftCorner = insets?.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT)
    AbsoluteRoundedCornerShape(
        topLeft = topLeftCorner?.radius?.toFloat() ?: 0f,
        topRight = topRightCorner?.radius?.toFloat() ?: 0f,
        bottomRight = bottomRightCorner?.radius?.toFloat() ?: 0f,
        bottomLeft = bottomLeftCorner?.radius?.toFloat() ?: 0f,
    )
}

参考文献

  1. WindowInsets.getRoundedCorner(position: Int) はAndroid 12(API 31)以降に利用可能です。 ↩

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?