Bottom Sheet with React Native
Let’s build ourselves a basic bottom sheet in react native.
Github: https://github.com/arbaz52/react-native-bottom-sheet
We’ll start with a bare react-native project. Start with following react native’s documentation on how to setup a project. Once you have the project all set. Open it in your editor of choice. I go with VSCode.
Imports
Constants
The reason we’re using Dimension of window
instead of screen
is because we’ll be displaying an overlay behind the bottom sheet and over the actual content, and we want it to draw over the status bar as well, otherwise status bar will look odd.
Styles
Bottom Sheet Component
The reason we’re using forwardRef is we want our bottom sheet to be opened/closed by outside as well so we’ll be exposing functions that will let us do that.
We’ll use the state expanded
to render/not-render our overlay so it does not render over the content if the bottom sheet is closed.
We’re starting with bottom sheet closed that is why the opacity
that we will use for our overlay is set to 0
The reason we’re doing WINDOW_HEIGHT — BOTTOM_SHEET_HEIGHT.min
is because we’re starting from the top, we move to the window’s bottom and then moving up the same amount as the minimum height for the bottom sheet. Notice that we’re not chaging our bottom sheet’s height, that would always be the max height we’ve set it, we’re just moving it so the rest goes out of screen.
I’ll explain why we’re using translateY.flattenOffset
once I show you the implementation of PanResponder
but other than that, we’re just writing two animations, one for overlay and the other for our bottom sheet and then playing them in parallel.
Also, we’re now exposing these functions that will be used externally (outside the component) to open/close the bottom sheet.
Butter (Using PanResponder)
onMoveShouldSetPanResponder
: We’re returning true so we get access to events when a gesture is performed.
onPanResponderGrant
: When the gesture begins, we extract the current value of our translateY
, use it as its offset and set its value to 0
. Otherwise, when the user will perform the gesture, the bottom sheet will stutter.
onPanResponderMove
: During the time when the gesture is being performed, we’re getting its change in y/vertical axis and using it as value for our translateY
onPanResponderRelease
: When the gesture ends, we extract the value of how much was dragged in y/vertical axis and if it’s less than our threshold value, we ignore the drag and animate our translateY
value to 0
. If it’s greater, we’re checking the gesture direction, if it’s upwards or -ive, we open the sheet, otherwise we close it using functions we’ve defined earlier.
Final piece in the puzzle is the rendering:
- Status bar is translucent because we want to draw our overlay on top of it.
- We do not render the overlay if the bottom sheet is closed.
- We’re using
Animted.View
instead of simpleView
because we want to animate itstransform
property. - We’re attaching
panResponder.panHandlers
responsible for accessing/handling gesture events to allow user to drag the bottom sheet vertically. - We’re rendering the content of the bottom sheet passed by the parent after the drag handle.