Android Nomad #40 - Bottom sheets

Tips and tricks for implementing a Modal Bottom Sheet

Android Nomad #40 - Bottom sheets

Modal bottom sheets are versatile UI components that play a crucial role in modern app design. They're commonly used to display secondary actions, settings, or additional content without navigating away from the current screen.

Understanding Modal Bottom Sheets

Modal bottom sheets appear in response to user actions, such as tapping a button or an overflow icon. They can be dismissed through various means:

  • Selecting a menu item or action within the bottom sheet
  • Tapping the scrim (the semi-transparent overlay)
  • Swiping the sheet down
  • Using a close affordance (e.g., a close button) in the sheet's top app bar, if present

Key Considerations for Implementation

When implementing a modal bottom sheet, there are three primary aspects to consider:

  1. Design: Ensure your UI adheres to Material 3 guidelines, including the use of a drag handle or close button.
  2. State Management: Properly manage the bottom sheet's state for smooth interactions.
  3. Dismiss Handling: Carefully manage dismiss actions to avoid focus-related issues.

Let's dive deeper into each of these aspects.

Implementing Modal BottomSheet in Compose

1. BottomSheetState

val bottomSheetState = rememberModalBottomSheetState(
    skipPartiallyExpanded = false,
    confirmValueChange = { true }
) 
  • skipPartiallyExpanded: When true, the sheet will always fully expand or hide, skipping the partially expanded state. Set to false to allow partial expansion based on content height.
  • confirmValueChange: This optional parameter allows you to handle state changes. The default implementation always returns true, but you can customize it for more granular control.

2. ModalBottomSheet

ModalBottomSheet(
   onDismissRequest = { openBottomSheet = false },
   sheetState = bottomSheetState
) {
     // Your bottom sheet content goes here
}
  • onDismissRequest: This callback is triggered when the user attempts to dismiss the sheet (e.g., by tapping outside). It's crucial for managing the sheet's visibility.

3. Handling dismiss

Proper dismiss handling is essential to avoid UI glitches. Here's a recommended approach:

val scope = rememberCoroutineScope()

// When dismissing the bottom sheet

scope.launch {
    bottomSheetState.hide()
}.invokeOnCompletion {
   if (!bottomSheetState.isVisible) {
      openBottomSheet = false
   }
}

This pattern ensures that the openBottomSheet state is only updated after the bottom sheet has fully hidden, preventing potential race conditions.

Finally, I highly recommend reading the material guidelines, it is a well written document which covers almost everything you need to know for designing a comprehensive modal bottom sheet.

Subscribe to Sid Pillai

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe