Recently I've been trying Material3 combined with Jetpack Compose, and I need a drawer along with a scaffold in one of my screen. It's sad that Scaffold
in material3 hasn't support drawer yet, but luckily ModalNavigationDrawer
can be found as a substitute. However, using ModalNavigationDrawer, the drawer's content is always covering the whole screen when drawer is opened, and I can't find any parameter to set it's width to a proper value, e.g. half of the screen width. Is there any way I can solve this problem?
My compose version is 1.2.0-beta02 and my material3 version is 1.0.0-alpha12.
From the source code of ModalNavigationDrawer, the max-width is set in modifier and the drawer content's column is set to fill max size so by default it will take NavigationDrawerTokens.ContainerWidth's value as width.
But a work-around exists here, what you can do is you need to set drawerContainerColor
as Color.Transparent
and put another column or box inside the drawerContent
with your required size.
You can use requiredWidth
modifier to fix the required width or you can use sizeIn
modifier according to min and max-width.
ModalNavigationDrawer(
drawerContent = {
Column(
modifier = Modifier
.requiredWidth(250.dp)
.fillMaxHeight()
.background(Color.White, RoundedCornerShape(topEnd = 16.dp, bottomEnd = 16.dp))
) {
//Drawer Content
}
},
drawerContainerColor = Color.Transparent
) {
//Main Content
}
Update with click to close the drawer on tap of the background -
If you want to have the ripple effect on Spacer's clickable just remove the interactionSource and indication parameters.
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
Row(modifier = Modifier.fillMaxWidth()) {
Column(
modifier = Modifier
.requiredWidth(250.dp)
.fillMaxHeight()
.background(
Color.White,
RoundedCornerShape(topEnd = 16.dp, bottomEnd = 16.dp)
)
) {
//Drawer Content
}
Spacer(
modifier = Modifier
.fillMaxSize()
.clickable(
interactionSource = MutableInteractionSource(),
indication = null
) {
scope.launch {
if (drawerState.isOpen) {
drawerState.close()
}
}
},
)
}
},
drawerContainerColor = Color.Transparent
) {
//Main Content
}