Recently I’ve tried to get an inspiration for a next animation challenge. And here we go — created by Ivan Parfenov. I was curious if I am able to do this transition effect with React Native. You can check out a result on my expo account! Why we even need the animations like these? Read Good to great UI animation tips by Pablo Stanley.
We can see there is a couple of animations. Toolbar tile (show/hide), bottom bar (show/hide), move a selected item, hide all others, show detail items and maybe even more.
The hard thing about the transition is to synchronize all of those animations. We can’t really unmount the List Page and show the Detail Page because we need to wait till all animations are done. Also, I am a fan of having a clean code. Easy to maintenance. If you have ever tried to implement an animation to your project, the code usually gets messy. Full of helper variables, crazy calculations, etc. That’s why I would like to introduce react-native-motion.
An idea of react-native-motion
Can you see the animation of toolbar’s title? You just need to move the title a bit and animate an opacity to zero/one. No big deal! But because of that, you need to write a code like this. Even before you actually start to write UI for that component.
Now let’s take a look how we can use react-native-motion for this. I know the animations are quite often very specific. And I know React Native provides very powerful Animated API. Anyway, it would be great to have a library with basic animations.
The biggest problem of this challenge was moving of selected list item. The item that is shared between List Page and Detail Page. How to move the item from FlatList to the top of Detail’s Page when the element is actually not absolutely positioned? It is quite easy with react-native-motion.
We specified source element of the SharedElement on List Page. Now we need to do almost the same for destination element on the Detail Page. To know the position where we want to move the shared element.
Where is the magic?
How can we move a relatively positioned element from one page to the another one? Actually, we can’t. The SharedElement works like this:
- get a position of the source element
- get position of the destination element (obviously, without this step the animation can’t be initiated)
- create a clone of the shared element (The magic!)
- render a new layer above the screen
- render the cloned element that will cover the source element (in his position)
- initiate move to the destination position
- once the destination position was reached, remove the cloned element
You can probably imagine there are 3 elements of the same React Node at the same moment. That’s because List Page is covered up by Detail Page during that moving animation. That’s why we can see all 3 elements. But we want to create an illusion that we actually moving the original source item.
You can see point A and point B. That’s a time period when the moving is performing. You can also see the SharedElement fires some useful events. In this case, we use WillStart and DidFinish events. It is up to you to set an opacity for source and destination element to 0 when a moving to destination was initiated, and back to 1 for destination element once the animation was finished.
What do you think?
There is still work on react-native-motion. It is definitely not a final and stable version of this library. But it is a good start I hope :) I would love to hear what do you think about that!
I am constantly looking for new challenges and opportunities. If you need a help with something, let me know, please ;) I will be happy to discuss it.