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 👇
🔁 In case you missed it
How to use SWR - Fetch and Cache dataLearn 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 SavinHelping you become a better developer together with the notJust.dev team |