React Native Gesture Handler

FreeGuideOnline 最新 2026-07-12

React Native Gesture Handler 完全入门指南

React Native Gesture Handler 是一个声明式的本地手势处理库,旨在替代 React Native 内置的 PanResponderTouchable 组件。它直接运行在原生线程上,解决了手势响应与 JavaScript 线程动画之间的竞争问题,提供丝滑的 60fps 交互体验。本教程将带你从安装到实战,系统掌握它的核心用法。


1. 为什么需要 Gesture Handler?

React Native 默认的手势系统运行在 JS 线程上,当 JS 线程繁忙(如加载数据、大量渲染)时,手势会出现延迟甚至丢失。Gesture Handler 将手势识别放在原生 UI 线程,并通过 Native Driver 驱动动画,即使 JS 线程阻塞也能保证手势流畅。它提供了更丰富的手势识别能力,如长按、捏合、旋转、轻扫以及复杂的手势组合。


2. 安装与基础配置

安装核心库

npm install react-native-gesture-handler
# 或
yarn add react-native-gesture-handler

iOS 额外配置

进入 ios/ 目录执行 pod install:

cd ios && pod install && cd ..

Android 额外配置

MainActivity.java 中添加必要的 import:

import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

然后将 createReactActivityDelegate 修改为:

@Override
protected ReactActivityDelegate createReactActivityDelegate() {
  return new ReactActivityDelegate(this, getMainComponentName()) {
    @Override
    protected ReactRootView createRootView() {
      return new RNGestureHandlerEnabledRootView(MainActivity.this);
    }
  };
}

根组件包裹

使用 GestureHandlerRootView 包裹应用的根组件(通常在 App.tsx 中):

import { GestureHandlerRootView } from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* 你应用的其余部分 */}
    </GestureHandlerRootView>
  );
}

3. 核心手势组件

Gesture Handler 提供了一系列独立的手势组件,每类手势都可以像普通 View 一样嵌套子元素。最常用的有:

组件 用途
TapGestureHandler 点击(可指定点击次数)
LongPressGestureHandler 长按
PanGestureHandler 拖拽/平移
PinchGestureHandler 双指缩放
RotationGestureHandler 双指旋转
FlingGestureHandler 快速滑动(轻扫)
ForceTouchGestureHandler 3D Touch(iOS)
NativeViewGestureHandler 包裹原生滚动组件

3.1 TapGestureHandler(点击)

监听单击或多次点击,通过 numberOfTaps 属性指定所需点击次数。

import { TapGestureHandler, State } from 'react-native-gesture-handler';

<TapGestureHandler
  numberOfTaps={2}
  onHandlerStateChange={({ nativeEvent }) => {
    if (nativeEvent.state === State.ACTIVE) {
      console.log('双击触发');
    }
  }}
>
  <View style={styles.box} />
</TapGestureHandler>

3.2 PanGestureHandler(拖拽)

跟踪手指的移动,提供 translationXtranslationY 和速度信息。通常结合 Animated 实现元素跟随。

import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

const PanExample = () => {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const gestureEvent = (event) => {
    translateX.value = event.translationX;
    translateY.value = event.translationY;
  };

  const onEnd = () => {
    translateX.value = withSpring(0);
    translateY.value = withSpring(0);
  };

  return (
    <PanGestureHandler onGestureEvent={gestureEvent} onEnded={onEnd}>
      <Animated.View style={[styles.ball, useAnimatedStyle(() => ({
        transform: [
          { translateX: translateX.value },
          { translateY: translateY.value },
        ],
      }))]} />
    </PanGestureHandler>
  );
};

3.3 PinchGestureHandler 和 RotationGestureHandler

缩放与旋转多用于图片查看器,可通过 scalerotation(弧度)获取手势数据。

<PinchGestureHandler
  onGestureEvent={(event) => {
    scale.value = event.nativeEvent.scale;
  }}
>
  <Animated.View style={[{ transform: [{ scale: scale.value }] }]} />
</PinchGestureHandler>

4. 手势状态管理

每个手势都有生命周期状态,通过 onHandlerStateChange 捕获,常用状态:

  • State.UNDETERMINED (0) – 初始状态
  • State.BEGAN (2) – 手势开始
  • State.ACTIVE (4) – 手势进行中
  • State.END (5) – 手势正常结束
  • State.CANCELLED (6) – 手势被取消
  • State.FAILED (1) – 识别失败

推荐按需使用 State.ACTIVEState.END 来控制业务逻辑。


