Search code examples
androidandroid-jetpack-composeandroid-jetpack-compose-material3

Jetpack Compose: How to modify the width of Drawer in ModalNavigationDrawer?


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.


Solution

  • 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
        }