添加手势
在本教程中,了解如何从 React Native Gesture Handler 和 Reanimated 库实现手势。
手势是在应用中提供直观用户体验的好方法。React Native 手势处理程序 库提供可以处理手势的内置原生组件。它使用平台的原生触摸处理系统识别平移、点击、旋转和其他手势。在本章中,我们将使用此库添加两个不同的手势:
¥Gestures are a great way to provide an intuitive user experience in an app. The React Native Gesture Handler library provides built-in native components that can handle gestures. It recognizes pan, tap, rotation, and other gestures using the platform's native touch handling system. In this chapter, we'll add two different gestures using this library:
-
双击可缩放表情符号贴纸的大小,再次双击可缩小比例。
¥Double tap to scale the size of the emoji sticker and reduce the scale when double tapped again.
-
平移以在屏幕上移动表情符号贴纸,以便用户可以将贴纸放置在图片上的任何位置。
¥Pan to move the emoji sticker around the screen so that the user can place the sticker anywhere on the image.
我们还将使用 复活 库在手势状态之间进行动画处理。
¥We'll also use the Reanimated library to animate between gesture states.

1
2
Use animated components
An Animated
component looks at the style
prop of the component and determines which values to animate and apply updates to create an animation. Reanimated exports animated components such as <Animated.View>
, <Animated.Text>
, or <Animated.ScrollView>
. We will apply animations to the <Animated.Image>
component to make a double tap gesture work.
- Open the EmojiSticker.tsx file in the components directory. Inside it, import
Animated
from thereact-native-reanimated
library to use animated components. - Replace the
Image
component with<Animated.Image>
.
!!!IG10!!!
!!!IG1!!!
For a complete reference of the animated component API, see React Native Reanimated documentation.
3
Add a tap gesture
React Native Gesture Handler allows us to add behavior when it detects touch input, like a double tap event.
In the EmojiSticker.tsx file:
- Import
Gesture
andGestureDetector
fromreact-native-gesture-handler
. - To recognize the tap on the sticker, import
useAnimatedStyle
,useSharedValue
, andwithSpring
fromreact-native-reanimated
to animate the style of the<Animated.Image>
. - Inside the
EmojiSticker
component, create a reference calledscaleImage
using theuseSharedValue()
hook. It will take the value ofimageSize
as its initial value.
!!!IG2!!!
Creating a shared value using the useSharedValue()
hook has many advantages. It helps to mutate data and runs animations based on the current value. We can access and modify the shared value using the .value
property. We'll create a doubleTap
object to scale the initial value and use Gesture.Tap()
to animate the transition while scaling the sticker image. To determine the number of taps required, we'll add numberOfTaps()
.
Create the following object in the EmojiSticker
component:
!!!IG3!!!
To animate the transition, let's use a spring-based animation. This will make it feel alive because it's based on the real-world physics of a spring. We will use the withSpring()
function provided by react-native-reanimated
.
On the sticker image, we'll use the useAnimatedStyle()
hook to create a style object. This will help us to update styles using shared values when the animation happens. We'll also scale the size of the image by manipulating the width
and height
properties. The initial values of these properties are set to imageSize
.
Create an imageStyle
variable and add it to the EmojiSticker
component:
!!!IG4!!!
Next, wrap the <Animated.Image>
component with the <GestureDetector>
and modify the style
prop on the <Animated.Image>
to pass the imageStyle
.
!!!IG11!!!
!!!IG5!!!
In the above snippet, the gesture
prop takes the value of the doubleTap
to trigger a gesture when a user double-taps the sticker image.
Let's take a look at our app on Android, iOS and the web:
For a complete reference of the tap gesture API, see the React Native Gesture Handler documentation.
4
Add a pan gesture
To recognize a dragging gesture on the sticker and to track its movement, we'll use a pan gesture. In the components/EmojiSticker.tsx:
- Create two new shared values:
translateX
andtranslateY
. - Replace the
<View>
with the<Animated.View>
component.
!!!IG12!!!
!!!IG6!!!
Let's learn what the above code does:
- The translation values defined will move the sticker around the screen. Since the sticker moves along both axes, we need to track the X and Y values.
- In the
useSharedValue()
hooks, we have set both translation variables to have an initial position of0
. This is the sticker's initial position and a starting point. This value sets the sticker's initial position when the gesture starts.
In the previous step, we triggered the onStart()
callback for the tap gesture chained to the Gesture.Tap()
method. For the pan gesture, specify an onChange()
callback, which runs when the gesture is active and moving.
- Create a
drag
object to handle the pan gesture. TheonChange()
callback acceptsevent
as a parameter.changeX
andchangeY
properties hold the change in position since the last event. and update the values stored intranslateX
andtranslateY
. - Define the
containerStyle
object using theuseAnimatedStyle()
hook. It will return an array of transforms. For the<Animated.View>
component, we need to set thetransform
property to thetranslateX
andtranslateY
values. This will change the sticker's position when the gesture is active.
!!!IG7!!!
Next, inside the JSX code:
- Update the
<EmojiSticker>
component so that the<GestureDetector>
component becomes the top-level component. - Add the
containerStyle
on the<Animated.View>
component to apply the transform styles.
!!!IG13!!!
!!!IG8!!!
`
Let's take a look at our app on Android, iOS and the web:
Summary
Chapter 6: Add gestures
We've successfully implemented pan and tap gestures.
In the next chapter, we'll learn how to take a screenshot of the image and the sticker, and save it on the device's library.