Photo by balazsketyi modified.

Flutter: How to Build Draggable Bottom Sheet like Google Maps

Tsung-Wei Hsu
4 min readSep 2, 2023

A draggable bottom sheet, that we see quite often especially in navigation apps, where a child view for details needs be placed alongside with the parent view. The widgets such as BottomSheet, ModalBottomSheet or Dialog will probably come to mind quickly, but also quickly do we realize, that their nature makes the parent view non-interactable and dimmed out, thus unusable.

For this specific view, what we want normally to achieve are:

  • The child gives additional info to the parent.
  • The child is sizable and dismissible.
  • Both the parent and the child are interactable.

Luckily, there IS an official widget that check all the boxes above called DraggableScrollableSheet, here are some tips and quirks of how to implement it smoothly into your apps:

Build the Draggable Sheet

The sheet is relatively flexible and can be placed in any container. Below, we create a sheet with all attributes it offers:

Firstly, we set the initialChildSize to 0.5 making it shown by default. Otherwise, setting it to 0 hides the sheet at the beginning.

All sizes are defined fractionally to the parent height, e.g. a max size of 0.5 means the sheet can be dragged up to the half of its parent height. Here, the sheet can be expanded to fully cover the parent.

snap enables the behavior that the sheet will move to the closest snap point instead of staying still at the dragging position. It is also worth noting that maxChildSize and minChildSize are automatically treated as a snap point, so no need to define them again in snapSizes.

It is crucial to assign the scrollController in the builder, if you have a scrollable widget (actually the most cases). It helps the sheet to enable scrolling for the scrollable widget, when the sheet reaches its maximal height. If not assigned, you could still scroll but the sheet cannot be dragged at all.

Tune the Sizes

It is often desirable that the sheet has a collapsed state before it is completely closed. In addition, the collapsed state usually has a specific height instead of a fractional. With LayoutBuilder below, we obtain the parent height and turn the exact height of 60px to the fractional:

Now, the standard states of a bottom sheet have been established, namely expanded, anchored, collapsed and lastly hidden states.

Handle the Positions

Since the minChildSize is 0, the sheet will snap and close itself, when users drag too deep to the bottom, which we in some cases want to avoid. That’s when the _controller defined above takes over by adding a listener at the initialization:

The listener fires every time when the sheet is being dragged, in which we can properly track the current size of the sheet and, with a simple condition, prevent it from snapping to 0 and stay above collapsed point.

Remember _sheet given to the sheet widget previously? It is now used as the reference to access snapSizes defined in the build tree as well as all the rest of its attributes like maxChildSize, etc. These values help creating further actions to position the sheet and make whole sheet control relatively dynamic.

Customize as Wished

Now, it’s time for you to customize what content should be presented inside the sheet by individual use cases. Below are key takeaways of building a well-functioning sheet with background interactable:

  • DraggableScrollableSheet is not callable such as showBottomSheet() but a widget placed directly into the widget tree.
  • All sizes refer to height and are defined fractionally depending on the parent widget.
  • Both GlobalKey and LayoutBuilder help obtaining useful attributes like the parent height, snap sizes, etc.
  • The Sheet should contain a scrollable view assigned with the ScrollController provided by the builder, so that the dragging of the sheet and the scrolling of content do not overlapped.
  • Consider adding a state management, which enables the control of sheet positions above or below the widget tree.

Eventually, you might get something like this resembling the mainstream navigation apps:

A mockup of mainstream navigation apps.

Happy Coding! 🙌🏼
Below are some useful insights in Flutter, which might also interest you:

--

--

Tsung-Wei Hsu

frontend | web and mobile | apps | programming and making coffee from Frankfurt, Germany ☕️