LoginSignup
0
0

More than 1 year has passed since last update.

JetpackComposeで、Drawerを右から出す

Posted at

JetpackComposeでは、NavigationDrawerのようなものが提供されている。
Scaffoldでも引数で指定可能だが、もう少し奥まで読むとModalDrawerというもので提供されている。
これは標準では(一般的なLocaleでは)左から出る。これを右から出したい。

本記事ではDrawerの開閉方法については触れず、右から出す方法にだけ注目して記述します。

やることは3つ。

  1. CompositionLocalProvider を使って、LayoutDirectionを右からに変更する
  2. 表示するコンテンツも右寄せになってしまうので、CompositionLocalProviderで左からに上書きする
  3. Shapeを指定して、中のコンテンツの横幅だけを表示するようにする

1. CompositionLocalProvider を使って、LayoutDirectionを右からに変更する

Scaffoldを例に記述する

    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        Scaffold(
            ...
        ) {
            ...
        }
    }

2. 表示するコンテンツも右寄せになってしまうので、CompositionLocalProviderで左からに上書きする

    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        Scaffold(
            ...
            drawerContent = {
                CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                    // Drawerの中身
                }
            },
        ) {
            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                // 本体
            }
        }
    }

3. Shapeを指定して、中のコンテンツの横幅だけを表示するようにする

        val EndDrawerPadding = 56 // ModalDrawerの中で指定されている、Drawer余白の固定値(dp)
        val DrawerWidth = 100 // dp
    val configuration = LocalConfiguration.current

    fun customShape() = object : Shape {
        override fun createOutline(
            size: Size,
            layoutDirection: LayoutDirection,
            density: Density
        ): Outline {
            val screenWidth = with(density) { configuration.screenWidthDp.dp.toPx() }
            val drawerContentWidth = with(density) { screenWidth - EndDrawerPadding.dp.toPx() }
            return Outline.Rectangle(
                Rect(
                    drawerContentWidth - with(density) { DrawerWidth.dp.toPx() },
                    0f,
                    screenWidth, // drawerContentWidthを指定すると少し余白ができちゃうので、多めに指定している
                    with(density) { configuration.screenHeightDp.dp.toPx() }
                )
            )
        }
    }
    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
        Scaffold(
            ...
            drawerShape = customShape(),
            drawerContent = {
                CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                    // Drawerの中身 (例)
                    Column(modifier = Modifier.size(DrawerWidth.dp)) {
                        // ...
                    }
                }
            },
        ) {
            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
                // 本体
            }
        }
    }

懸念

EndDrawerPadding はModalDrawer内で定義されているPrivateスコープの値だけど、これがアップデート変わったら死ぬ^^

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