Reputation: 323
How to slide the contents of scaffold when drawers open. Similar to this question but in jetpack compose.
Upvotes: 2
Views: 1828
Reputation: 24044
I found a solution...
// This is optional if you need to open/close the drawer programmatically
val coroutineScope = rememberCoroutineScope()
// We need the drawer state to check:
// 1. if it is opened or closed
// 2. request to open/close it
// 3. get the drawer's offset (and do the slide of the content)
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
// Drawer's width. It will be updated later in LaunchedEffect
var drawerWidth by remember {
mutableStateOf(drawerState.offset.value)
}
// As soon the user move the drawer, the content must move in sync.
// So here we're creating a derived state of the drawer state
// to update the content position.
val contentOffset = remember {
derivedStateOf {
drawerState.offset.value
}
}
// The scaffold state contains the drawer state.
val scaffoldState = rememberScaffoldState(
drawerState = drawerState
)
Scaffold(
scaffoldState = scaffoldState,
drawerContent = {
Box {
// your drawer content here...
}
}
) {
Box(Modifier.fillMaxSize()) {
// Here's the content's offset calculation logic
val xPos = (abs(drawerWidth) - abs(contentOffset.value))
Column(
// Set the content's offset
Modifier.offset(
x = with(LocalDensity.current) {
max(0.dp, xPos.toDp() - 56.dp)
}
)
) {
// Optional: opening the drawer using a button
Button(onClick = {
coroutineScope.launch {
drawerState.open()
}
}) {
Text("Open Drawer")
}
}
}
}
// Important! Initializing the drawerWidth
SideEffect {
if (drawerWidth == 0f) {
drawerWidth = drawerState.offset.value
}
}
Here's the result:
Warning! This solution has a problem: as you can see, I'm using a hardcoded value 56.dp
. This is because the Material Design library uses this value as end padding of the drawer. You can see this constant in the Drawer.kt
file in Material Design library.
private val EndDrawerPadding = 56.dp
Upvotes: 7