Skip to content

react-native-gesture-handler

  • react-native-gesture-handler 是处理手势的react-native库
手势API 名称一句话用途示例
PanGesture.Pan()拖动、滑动、速度追踪拖拽排序、右滑返回
TapGesture.Tap()单击、双击、长按双击放大、长按菜单
PinchGesture.Pinch()双指缩放图片/地图缩放
RotationGesture.Rotation()双指旋转图片旋转裁剪
FlingGesture.Fling()快速抛滑抛卡片、甩一甩
LongPressGesture.LongPress()长按计时语音按钮
ForceTouchGesture.ForceTouch()3D Touch 力度压感画笔
NativeGesture.Native()与原生 ScrollView 共存嵌套滚动、下拉刷新

PanGesture(拖动/滑动)

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

const translateX = useSharedValue(0);
const pan = Gesture.Pan()
  .onUpdate((e) => {
    translateX.value = e.translationX; // 实时位移
  })
  .onEnd((e) => {
    if (e.translationX > 120) translateX.value = withSpring(300); // 过半屏松手
    else translateX.value = withSpring(0);
  });

const style = useAnimatedStyle(() => ({
  transform: [{ translateX: translateX.value }],
}));

<GestureDetector gesture={pan}>
  <Animated.View style={[style, styles.card]} />
</GestureDetector>

TapGesture(单击/双击/长按)

tsx
const tap = Gesture.Tap()
  .numberOfTaps(2) // 双击
  .onEnd(() => {
    runOnJS(handleDoubleTap)(); // 回到 JS 线程
  });

<GestureDetector gesture={tap}>
  <Animated.View><Text>双击我</Text></Animated.View>
</GestureDetector>

LongPressGesture(长按)

tsx
const longPress = Gesture.LongPress()
  .minDuration(800)
  .onEnd(() => runOnJS(startRecord)());

<GestureDetector gesture={longPress}>
  <Animated.View><Text>长按录音</Text></Animated.View>
</GestureDetector>

PinchGesture(双指缩放)

tsx
const scale = useSharedValue(1);
const pinch = Gesture.Pinch()
  .onUpdate((e) => {
    scale.value = e.scale; // 实时缩放比
  })
  .onEnd(() => {
    scale.value = withSpring(Math.min(Math.max(scale.value, 0.5), 3));
  });

const style = useAnimatedStyle(() => ({
  transform: [{ scale: scale.value }],
}));

<GestureDetector gesture={pinch}>
  <Animated.Image source={img} style={[style, { width: 300, height: 300 }]} />
</GestureDetector>

RotationGesture(双指旋转)

tsx
const rotation = useSharedValue(0);
const rotate = Gesture.Rotation()
  .onUpdate((e) => {
    rotation.value = e.rotation; // 弧度
  })
  .onEnd(() => {
    rotation.value = withSpring(rotation.value % (2 * Math.PI));
  });

const style = useAnimatedStyle(() => ({
  transform: [{ rotate: `${rotation.value}rad` }],
}));

<GestureDetector gesture={rotate}>
  <Animated.View style={[style, styles.box]} />
</GestureDetector>

FlingGesture(快速抛滑)

tsx
const fling = Gesture.Fling()
  .direction(Directions.RIGHT)
  .onEnd(() => {
    translateX.value = withSpring(width); // 抛出屏幕
  });

<GestureDetector gesture={fling}>
  <Animated.View style={[style, styles.card]} />
</GestureDetector>

ForceTouch(3D Touch/力度)

tsx
const force = Gesture.ForceTouch()
  .onUpdate((e) => {
    force.value = e.force; // 0-1
  })
  .onEnd(() => {
    force.value = withTiming(0);
  });

const style = useAnimatedStyle(() => ({
  transform: [{ scale: 1 + force.value * 0.3 }],
}));

<GestureDetector gesture={force}>
  <Animated.View style={[style, styles.circle]} />
</GestureDetector>

组合 & 并发(多手势共存)

tsx
const simultaneous = Gesture.Simultaneous(
  Gesture.Pan(),
  Gesture.Pinch(),
  Gesture.Rotation()
);

<GestureDetector gesture={simultaneous}>
  <Animated.View style={[panStyle, pinchStyle, rotateStyle]} />
</GestureDetector>

性能优化

技巧代码
避免 JS 线程runOnJS() 只在必要时用
用 SharedValueconst x = useSharedValue(0); 替代 useState
分离耗时计算useAnimatedReaction(() => x.value, (cur) => runOnJS(update)(cur));
60 fps 监控useFrameCallback((f) => console.log(f.timeSincePreviousFrame));

与 ScrollView 共存(Native 模式)

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

<GestureHandlerRootView style={{ flex: 1 }}>
  <ScrollView>
    {/* 嵌套 Pan 不会冲突 */}
  </ScrollView>
</GestureHandlerRootView>

Released under the MIT License.