0

enter image description here Hello!

I am working on an Android app in Android Studio using Jetpack Compose, and I want to implement two drawers:

A left drawer that can be opened and closed by swiping from the left edge of the screen. A right drawer that can be opened and closed by swiping from the right edge of the screen. I’m having trouble figuring out how to implement both drawers and how to manage the swipe gestures so they work independently of each other.

I know how to create a single drawer using Drawer in Jetpack Compose, but I’m not sure how to implement two drawers with swipe gestures for both edges of the screen.

Could anyone provide an example or guide me on how to implement this functionality in Jetpack Compose?

Maybe a Pager or slider could also work. But i cant get that to work either.

Thanks in advance!

asked Mar 15, 2025 at 20:13

1 Answer 1

1

Example of Two Navigation drawer left and right :

@Composable
fun NavigationDrawerExamples() {
 DetailedDrawerExample { innerPadding ->
 Box(modifier = Modifier.padding(innerPadding)) {
 Text(
 "Swipe from left edge or use menu icon to open the dismissible drawer",
 modifier = Modifier.padding(16.dp)
 )
 }
 }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DetailedDrawerExample(
 content: @Composable (PaddingValues) -> Unit
) {
 val drawerStateLeft = rememberDrawerState(initialValue = DrawerValue.Closed)
 val drawerStateRight = rememberDrawerState(initialValue = DrawerValue.Closed)
 val clickedDrawerLeftOrRight = remember { mutableStateOf(true) }.also {
 Log.e("bvc", "clickedDrawerLeftOrRight value = " + (it.value))
 }
 val clickedDrawerLeftOrRightUpdated = rememberUpdatedState(clickedDrawerLeftOrRight).also {
 Log.e("bvc", "clickedDrawerLeftOrRightUpdated value = " + (it.value.value))
 }
 var correctDrawerState = remember {
 derivedStateOf {
 if (clickedDrawerLeftOrRightUpdated.value.value) drawerStateLeft else drawerStateRight
 }
 }.also {
 Log.e("bvc", "correctDrawerState value = " + (it.value == drawerStateLeft))
 }
 val scope1 = rememberCoroutineScope()
 val scope2 = rememberCoroutineScope()
 val navigationIcon = @Composable {
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
 Row {
 Row(
 Modifier
 .wrapContentSize(Alignment.TopStart)
 .weight(0.5f),
 horizontalArrangement = Arrangement.Start
 ) {
 IconButton(onClick = {
 scope1.launch {
 clickedDrawerLeftOrRight.value = true
 if (drawerStateLeft.isClosed) {
 drawerStateLeft.open()
 } else {
 drawerStateLeft.close()
 }
 }
 }) {
 Icon(Icons.Default.Menu, contentDescription = "Menu")
 }
 }
 Row(
 Modifier
 .wrapContentSize(Alignment.TopEnd)
 .weight(0.5f),
 horizontalArrangement = Arrangement.End
 ) {
 IconButton(onClick = {
 scope2.launch {
 clickedDrawerLeftOrRight.value = false
 if (drawerStateRight.isClosed) {
 drawerStateRight.open()
 } else {
 drawerStateRight.close()
 }
 }
 }) {
 Icon(Icons.Default.Menu, contentDescription = "Menu")
 }
 }
 }
 }
 }
 if (correctDrawerState.value == drawerStateLeft) {
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
 ModalNavigationDrawer(
 drawerContent = {
 ModalDrawerSheet {
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
 Column(
 modifier = Modifier
 .padding(horizontal = 16.dp)
 .verticalScroll(rememberScrollState())
 ) {
 Spacer(Modifier.height(12.dp))
 Text(
 "Drawer Title Left",
 modifier = Modifier.padding(16.dp),
 style = MaterialTheme.typography.titleLarge
 )
 HorizontalDivider()
 Text(
 "Section 1 Left",
 modifier = Modifier.padding(16.dp),
 style = MaterialTheme.typography.titleMedium
 )
 NavigationDrawerItem(
 label = { Text("Item 1 Left") },
 selected = false,
 onClick = { /* Handle click */ }
 )
 NavigationDrawerItem(
 label = { Text("Item 2 Left") },
 selected = false,
 onClick = { /* Handle click */ }
 )
 HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
 Text(
 "Section 2",
 modifier = Modifier.padding(16.dp),
 style = MaterialTheme.typography.titleMedium
 )
 NavigationDrawerItem(
 label = { Text("Settings Left") },
 selected = false,
 icon = {
 Icon(
 Icons.Outlined.Settings,
 contentDescription = null
 )
 },
 badge = { Text("20 Left") }, // Placeholder
 onClick = { /* Handle click */ }
 )
 NavigationDrawerItem(
 label = { Text("Help and feedback Left") },
 selected = false,
 icon = {
 Icon(
 Icons.Default.Menu,
 contentDescription = null
 )
 },
 onClick = { /* Handle click */ },
 )
 Spacer(Modifier.height(12.dp))
 }
 }
 }
 },
 drawerState = correctDrawerState.value
 ) {
 Scaffold(
 topBar = {
 LargeTopAppBar(
 title = { Text("Navigation Drawer Example1") },
 navigationIcon = navigationIcon
 )
 }
 ) { innerPadding ->
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
 content(innerPadding)
 }
 }
 }
 }
 } else {
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
 ModalNavigationDrawer(
 drawerContent = {
 ModalDrawerSheet {
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
 Column(
 modifier = Modifier
 .padding(horizontal = 16.dp)
 .verticalScroll(rememberScrollState())
 ) {
 Spacer(Modifier.height(12.dp))
 Text(
 "Drawer Title Right",
 modifier = Modifier.padding(16.dp),
 style = MaterialTheme.typography.titleLarge
 )
 HorizontalDivider()
 Text(
 "Section 1 Right",
 modifier = Modifier.padding(16.dp),
 style = MaterialTheme.typography.titleMedium
 )
 NavigationDrawerItem(
 label = { Text("Item 1 Right") },
 selected = false,
 onClick = { /* Handle click */ }
 )
 NavigationDrawerItem(
 label = { Text("Item 2 Right") },
 selected = false,
 onClick = { /* Handle click */ }
 )
 HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
 Text(
 "Section 2 Right",
 modifier = Modifier.padding(16.dp),
 style = MaterialTheme.typography.titleMedium
 )
 NavigationDrawerItem(
 label = { Text("Settings Right") },
 selected = false,
 icon = {
 Icon(
 Icons.Outlined.Settings,
 contentDescription = null
 )
 },
 badge = { Text("20 Right") }, // Placeholder
 onClick = { /* Handle click */ }
 )
 NavigationDrawerItem(
 label = { Text("Help and feedback Right") },
 selected = false,
 icon = {
 Icon(
 Icons.Default.Menu,
 contentDescription = null
 )
 },
 onClick = { /* Handle click */ },
 )
 Spacer(Modifier.height(12.dp))
 }
 }
 }
 },
 drawerState = correctDrawerState.value
 ) {
 Scaffold(
 topBar = {
 LargeTopAppBar(
 title = { Text("Navigation Drawer Example 2") },
 navigationIcon = navigationIcon
 )
 }
 ) { innerPadding ->
 CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
 content(innerPadding)
 }
 }
 }
 }
 }
}
answered Mar 20, 2025 at 11:48
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.