How to create animated swipe button from react native? Here we use react native reanimated v2 for creating this swipe button. React native animations are something that was complicated for me at the beginning. so I had to spend some time investigating gesture handlers and reanimated v2 trying to figure things out. So let’s start to create animated swipe button.
What we are going to build is a swipe button that looks like this:
Things We are goings to Cover in this section
- Create animations with reanimated when swiping with swipeable dimension(the circled area inside the button)
- adding animations for ‘Swipe Me’ text when swiping
- Adding a Linear Gradient effect for swipe range when swiping
- Execute a custom function(this can be an API call) after the swiping is over.
What We Need to Achieve this Component
Create animated swipe button
We will start with App.js. I have created a subfolder src and created a new file as SwipeButton.jsx. Let’s check the SwipeButton.jsx code step by step. For better understanding, I have created a diagram. So the idea here is after we swipe half of the width of the button if we end the swiping it should swipe to the end automatically.
So here I have declared some variables so that we can integrate the swipe button. These variables can be varied according to your needs. Here SWIPEABLE_DIMENSIONS means the rounded swipe area inside the button. So to identify gesture events we can use PanGestureHandler from react-native-gesture-handler and there we can capture the events from the onGestureEvent function.
As you can see we have used the useSharedValue hook from reanimated to set the initial value. Shared Values serve a similar purpose to React Native’s Animated.Values. They can drive animations, transport data, and offer a means of responding to changes. We can use this hook to read and write data from the UI thread.
Understanding ‘useAnimatedGestureHandler’
we are using the useAnimatedGestureHandler hook from reanimated to capture the onStart, onActive, onEnd events(These are worklets). The handler worklets will receive the event and context as parameters. From the event object, we can capture the translation of the swipeable dimensions. We use context as a plain JS object to store some data.
onStart
Create a context object to store in the UI thread so that when un-toggling the button it won’t come to the initial position and also to capture whether the swiping is completed or not.
onActive
Here we are covering a couple of scenarios. We have declared a newValue variable to get the translation from the x-axis. If we swipe from the initial position then the new value should be e.translateX. If the swiping is completed and we are going to swipe again to the initial position(un-toggling the button) then we should always add the SWIPE_AREA to the translation from the x-axis which is coming on the event object because when un-toggling the button e.transalateX is a minus value. So It will work smoothly in this case. And finally, the swiping should occur between 0 and H_SWIPE_RANGE if not we will not update the shared value.
onEnd
We need two things here;
- I want my button to revert to its original position if I didn’t swipe for a sufficient amount of time;
- I want to carry out my action if I swiped long enough.
We are checking if the swiping is completed to the minimum range to be finished. If the shared value is greater than the minimum range to be swiped we set the SWIPE_RANGE as the shared value and mark it as completed otherwise it’s brought back to the original position.
The minimum swipe range for the swipe to be completed is BUTTON_WIDTH / 2 – SWIPEABLE_DIMENSIONS / 2 – 2 * BUTTON_PADDING.
When you call a function on the UI thread you can’t be sure if you’re calling a worklet or a callback from the JS thread. So here onEnd function is working on the UI thread. We have to call runOnJS otherwise this will throw an exception.
How do we call the ‘runOnJs’ function?
just think about a simple javascript function
const multiply = (a, b) => a * b
we can write this as;
runOnJs(multiply)(a, b)
Animate Swipeable Dimensions
Let’s animate the Swipeable dimensions. Here we will use the useAnimatedStyle hook to write our animations.
transform: [{ translateX: sharedValue.value }]
This will transform the Swipeable area to the shared value location. We also change the background colour on the Swipeable dimension with the use of interPolateColor. Interpolation is a way of estimating a function at intermediate points, learning from the ranges you provide. With interpolate in React Native, you can interpolate animated values by taking an input range, interpolating it, and mapping the values to an outputRange.
interpolateColor and interpolate both accept a couple of arguments:
- The animated value that it needs to look at;
- The array of input values;
- The array of output values;
- Extrapolation type
So here the first parameter for that is the translation in the x-axis value and then the input range will be [0, H_SWIPE_RANGE]. H_SWIPE_RANGE refers to the maximum swipeable width at which the swipe can be done. As the third parameter, we have applied the output range as a colour variation as [‘#1b9aaa’, ‘#fff’]. In this case when we animate from left it right when the input changes the output colour change from ‘#1b9aaa‘ to ‘#fff’ smoothly.
Animate “Swipe Me” Text
As you can see above we have centred the ‘Swipe me’ text and we have reduced the opacity up to 0 when the swipe ends. And also we have translated the Swipe text to the right a little bit when swiping. For that, we have given the input range as [0, H_SWIPE_RANGE] and the output range to be [0, BUTTON_WIDTH / 2 – SWIPEABLE_DIMENSIONS]. This will move the text to the right when swiping. Then for extrapolation, we have added extrapolate as CLAMP so that we can stop the animation if the input range exceeds.
How to add Linear Gradient to the swipe wave
Then we are coming to the last part. We are going to animate the horizontal wave range. Here is the code for that. first, we have to create the Linear Gradient component as an Animatable component.
As you can see above we have increased the opacity from 0 to 1 when the swiping comes to end. We have increased the wavelength when swiping. The wavelength should be the translateX + H_WAVE_RANGE(this is the initial width of the Wave Range).
And that’s how to create animated swipe button, here is the whole code snippet. Also, I have attached the link for the full code in GitHub given below.
https://github.com/pasindu1/AnimateSwipeButton.git
If you have any questions, or comments or think that there is a better way to implement this — feel free to comment here or reach out at [email protected]
Leave A Comment