JetpackComposeでは、NavigationDrawerのようなものが提供されている。
Scaffoldでも引数で指定可能だが、もう少し奥まで読むとModalDrawerというもので提供されている。
これは標準では(一般的なLocaleでは)左から出る。これを右から出したい。
本記事ではDrawerの開閉方法については触れず、右から出す方法にだけ注目して記述します。
やることは3つ。
- CompositionLocalProvider を使って、LayoutDirectionを右からに変更する
- 表示するコンテンツも右寄せになってしまうので、CompositionLocalProviderで左からに上書きする
- 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スコープの値だけど、これがアップデート変わったら死ぬ^^