Skip to main content

Implementing Bottom Sheet Dialog in Jetpack Compose

Bottom sheet dialogs are a popular UI component in modern Android apps, providing a flexible and intuitive way to present additional content without completely disrupting the user’s workflow. Jetpack Compose simplifies their implementation with its declarative UI approach, offering developers both simplicity and customization.

In this blog post, we will explore how to implement a bottom sheet dialog using Jetpack Compose. We'll cover both the basics and advanced customizations, ensuring you can create visually appealing and functional bottom sheets tailored to your app’s requirements.

Table of Contents

  1. Introduction to Bottom Sheet Dialogs

  2. Components of Bottom Sheet Dialog in Jetpack Compose

  3. Implementing a Simple Bottom Sheet

  4. Customizing the Bottom Sheet Dialog

  5. Handling State and Events

  6. Advanced Use Cases

  7. Best Practices and Performance Optimization

  8. Conclusion

1. Introduction to Bottom Sheet Dialogs

Bottom sheet dialogs can display additional content, actions, or menus that slide up from the bottom of the screen. There are two primary types:

  • Persistent Bottom Sheets: These remain visible and often contain core functionality (e.g., navigation).

  • Modal Bottom Sheets: These are temporary and used for user-specific actions or information.

Jetpack Compose provides tools to create both types with ease, leveraging ModalBottomSheetLayout and other composable functions.

2. Components of Bottom Sheet Dialog in Jetpack Compose

Before diving into code, let’s understand the core components:

  • ModalBottomSheetLayout: A composable that manages the modal bottom sheet’s state and layout.

  • SheetState: Used to control the visibility and behavior of the bottom sheet.

  • Coroutines: Often used to manage animations and sheet interactions asynchronously.

These elements combine to create a seamless bottom sheet dialog experience in Compose.

3. Implementing a Simple Bottom Sheet

Here’s how you can create a basic modal bottom sheet dialog:

Step 1: Add Dependencies

Ensure you have the latest Jetpack Compose library in your build.gradle:

implementation "androidx.compose.material3:material3:<version>"

Step 2: Create a Modal Bottom Sheet Layout

@Composable
fun SimpleBottomSheetDemo() {
    val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
    val scope = rememberCoroutineScope()

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            Column(
                modifier = Modifier.padding(16.dp).fillMaxWidth(),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text("Bottom Sheet Content", style = MaterialTheme.typography.body1)
                Spacer(modifier = Modifier.height(8.dp))
                Button(onClick = {
                    scope.launch { sheetState.hide() }
                }) {
                    Text("Close")
                }
            }
        }
    ) {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Button(onClick = {
                scope.launch { sheetState.show() }
            }) {
                Text("Show Bottom Sheet")
            }
        }
    }
}

Explanation

  1. ModalBottomSheetLayout: Wraps the content and manages the bottom sheet.

  2. rememberModalBottomSheetState: Controls the sheet’s visibility and state.

  3. CoroutineScope: Handles asynchronous animations (e.g., show() and hide()).

4. Customizing the Bottom Sheet Dialog

Jetpack Compose allows extensive customization:

Styling the Bottom Sheet

You can style the sheet content using modifiers and Material Design components:

sheetContent = {
    Column(
        modifier = Modifier
            .background(Color.White, RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp))
            .padding(16.dp)
            .fillMaxWidth(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("Custom Styled Bottom Sheet", style = MaterialTheme.typography.h6)
        Spacer(modifier = Modifier.height(16.dp))
        Button(onClick = { /* action */ }) {
            Text("Perform Action")
        }
    }
}

Controlling Sheet Behavior

Adjust the behavior with parameters like skipHalfExpanded:

val sheetState = rememberModalBottomSheetState(
    initialValue = ModalBottomSheetValue.Hidden,
    skipHalfExpanded = true
)

Adding Gestures

Enable gestures for a more interactive experience using the Modifier.draggable.

5. Handling State and Events

Managing State

