After trying to refactor my project from the normal view system to Android Compose, I can really feel the difference between them.
I feel Android Compose will for sure become the default way to build UI in native android, but it still have a lot of cons that Google engineers are trying to solve but till then, I am gonna write on how to solve one of them in this post and it is how to have multiple bottom-sheets in the same app.
After reading this article you will easily build multiple bottom sheets as shown below.
First before reading please be careful that this post applies to compose version 1.0.0-beta05
.
and is definitely related to these issues:
If these two issues are not solved yet you can continue reading my post, if any of them are solved and it will change the way to support multiple bottom-sheets, I will write another post.
1- Now Let's start by defining the bottom sheets that we are gonna use in our application
sealed class BottomSheetScreen() {
object Screen1: BottomSheetScreen()
object Screen2: BottomSheetScreen()
class Screen3(val argument:String):BottomSheetScreen()
}
2- We will have a mutable state of our current sheet
@Composable
private fun MainLayout() {
var currentBottomSheet: BottomSheetScreen? by remember{
mutableStateOf(null)
}
}
3- We will use BottomSheetScaffold
to handle opening and closing the bottom sheet
val scaffoldState = rememberBottomSheetScaffoldState()
BottomSheetScaffold(sheetPeekHeight = 0.dp, scaffoldState = scaffoldState,
sheetShape = BottomSheetShape,
sheetContent = {
currentBottomSheet?.let { currentSheet ->
SheetLayout(currentSheet,closeSheet)
}
}) { paddingValues ->
Box(Modifier.padding(paddingValues)){
MainContent(openSheet)
}
}
4- Now, We will define two lambdas for opening and closing the bottom sheet
val closeSheet: () -> Unit = {
scope.launch {
scaffoldState.bottomSheetState.collapse()
}
}
val openSheet: (BottomSheetScreen) -> Unit = {
currentBottomSheet = it
scope.launch { scaffoldState.bottomSheetState.expand() }
}
// to set the current sheet to null when the bottom sheet closes
if(scaffoldState.bottomSheetState.isCollapsed)
currentBottomSheet = null
Summing it up, our code should be similar to that
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun MainLayout() {
val scope = rememberCoroutineScope()
val scaffoldState = rememberBottomSheetScaffoldState()
var currentBottomSheet: BottomSheetScreen? by remember{
mutableStateOf(null)
}
val closeSheet: () -> Unit = {
scope.launch {
scaffoldState.bottomSheetState.collapse()
}
}
val openSheet: (BottomSheetScreen) -> Unit = {
currentBottomSheet = it
scope.launch { scaffoldState.bottomSheetState.expand() }
}
if(scaffoldState.bottomSheetState.isCollapsed)
currentBottomSheet = null
BottomSheetScaffold(sheetPeekHeight = 0.dp, scaffoldState = scaffoldState,
sheetShape = BottomSheetShape,
sheetContent = {
currentBottomSheet?.let { currentSheet ->
SheetLayout(currentSheet,closeSheet)
}
}) { paddingValues ->
Box(Modifier.padding(paddingValues)){
MainContent(openSheet)
}
}
}
5- Now we will define our SheetLayout
, as we can see from the above code that it takes two parameters
- The current bottom sheet
- The
closeSheet
lambda, because if we want to have a button to close the sheet
It should be similar to that
@Composable
fun SheetLayout(currentScreen: BottomSheetScreen,onCloseBottomSheet :()->Unit) {
BottomSheetWithCloseDialog(onCloseBottomSheet){
when(currentScreen){
BottomSheetScreen.Screen1 -> Screen1()
BottomSheetScreen.Screen2 -> Screen2()
is BottomSheetScreen.Screen3 -> Screen3(argument = currentScreen.argument)
}
}
}
6- Finally last step we define MainContent
composable function that takes openSheet
as a parameter
@Composable
fun MainContent(openSheet: (BottomSheetScreen) -> Unit) {
Column(Modifier.fillMaxSize(),verticalArrangement = Arrangement.SpaceEvenly,horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "This is Main Content")
Button(onClick = { openSheet(BottomSheetScreen.Screen1) }) {
Text(text = "Open bottom sheet 1")
}
Button(onClick = { openSheet(BottomSheetScreen.Screen2) }) {
Text(text = "Open bottom sheet 2")
}
Button(onClick = { openSheet(BottomSheetScreen.Screen3("this is an argument")) }) {
Text(text = "Open bottom sheet 2")
}
}
}
NB: Here is the whole project used in the Demo on Github
Thanks for reading 🐱🏍
Top comments (2)
cool
Impressive 👌🏻