Introducing Navigation-Material đ§đ¨ď¸
Navigation-Compose (well, kinda) has an exciting new feature: Support for bottom sheet destinations!
Over the past (almost) 6 months, I worked on a library in collaboration with the Navigation team that offers support for Modal Bottom Sheets in Navigation Compose. Navigation with Fragments has long supported DialogFragments
, and with todayâs release of the Navigation Material library, we are providing the same feature for composable bottom sheets with Navigation Compose. Since modal bottom sheets are still an experimental Compose-Material API, the library will be released as part of Accompanist, a collection of extension libraries for Jetpack Compose.
All AndroidX libraries, Navigation and Compose included, follow strict semantic versioning as explained on the AndroidX releases page. This means that any API that isnât experimental is set in stone once a library goes to its Release Candidate (RC) phase. It would take a major version bump (i.e., a â2.0â) to make breaking API changes to these stable APIs.
- Ian Lake about the versioning system of AndroidX libraries
Because of the versioning requirements for AndroidX libraries, Navigation Material will be offered as part of Accompanist, just like navigation-animation. Think of it as an incubator until the bottom sheet APIs are fully grown up! Enough of the talking â letâs look at how you can use it!
Getting started!
Navigation Material is fresh out of the oven, built off todayâs release of Navigation 2.4.0-alpha06! There are a few easy steps to get started:
- Create a
BottomSheetNavigator
using therememberBottomSheetNavigator()
function - Add the
BottomSheetNavigator
to yourNavController
- Wrap your existing
NavHost
in theModalBottomSheetLayout
composable provided by Navigation Material. If you donât have aNavHost
yet, weâll create one! - Now youâre ready to define bottom sheet destinations using the new
bottomSheet
function!
Letâs go through it! First, weâll add a dependency on the Navigation Material library:
This enables you to access APIs like BottomSheetNavigator
. BottomSheetNavigator
is a Navigator
handling composable bottom sheet destinations. To make the navigation library aware of it, we register it with the NavController
:
Now, we wrap our existing NavHost
composable in the ModalBottomSheetLayout
composable provided by the Navigation Material library. If you donât have a NavHost
yet, you can add it here.
The ModalBottomSheetLayout
composable is a helper to create a Material ModalBottomSheetLayout
from a BottomSheetNavigator
.
Note: We register the navigator with the NavController directly in the composition, not in an effect like SideEffect
. This is because the NavHost needs this information when trying to build the navigation graph which will include a bottom sheet destination in just a bit! We recently landed some changes in Navigation Compose that makes this safe.
Back to the role of our navigator: BottomSheetNavigator
exposes the current destinationâs sheet content, or nothing if there currently is no active bottom sheet destination. This composable is then set as the ModalBottomSheetLayout
âs sheetContent
.
Essentially, a BottomSheetNavigator
drives a ModalBottomSheetState
, showing and hiding the sheet appropriately and coordinating the sheetâs content.
Finally, we can define a bottom sheet destination using the new bottomSheet
extension function on NavGraphBuilder
provided by Navigation Material. The bottomSheet
function takes a composable lambda with a NavBackStackEntry
parameter. That means that you will have access to the bottom sheetâs back stack entry which you can use to look at arguments and more.
And thatâs it! Bottom sheet destinations are regular navigation destinations, with the difference that they are floating window destinations. This means that they overlay other destinations on the back stack, just like dialog destinations do.
Navigating
You can navigate to bottom sheets just like any other destination:
You can navigate away from bottom sheet destinations as usual, or the user can dismiss the sheet by tapping on the scrim or tapping the back button. In this case, the sheet back stack entry will be popped off the back stack.
Navigating with Arguments
Bottom sheet destinations support the features of other types of destinations (like the composable
destination type), like passing arguments:
Thatâs it! This library and its APIs are experimental and subject to change until the Material Bottom Sheet APIs are finalized. We would love to hear your feedback over in the Accompanist repository!
The Navigation team also released the new Navigation Animation library today, bringing support for animations with Navigation Compose. Check out their post!
Why do we need this library?
Bottom Sheets in Jetpack Compose
Coming from the world of Activities, Views and Fragments, getting used to how Bottom Sheets are handled in Compose can be a bit of a learning curve. In Compose, state is passed down and events are passed up. Implementing bottom sheets means that a layout has to host both the sheetâs content and the layoutâs body that the sheet is shown on top of:
In bigger apps, bottom sheet content needs to be able to change: Either because it needs to be composed based on arguments or there might be different sheets that should be shown depending on the applicationâs current screen. The body
of the Material ModalBottomSheetLayout
is responsible for hosting the different destinations. To combine a Material ModalBottomSheetLayout
with Jetpack Compose Navigation, the ModalBottomSheetLayout
needs to host a NavHost
:
A basic integration could look like this:
This integration will scale quite badly â all Composable destinations that need to show a bottom sheet need to be able to set the sheet content and maybe even access the ModalBottomSheetState
. Back click and back stack handling are other issues not even considered in this example.
The code isnât very straightforward to understand and can feel a bit counter-intuitive if you havenât worked with bottom sheets in Compose before, especially in combination with Navigation.
To make our lives easier, we need a bridge that helps the NavHost
and the NavController
talk to the ModalBottomSheetLayout
to coordinate the sheetâs sheetContent
and the sheetâs visibility. Luckily, thatâs what Navigation Material provides so that you donât need to write all of this boilerplate code!
Get started using it today by heading over to the Accompanist documentation or jumping back to the above âGetting Startedâ section!
Thank youâs
Getting this library ready was a huge effort I spent several months on and I could not have done it without the support from some awesome folks. Thank you to Ian Lake for lots of patience, reviews, accepting contributions that made this library possible, suggestions and sharing your knowledge. Thanks to Matvey Malkov for helping me figure out some tricky bottom sheet things :) Thanks to Jeremy Woods for the collaboration between Navigation Animation and Navigation Material. Thanks to Chris Banes for maintaining Accompanist, it is truly awesome! Thank you to Mark Dickson, Hugo Visser, Andrew Kelly and Ben Weiss for reviewing this post! And finally, thank you to Yasmine Evjen for helping to find the emoji combo for Navigation Animation and Navigation Material.
If you want to hear more about this libraryâs story and technical details, follow this blog to get notified about the next story!