Compose’s state handling is intuitive. Use remember and mutableStateOf to manage data flow:

val isSheetVisible = remember { mutableStateOf(false) }

Listening for State Changes

Monitor state changes with LaunchedEffect:

LaunchedEffect(sheetState.isVisible) {
    if (sheetState.isVisible) {
        // Perform an action when the sheet is shown
    }
}

6. Advanced Use Cases

Integrating with ViewModel

Combine the bottom sheet with a ViewModel to manage business logic:

@Composable
fun BottomSheetWithViewModel(viewModel: MyViewModel) {
    val uiState by viewModel.uiState.collectAsState()

    ModalBottomSheetLayout(
        sheetContent = {
            Text(text = uiState.bottomSheetContent)
        },
        content = { /* Main content */ }
    )
}

Dynamic Content

Populate the bottom sheet dynamically based on user interactions or API responses.

7. Best Practices and Performance Optimization

  1. Keep Content Minimal: Avoid overcrowding the bottom sheet.

  2. Use LazyColumn for Lists: For dynamic content, use LazyColumn to optimize rendering.

  3. Test Responsiveness: Ensure the bottom sheet adapts well to different screen sizes and orientations.

  4. Avoid Nested Scrolls: Use scrollable content cautiously to avoid conflicts.

8. Conclusion

Implementing bottom sheet dialogs in Jetpack Compose is both simple and highly customizable. By leveraging Compose’s declarative nature and state management capabilities, developers can create engaging and responsive bottom sheets that enhance the user experience.

Start experimenting with the examples provided and integrate bottom sheet dialogs into your apps to deliver modern and intuitive UI components!

Popular posts from this blog

Restricting Jetpack Compose TextField to Numeric Input Only

Jetpack Compose has revolutionized Android development with its declarative approach, enabling developers to build modern, responsive UIs more efficiently. Among the many components provided by Compose, TextField is a critical building block for user input. However, ensuring that a TextField accepts only numeric input can pose challenges, especially when considering edge cases like empty fields, invalid characters, or localization nuances. In this blog post, we'll explore how to restrict a Jetpack Compose TextField to numeric input only, discussing both basic and advanced implementations. Why Restricting Input Matters Restricting user input to numeric values is a common requirement in apps dealing with forms, payment entries, age verifications, or any data where only numbers are valid. Properly validating input at the UI level enhances user experience, reduces backend validation overhead, and minimizes errors during data processing. Compose provides the flexibility to implement ...

jetpack compose - TextField remove underline

Compose TextField Remove Underline The TextField is the text input widget of android jetpack compose library. TextField is an equivalent widget of the android view system’s EditText widget. TextField is used to enter and modify text. The following jetpack compose tutorial will demonstrate to us how we can remove (actually hide) the underline from a TextField widget in an android application. We have to apply a simple trick to remove (hide) the underline from the TextField. The TextField constructor’s ‘colors’ argument allows us to set or change colors for TextField’s various components such as text color, cursor color, label color, error color, background color, focused and unfocused indicator color, etc. Jetpack developers can pass a TextFieldDefaults.textFieldColors() function with arguments value for the TextField ‘colors’ argument. There are many arguments for this ‘TextFieldDefaults.textFieldColors()’function such as textColor, disabledTextColor, backgroundColor, cursorC...

jetpack compose - Image clickable

Compose Image Clickable The Image widget allows android developers to display an image object to the app user interface using the jetpack compose library. Android app developers can show image objects to the Image widget from various sources such as painter resources, vector resources, bitmap, etc. Image is a very essential component of the jetpack compose library. Android app developers can change many properties of an Image widget by its modifiers such as size, shape, etc. We also can specify the Image object scaling algorithm, content description, etc. But how can we set a click event to an Image widget in a jetpack compose application? There is no built-in property/parameter/argument to set up an onClick event directly to the Image widget. This android application development tutorial will demonstrate to us how we can add a click event to the Image widget and make it clickable. Click event of a widget allow app users to execute a task such as showing a toast message by cli...