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.

- 320,139
- 94
- 887
- 841

- 191
- 2
- 13
-
https://stackoverflow.com/questions/65305734/how-to-set-the-scaffold-drawer-width-in-jetpackcompose solution with Outline – vitidev Jul 07 '22 at 08:21
5 Answers
Use a ModalDrawerSheet
in the drawerContent
and then set its modifier to the desired width:
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet(
modifier = Modifier
.width(300.dp) // or your desired width
.fillMaxHeight()
) {
...Your Drawer Content...
}
}
)
Code sample on the Material3 developer's page and the ModalDrawerSheet docs

- 586
- 4
- 10
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
}

- 727
- 1
- 10
- 15
-
It works well and thanks very much. Although this work-around is already brilliant, since the transparent part actually still belongs to drawerContent, you can't close the drawer by clicking "outside of the drawer" as before, which may makes users feel weird. Could you provide some extra advice? Or it's just unachievable for the current version of ModalNavigationDrawer? – Eynnzerr Jul 06 '22 at 08:19
-
@Eynnzerr I have updated the answer with a tap to close on the background. – Priyank Jain Jul 06 '22 at 14:01
I have tweaked @Priyank-Jain's answer a little bit to clean up the elevation left behind by the original drawer. Remove the elevation from the original draw and add it to the newly created one
val scope = rememberCoroutineScope()
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
Row(modifier = Modifier.fillMaxWidth()) {
Surface(
modifier = Modifier
.requiredWidth(320.dp)
.fillMaxHeight(),
color = Color.White,
shape = RoundedCornerShape(topEnd = 16.dp, bottomEnd = 16.dp),
elevation = 16.dp
) {
//Drawer Content
}
Spacer(
modifier = Modifier
.fillMaxSize()
.clickable(
interactionSource = MutableInteractionSource(),
indication = null
) {
scope.launch {
if (drawerState.isOpen) {
drawerState.close()
}
}
},
)
}
},
drawerContainerColor = Color.Transparent,
drawerElevation = 0.dp,
) {
//Main Content
}

- 118
- 4
- 11
You can add padding to the end of the modalDrawersheet.
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet(
modifier = Modifier
.padding (0.dp, 0.dp, 50.dp, 0.dp)
.fillMaxHeight()
) {
// drawer content
}
}
)

- 812
- 1
- 4
- 18
ModalNavigationDrawer
hardcodes the width of the content to be 360dp (as seen in the source). In order to override this, we can use requiredWidth()
as follows:
ModalNavigationDrawer(
drawerState = drawerState,
content = underlyingContent,
drawerContent = {
ModalDrawerSheet(modifier = Modifier.requiredWidth(320.dp)) {
// content
}
}
)

- 66
- 1
- 6