sunny52525
sunny52525

Reputation: 323

Push content when drawer opens in Jetpack Compose

How to slide the contents of scaffold when drawers open. Similar to this question but in jetpack compose.

Upvotes: 2

Views: 1828

Answers (1)

nglauber
nglauber

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:

enter image description here

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

Related Questions