27

We can have Navigation Drawer in JetpackCompose by using Scaffold as below

Scaffold(
    drawerContent = { Text(text ="Drawer") }
) {}

enter image description here

I want to make the width of the drawer smaller. How can I do so?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Elye
  • 53,639
  • 54
  • 212
  • 474

5 Answers5

12

You can modify the shape (including width and height) using drawerShape parameter in Scaffold method.

So for instance

 Scaffold(
    scaffoldState = scaffoldState,
    drawerContent = { Text("Drawer content") },
    drawerShape = customShape(),
    content = {inner padding -> /* Body*/}
)

Then your customShape function

fun customShape() =  object : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
        ): Outline {
            return Outline.Rectangle(Rect(0f,0f,100f /* width */, 131f /* height */))
     }
 }

You can also use Outline.Rounded to get rounded corners

Kofi
  • 525
  • 6
  • 15
  • 1
    May be the best solution at the moment until a property for modifying drawer width is hopefully added to Scaffold. My only worry is if creating a Shape inside Composable functions could lead to slowdowns. I've tested that the above code works, but haven't profiled it yet in a real app. – kabumere Oct 08 '21 at 08:02
  • 1
    @kabumere I don't think it would slow down the app since internally, various composable functions use Material shapes (including the default `drawerShape` here; I'll check my pc and get the actual shape) which are actually functions similar to what I provided. Nonetheless, you can always make `customShape` a `val` and not a `fun` so the `Shape` object would be created once – Kofi Oct 08 '21 at 09:08
  • Yeah, mine was a val inside of a Composable function. I just started using Compose, so I guess I'm still wrapping my head around what gets re-called during recomposition and what doesn't. – kabumere Oct 08 '21 at 19:54
  • 1
    This work if you want the drawer to be smaller. but if you want it to be larger (ex: full screen width). The drawer looks like it is larger but the content is still limited. All is truncaded. Any one have any idea on how to solves that ? – BigDan Dec 15 '21 at 16:50
  • @BigDan That depends on the layout you used as `drawerContent`. You should modify the properties of that composable to extend it – Kofi Feb 21 '22 at 12:45
  • How would you fill full screen height? – kc_dev Jul 29 '22 at 13:06
  • 1
    @kc_dev `return Outline.Rectangle(Rect(0f,0f,100f /* width */, size /* height */))` – mikeorr85 Jul 31 '22 at 16:11
  • How to use it if I need Rtl support? – Roman May 01 '23 at 13:36
  • @Roman I guess it already does since you're setting just the width and height – Kofi May 17 '23 at 09:01
  • Nice solution. Thanks. I have to point out that `Rect(0f,0f,100f,131f)` made the drawer too small. I would suggest to use `Rect(0f,0f,size.width * 0.8f, size.height * 0.6f)`. You can change the proportion parameters (0.8f & 0.6f) as you wish. You will have to set the same proportion for the lazyColumn inside drawerContent as well. Otherwise some content could be cropped off from the drawer. – Binu Jasim Jul 26 '23 at 12:09
1

Here is an example drawing a Scaffold custom shape.

1. Spec exact size.

Scaffold(
    drawerShape = NavShape(400.dp, 0f)
)

2. Spec size by percent (half screen).

Scaffold(
    drawerShape = NavShape(0.dp, 0.5f)
)

Custom shape class

class NavShape(
    private val widthOffset: Dp,
    private val scale: Float
) : Shape {

    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        return Outline.Rectangle(
            Rect(
                Offset.Zero,
                Offset(
                    size.width * scale + with(density) { widthOffset.toPx() },
                    size.height
                )
            )
        )
    }
}
Vahe Gharibyan
  • 5,277
  • 4
  • 36
  • 47
0

I accomplished that by:

#1 - Setting to the Drawer's content Modifier a max width:

@Composable
fun MyDrawerContent(){
     Column(Modifier.fillMaxHeight().width(300.dp)) {
          ...
        

#2 - Setting the Scafold's drawer colors to Transparent + no Elevation

Scaffold(
     drawerBackgroundColor = Color.Transparent,
     drawerContentColor = Color.Transparent,
     drawerElevation = 0.dp,
     drawerContent = {
          MyDrawerContent()
     },
     ...

Note: Only problem I faced is if you touch on the transparent area the drawer does not closes as it used to. Siding it to close works perfectly though. It's a workaround...

-2
Scaffold(
      topBar = {
          topBar()
      },
      scaffoldState = scaffoldState,
      drawerContent = {
          drawer()
      },
      drawerGesturesEnabled = true
  ) { innerPadding ->
      NavigationHost(navController = navController)
  }
}
-4

Have you tried adding a modifier inside your drawer composable ?

Something like this:

Scaffold(drawerContent = { 
        Box(modifier = Modifier.fillMaxWidth(0.9f){
            Text(text = "Drawer") 
        }
    }) {}
CyrilFind
  • 634
  • 1
  • 7
  • 16
  • 4
    It doesn't work :(. This just set the content width within the drawer. The drawer width is still the same. – Elye Dec 15 '20 at 21:55
  • @Elye ah right, maybe don't use `Scaffold` but `ModalDrawerLayout` directly, that way you can use its `modifier` – CyrilFind Dec 16 '20 at 10:35
  • 1
    @ CyrilFind, It won't work with Modal drawer. Modal drawer represents the entire screen along with nav menu, not just the nav menu. – Sparsh Dutta Aug 12 '21 at 13:03