« Bottom Sheet in Jetpack Compose.
Two types of Bottom Sheet
If you want to implement a standard bottom sheet, you can use the BottomSheetScaffold composable. It accepts similar parameters to Scaffold, such as topBar, floatingActionButton, and snackbarHost. It includes additional parameters that provide a means to display bottom sheets.
If you want to implement a modal bottom sheet, you can use the ModalBottomSheetLayout composable:
standard bottom sheet
1@OptIn(ExperimentalMaterialApi::class)2@Composable3fun HomeScreen() {4 val bottomSheetScaffoldState =5 rememberBottomSheetScaffoldState(bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed))6 val coroutineScope = rememberCoroutineScope()7 BottomSheetScaffold(scaffoldState = bottomSheetScaffoldState, sheetContent = {8 Box(9 Modifier10 .fillMaxWidth()11 .height(200.dp)12 ) {13 Text(text = "Hello from sheet")14 }15 }, sheetPeekHeight = 0.dp) {16 Button(onClick = {17 coroutineScope.launch {18 if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {19 bottomSheetScaffoldState.bottomSheetState.expand()20 } else {21 bottomSheetScaffoldState.bottomSheetState.collapse()22 }23 }24 }) {25 Text(text = "Expand/Collapse Bottom Sheet")26 }27 }28}
First, we define bottomSheetScaffoldState
which will hold the state of BottomSheetScaffold
. In turn it holds drawerState, bottomSheetState, snackbarHostState. In this tutorial, we focus only on bottomSheetState
sheetContent
— defines the content of our Bottom Sheet. You put any composable you want.
sheetPeekHeight
— sets the peek height of the Bottom Sheet. We will use 0.dp to hide the Bottom Sheet when the app starts.
So to interact with Bottom Sheet, we just must use these methods:
bottomSheetScaffoldState.bottomSheetState.expand()
— to expand
bottomSheetScaffoldState.bottomSheetState.collapse()
— to collapse
But these methods are suspend
functions and that’s why they must be used in CoroutineScope
.
For this purpose we can use rememberCoroutineScope
to create coroutineScope
modal bottom sheet
1@OptIn(ExperimentalMaterialApi::class)2@Composable3fun MainScreen() {4 val sheetState = rememberModalBottomSheetState(5 initialValue = ModalBottomSheetValue.Hidden,6 )7 val coroutineScope = rememberCoroutineScope()89 BackHandler(sheetState.isVisible) {10 coroutineScope.launch { sheetState.hide() }11 }1213 ModalBottomSheetLayout(14 sheetState = sheetState, sheetContent = {15 Column() {16 BottomSheet()17 BottomSheet()18 BottomSheet()19 BottomSheet()20 }21 }, modifier = Modifier.fillMaxSize()22 ) {23 Column(24 modifier = Modifier25 .fillMaxWidth()26 .padding(top = 24.dp)27 .padding(horizontal = 24.dp),28 horizontalAlignment = Alignment.CenterHorizontally29 ) {30 Text(31 text = "Welcome to bottom sheet playground!",32 modifier = Modifier.fillMaxWidth(),33 style = MaterialTheme.typography.h4,34 textAlign = TextAlign.Center35 )36 Spacer(modifier = Modifier.height(32.dp))37 Button(onClick = {38 coroutineScope.launch {39 if (sheetState.isVisible) sheetState.hide()40 else sheetState.show()41 }42 }) {43 Text(text = "Click to show bottom sheet")44 }45 }46 }47}4849@Composable50fun BottomSheet() {51 Column(52 modifier = Modifier.padding(32.dp)53 ) {54 Text(55 text = "Bottom sheet",56 style = MaterialTheme.typography.h657 )58 Spacer(modifier = Modifier.height(32.dp))59 Text(60 text = "Click outside the bottom sheet to hide it",61 style = MaterialTheme.typography.body162 )63 }64}
There are three ModalBottomSheetValues
:
Hidden
Expanded
HalfExpanded
The first two are describing enough. HalfExpanded
will only show half of the bottom sheet, and this state is enabled only if the height of the bottom sheet is more than 50% of the screen height
.
As we can see, we put our screen composables
inside the ModalBottomSheetLayout’s
content. Also, we pass sheetState
as an argument.
BackHandler is an effect for handling presses of the system back button. The first argument is when it is enabled, and the second is what it should do when the system back button is pressed.
Button inside the Column is showing and hiding the bottom sheet. sheetState.show()
will show the bottom sheet with animation and sheetState.hide()
will hide the bottom sheet with animation.
The logic for showing and hiding the bottom sheet is put in the UI, but it should be handled by the ViewModel.
For full class code to try out the code yourself: