When working with draggable elements in React Native mobile apps, I’ve learned that there are some simple ways to help gestures and animations feel better and more natural.
Let’s look at the Shop app’s Sheet component as an example:
This component can be dragged by the user. Once the drag completes, it either animates back to the open position or down to the bottom of the screen to close.
To implement this, we can start by using a gesture handler which sets
yPosition to move the sheet with the user’s finger:
When the drag ends and the user lifts their finger, we animate to either the closed or open position based on the finger's position, as implemented in
onEnd above. This works but there are some issues.
Problem 1: Speed of Drag
If we drag down quickly from the top, shouldn’t it close? We only take the position into account when determining whether it opens or closes. Shouldn’t we also take the speed of the drag when it ends as well?
In this example above, the user may feel frustrated that they are flicking the sheet down hard, yet it won’t close.
Problem 2: Position Animation
No matter what the distance is from the end position, the animation after the drag ends always takes 600 ms. If it’s closer, shouldn’t it take less time to get there? If you drag it with more force before letting go, shouldn’t that momentum make it go to the destination faster?
Springs and Velocity
To address problem number one, we use
onEnd, and add it to the position to determine whether to close or open. We have a multiplier as well to adjust how much we want velocity to count towards where the sheet ends up.
For problem number two, we use a spring animation rather than a fixed duration one! Spring animations don’t necessarily need to have an elastic bounce back.
withSpring takes into account distance and velocity to animate in a physically realistic way.
In the example above, it’s now easy to flick it quickly closed or open, and the animations to the open or closed position behave in a more realistic and natural way by taking distance and drag velocity into account.
Elasticity and Resistance
The next time you drag down a photo or story to minimize or close it, try doing it slowly and watch what’s happening. Is the element that’s being dragged matching your finger position exactly? Or is it moving slower than your finger?
When the dragged element moves slower than your finger, it can create a feeling of elasticity, as if you’re pulling against a rubber band that resists the drag.
In the Sheet example below, what if the user drags it up instead of down while the sheet is already open?
Notice that the Sheet matches the finger position perfectly as the finger moves up. As a result, it feels very easy to continue dragging it up. However, dragging it up further has no functionality since the Sheet is already open. To teach the user that it can’t be dragged up further, we can add a feeling of resistance to the drag. We can do so by dividing the distance dragged so the element only moves a fraction of the distance of the finger:
The user will now feel that the Sheet is resisting being dragged up further, intuitively teaching them more about how the UI works.
Make Gestures Better for Everyone
This is the final gesture handler with all the above techniques included:
As user interface developers, we have an amazing opportunity to delight people and make their experiences better.
If we care about and nail these details, they’ll combine together to form a holistic user experience that feels good to touch and interact with.
I hope that you have as much fun working on gestures like I do!
The above videos were taken with the simulator in order to show the simulated touches. For testing the gestures yourself however, I recommend trying the above examples by touching a real device.
Andrew Lo is a Staff Front End Developer on the Shop's Design Systems team. He works remotely from Toronto, Canada.
We all get shit done, ship fast, and learn. We operate on low process and high trust, and trade on impact. You have to care deeply about what you’re doing, and commit to continuously developing your craft, to keep pace here. If you’re seeking hypergrowth, can solve complex problems, and can thrive on change (and a bit of chaos), you’ve found the right place. Visit our Engineering career page to find your role.