5. 手势组合(Composing gestures)

当需要同时或序列化触发多个手势时,可以使用 Gesture.SimultaneousGesture.ExclusiveGesture.Race。组合手势通过 Gesture API 声明式配置。

5.1 同时手势(Simultaneous)

两个手势同时识别,互不干扰。例如:拖拽的同时可缩放。

const panGesture = Gesture.Pan();
const pinchGesture = Gesture.Pinch();

const combined = Gesture.Simultaneous(panGesture, pinchGesture);

// 使用时挂载到 GestureDetector
<GestureDetector gesture={combined}>
  <Animated.View style={...} />
</GestureDetector>

5.2 排他手势(Exclusive)

一次只有一个手势成功,常用于区分点击和长按。

const tap = Gesture.Tap();
const longPress = Gesture.LongPress();

const exclusive = Gesture.Exclusive(longPress, tap);

5.3 Race 手势

第一个激活的手势生效,后续手势失效。

5.4 序列手势(Sequence)

使用 Gesture.Sequence() 定义按顺序触发的手势链,如先长按再拖拽。


6. 与 Reanimated 集成动画

Gesture Handler 与 react-native-reanimated 深度集成,使用 useSharedValueuseAnimatedStyle 可实现高性能动画。在 Gesture API 中直接使用 .onBegin.onUpdate.onEnd 更新共享值。

示例:拖拽后带回弹效果

const isPressed = useSharedValue(false);
const offset = useSharedValue({ x: 0, y: 0 });
const start = useSharedValue({ x: 0, y: 0 });

const pan = Gesture.Pan()
  .onStart(() => {
    isPressed.value = true;
  })
  .onUpdate((e) => {
    offset.value = {
      x: e.translationX + start.value.x,
      y: e.translationY + start.value.y,
    };
  })
  .onEnd(() => {
    start.value = {
      x: offset.value.x,
      y: offset.value.y,
    };
  })
  .onFinalize(() => {
    isPressed.value = false;
  });

const animatedStyle = useAnimatedStyle(() => ({
  transform: [
    { translateX: offset.value.x },
    { translateY: offset.value.y },
    { scale: withSpring(isPressed.value ? 1.2 : 1) },
  ],
}));

return (
  <GestureDetector gesture={pan}>
    <Animated.View style={[styles.box, animatedStyle]} />
  </GestureDetector>
);

7. 实战:打造一个可拖拽缩放旋转的卡片

综合应用 PanPinchRotation 组合手势。

import React from 'react';
import { StyleSheet } from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

const TransformCard = () => {
  const scale = useSharedValue(1);
  const rotation = useSharedValue(0);
  const focalX = useSharedValue(0);
  const focalY = useSharedValue(0);

  const pinch = Gesture.Pinch()
    .onUpdate((e) => {
      scale.value = e.scale;
      focalX.value = e.focalX;
      focalY.value = e.focalY;
    })
    .onEnd(() => {
      scale.value = withSpring(1);
    });

  const rotate = Gesture.Rotation()
    .onUpdate((e) => {
      rotation.value = e.rotation;
    })
    .onEnd(() => {
      rotation.value = withSpring(0);
    });

  const composed = Gesture.Simultaneous(pinch, rotate);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: focalX.value },
      { translateY: focalY.value },
      { scale: scale.value },
      { rotate: `${rotation.value}rad` },
      { translateX: -focalX.value },
      { translateY: -focalY.value },
    ],
  }));

  return (
    <GestureDetector gesture={composed}>
      <Animated.View style={[styles.card, animatedStyle]} />
    </GestureDetector>
  );
};

8. 常见问题与注意事项

  • 手势冲突:若手势被父级滚动组件占用,可使用 simultaneousHandlerswaitFor 属性协调。
  • 性能:尽量使用原生驱动动画(Reanimated),避免频繁 setState 更新。
  • 嵌套 ScrollView:需要给 ScrollView 添加 NativeViewGestureHandler 包裹,否则拖拽可能被外部 Pan 捕获。
  • Android 物理返回键:Gesture Handler 可能会拦截返回手势,注意使用 enabled 属性动态禁用。

9. 总结

React Native Gesture Handler 是构建流畅触摸交互的基石。从基础的单点手势到复杂的多手势组合,它能显著提升应用的操作体验。配合 Reanimated,你可以轻松实现自然且高性能的动效。本指南涵盖了日常开发中 90% 的场景,现在就动手在你的应用中实践吧。