profile

notJust.dev Newsletter

🚀 The power of Reanimated and Gesture Handler

Published about 1 month ago • 4 min read

notJust.dev Newsletter 🚀

Stay up-to-date with the latest technologies and become a better developer

Hey notJust Developers,

Last week, I rebuilt the nice Apple Wallet Card animation in React Native using React Native Reanimated and React Native Gesture Handler 🧑‍💻

In this issue, I want to break down the animation and show what’s possible. I hope this will give you some ideas of interesting animations you can build in your apps.

This issue is sponsored by App.js

Join us at the 4th edition of App.js Conf, 22-24 May, to have fun with fellow React Native developers, meet core contributors from companies like Meta, Microsoft, and Software Mansion, and learn straight from the creators of React Native and Expo!

We’ve prepared a line-up full of engaging talks by RN experts, and a set of practical workshops to make sure your mobile development skills are up-to-date.

Use the code notjustdevs10 to get 10% off the conference ticket!

Reanimated

React Native Reanimated is a powerful animation library that makes it easy to create smooth animations and interactions that run in the UI thread.

Gesture Handler

React Native Gesture Handler provides native-drive gesture management and helps you build touch-based interactions. The gestures it supports range from simple tap and long press gestures, to more complex drag, pinch, rotate, and fling.

Gesture Handler integrates easily with Reanimated and helps you build gesture-based animations. That’s what we will explore next.

Custom Scroll List

For the vertical list of Cards, I decided to build the scroll functionality from scratch. I could use a ScrollView or a FlatList, but that would make the next animations a bit harder. Having full control over the position of elements in a list will make it easier to move the cards and build more complex animations.

For that, I simply mapped through my cards and rendered them inside a normal View. No scrolling yet.

To power the scroll, I used a reanimated shared value scrollY and then applied it as translationY to every card element.

I then wrapped all the cards inside a GestureDetector and used a Pan Gesture to handle the dragging gesture. When the user drags the list up or down, I update the scrollY value.

Now, we have a primitive scrollable list.

The next step was to add some inertia to the scroll animation. What I mean by that, is when we scroll a list, and release the finger, we don’t want the scroll to stop. We want the list to continue the scroll momentum, and slow down over time.

This can be accomplished by animating the scrollY value when the pan gesture ends. For that, reanimated provides a nice animation function withDecay which lets you create animations that mimic objects in motion that move with a given deceleration rate.

Selected Card Animation

When we select a card from the list, we want to move it to the top of the screen, and the rest of the cards, should all be stacked together at the bottom of the screen.

First, we need to keep track of the active card. I used a shared value and updated it using the Tap gesture on every card component

The next step, is to animate the position of the cards, whenever the active card changes. We have to handle 3 cases:

  • No credit card is selected - move the card back to its original position in the list, based on the current scroll position
  • The card is selected - move it to the top of the screen
  • Another card is selected - move it to the bottom of the screen

I use the useAnimatedReaction hook to execute the code for the above cases when the activeCardIndex changes

Using the animated function withTiming we get the nice and smooth transitions from the current position to the desired one.

The position in which we are moving the cards can be a bit confusing. Let me explain.

The goal was to move the card to the top of the screen. The top of the screen is X pixels away from the initial position of every card.

The initial Y position of every card depends on their index in the list:

  • index 0 - Y 0px
  • index 1 - Y 200px
  • index 2 - Y 400px

That means that the “Top of the screen” position, is different for every card. The good thing is that it can be easily calculated, by multiplying the card height with its index. That’s where we got -index * cardHeight.

The same logic was applied to move the cards to the bottom of the screen.

So, in this expression: -index * cardHeight * 0.9 + screenHeight * 0.7

  • -index * cardHeight moves the card to the top of the screen, relative to its position in the list
  • -index * cardHeight * 0.9 the 0.9 coefficient, adds a bit of margin between the cards, and this way we get the effect of a stack, where 10% of the previous card is still visible on top.
  • + screenHeight * 0.7 This simply shifts from “top of the screen” to “bottom of the screen”

That’s it 🙌

That’s all it took to create this animation. 2 files and approximately 200 lines of code for rendering, styling, and animating.

If you want to follow this tutorial step by step, check it out on our YouTube channel.

Here you can check the source code.

🙏 A small favor

Before you go, can I ask you a small favor? 👉👈

If you have followed our tutorials and found them valuable, can you please share some nice words about our work?

If you want to help, write a short tweet about how notJustDev tutorials help you as a React Native Dev, and tag @VadimNotJustDev.

We will share them on the page of our upcoming React Native & Expo course 🎉✨

🔴 Join me live

This Friday we will build a Local First Trello Clone. It's going to be a tutorial packed with value, so set a reminder and don't miss it out 👇

video preview

Count down to 2024-04-05T14:00:00.000Z

🔁 In case you missed it

How to use SWR - Fetch and Cache data

Learn how to quickly fetch data in your React Native app with SWR, making your app faster and smoother.

Building an Apple Wallet Clone

We'll design the User Interface from scratch, implement swipe gestures, and add animations to our app using Reanimated

Did you learn something new today?

If you found this email valuable, forward it to one friend or coworker who can benefit from it as well. That would be much appreciated 🙏

Vadim Savin

Helping you become a better developer together with the notJust.dev team

113 Cherry St 98104-2205, Seattle, WA 98104-2205
Unsubscribe · Preferences

notJust.dev Newsletter

by Vadim Savin

Stay up-to-date with the latest technologies and become a better developer

Read more from notJust.dev Newsletter

notJust.dev Newsletter 🚀 Stay up-to-date with the latest technologies and become a better developer Hey notJust Developers, Exciting news in the world of React Native Animation: The Skia team recently published React Native Skia version 1.0, a significant milestone achieved just 3 weeks ago. In this first-ever stable release, they’ve unveiled 5 super exciting features and enhancements. Rich Text Layouts using the New Paragraph API New Animation Hooks The Atlas API for rendering multiple...

about 1 month ago • 9 min read

notJust.dev Newsletter 🚀 Stay up-to-date with the latest technologies and become a better developer Hey notJust Developers, A lot of exciting things are happing in the React Native world. But today, I want to focus on 3 things that caught my attention in the last weeks: How React Strict DOM is reinventing cross-platform development The retirement of App Center and CodePush, and what are the alternatives How does the new EU Digital Services Act affect mobile developers Sponsored by IBM StepZen...

about 2 months ago • 3 min read

notJust.dev Newsletter 🚀 Stay up-to-date with the latest technologies and become a better developer Hey notJust Developers, Monetizing your mobile app is a crucial step in making it sustainable. The best monetization strategy, especially for consumer apps is the subscription model. It offers a reliable and predictable income stream, month over month. Companies like Netflix, Spotify, Duolingo, and Tinder have built an empire using the subscription model. Compared to in-app ads, you don’t need...

2 months ago • 6 min read
Share this post