How to create bottom sheet dialog with Jetpack Compose?

In this Jetpack compose tutorial we will learn How to create bottom sheet dialog in Android application using Jetpack Compose. Bottom sheet is an area containing additional content that are anchored to the bottom of the screen. 

Scaffold basically provides API that will combine different material components to make our layout. In the same way BackdropScaffold uses a backdrop as the centerpiece of the screen.

To use bottom sheet we need BottomSheetScaffold which is annotated  as ExperimentalMaterialApi, BottomSheetState (State which persistent bottom sheet in BottomSheetScaffold), remember BottomSheetScaffoldState ( which create and remember BottomSheetScaffoldState)

Some parameters for BottomSheetScaffold were given below:

sheetContent - Which contains the content of the bottom sheet.

scaffoldState - state of the Scaffold.

topBar -  top bar bar which is optional field.

sheetPeekHeight - The height of the bottom sheet when it is collapsed.

sheetContentColor - To set the color for the bottomsheet childs items we will use this property. Defaults to the matching content color for sheetBackgroundColor, or if that is not a color from the theme, this will keep the same content color set above the bottom sheet.

content - This the content of the Scaffold.

Lets define bottomSheetScaffoldState which will hold the state of Scaffold

val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
    bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
)

..

Lets create list to show in bottom sheet

data class BottomSheetItem(val title: String, val icon: ImageVector)

val bottomSheetItems = listOf(
        BottomSheetItem(title = "Notification", icon = Icons.Default.Notifications),
        BottomSheetItem(title = "Mail", icon = Icons.Default.MailOutline),
        BottomSheetItem(title = "Scan", icon = Icons.Default.Search),
        BottomSheetItem(title = "Edit", icon = Icons.Default.Edit),
        BottomSheetItem(title = "Favorite", icon = Icons.Default.Favorite),
        BottomSheetItem(title = "Settings", icon = Icons.Default.Settings)
    )

..

Final code:

package compose.material.theme

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.BottomSheetState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import compose.material.theme.ui.theme.Material3ComposeTheme
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {

    @OptIn(ExperimentalFoundationApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Material3ComposeTheme() {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    BottomSheetDemo()
                }
            }
        }
    }
}


data class BottomSheetItem(val title: String, val icon: ImageVector)

@OptIn(ExperimentalMaterialApi::class)
@ExperimentalFoundationApi
@Composable
fun BottomSheetDemo() {
    //Lets create list to show in bottom sheet
    val bottomSheetItems = listOf(
        BottomSheetItem(title = "Notification", icon = Icons.Default.Notifications),
        BottomSheetItem(title = "Mail", icon = Icons.Default.MailOutline),
        BottomSheetItem(title = "Scan", icon = Icons.Default.Search),
        BottomSheetItem(title = "Edit", icon = Icons.Default.Edit),
        BottomSheetItem(title = "Favorite", icon = Icons.Default.Favorite),
        BottomSheetItem(title = "Settings", icon = Icons.Default.Settings)
    )
    
    //Lets define bottomSheetScaffoldState which will hold the state of Scaffold
    val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
    )
    val coroutineScope = rememberCoroutineScope()
    BottomSheetScaffold(
        scaffoldState = bottomSheetScaffoldState,
        sheetShape = RoundedCornerShape(topEnd = 30.dp),
        sheetContent = {
            //Ui for bottom sheet
            Column(
                content = {

                    Spacer(modifier = Modifier.padding(16.dp))
                    Text(
                        text = "Bottom Sheet",
                        modifier = Modifier
                            .fillMaxWidth(),
                        textAlign = TextAlign.Center,
                        fontWeight = FontWeight.Bold,
                        fontSize = 21.sp,
                        color = Color.White
                    )
                    LazyVerticalGrid(
                       //cells = GridCells.Fixed(3)
                                columns = GridCells.Fixed(3), //https://developer.android.com/jetpack/compose/lists
                    ) {
                        items(bottomSheetItems.size, itemContent = {
                            Column(
                                horizontalAlignment = Alignment.CenterHorizontally,
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(top = 24.dp)
                                    .clickable {


                                    },
                            ) {
                                Spacer(modifier = Modifier.padding(8.dp))
                                Icon(
                                    bottomSheetItems[it].icon,
                                    bottomSheetItems[it].title,
                                    tint = Color.White
                                )
                                Spacer(modifier = Modifier.padding(8.dp))
                                Text(text = bottomSheetItems[it].title, color = Color.White)
                            }

                        })
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .height(350.dp)

                    //.background(Color(0xFF6650a4))
                    .background(
                        brush = Brush.linearGradient(colors = listOf(Color(0xFF8E2DE2), Color(0xFF4A00E0))),
                        // shape = RoundedCornerShape(cornerRadius)
                    )
                    .padding(16.dp),

            )
        },
        sheetPeekHeight = 0.dp,
        topBar = {
            //top app bar ui
            TopAppBar(
                title = { Text("Bottom Sheet Demo") },
                backgroundColor = Color.White,
                contentColor = Color.Blue
            )
        }
    ) {


        //Add button to open bottom sheet
        Column(modifier = Modifier.fillMaxSize()) {
            Button(
                modifier = Modifier
                    .padding(20.dp),
                onClick = {
                    coroutineScope.launch {
                        if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {
                            bottomSheetScaffoldState.bottomSheetState.expand()
                        } else {
                            bottomSheetScaffoldState.bottomSheetState.collapse()
                        }
                    }
                }
            ) {
                Text(
                    text = "Click to show Bottom Sheet"
                )
            }
        }
    }
}

..

GET source code on Github:

Comments