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!
1 Answer 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)
}
}
}
}
}
}
Comments
Explore related questions
See similar questions with these tags.