在移动应用中,手势交互 是提升用户体验的重要手段。通过手势,用户可以更直观、自然地与应用进行交互。React Native 提供了强大的手势处理系统,允许开发者轻松实现各种手势操作,如滑动、缩放、旋转等。本章节将详细介绍 React Native 中的手势系统,包括如何使用内置的 PanResponder
和 Gesture Responder System
,以及如何使用第三方库(如 react-native-gesture-handler
)实现更复杂的手势交互。
2.1 手势系统概述
在 React Native 中,手势系统主要由以下两个部分组成:
- Gesture Responder System(手势响应系统): 负责处理触摸事件,确定哪个组件应该响应手势。
- PanResponder: 基于 Gesture Responder System,提供更高级的手势处理功能,支持多点触控和手势识别。
React Native 还提供了第三方库 react-native-gesture-handler
,用于实现更复杂和高效的手势交互。
2.2 使用 PanResponder
PanResponder
是 React Native 提供的一个高级手势处理 API,基于 Gesture Responder System 构建。它可以处理多种手势事件,如 onMoveShouldSetPanResponder
, onPanResponderMove
, onPanResponderRelease
等。
2.2.1 基本用法
步骤:
-
创建 PanResponder:
使用
PanResponder.create
创建一个 PanResponder 对象,并定义手势处理函数。const panResponder = useRef(PanResponder.create({onStartShouldSetPanResponder: (evt, gestureState) => true,onPanResponderMove: (evt, gestureState) => {// 处理手势移动},onPanResponderRelease: (evt, gestureState) => {// 处理手势释放},}) ).current;
-
绑定 PanResponder 到组件:
将 PanResponder 的事件处理器绑定到组件的
onStartShouldSetPanResponder
,onPanResponderMove
,onPanResponderRelease
等属性。<View {...panResponder.panHandlers} style={styles.box}>{/* 内容 */} </View>
示例:
// DraggableBox.js
import React, { useRef } from 'react';
import { View, Text, StyleSheet, PanResponder, Animated } from 'react-native';const DraggableBox = () => {const pan = useRef(new Animated.ValueXY()).current;const panResponder = useRef(PanResponder.create({onStartShouldSetPanResponder: () => true,onPanResponderMove: Animated.event([null,{dx: pan.x, // 横轴移动距离dy: pan.y, // 纵轴移动距离},],{ useNativeDriver: false }),onPanResponderRelease: () => {Animated.spring(pan, {toValue: { x: 0, y: 0 },useNativeDriver: false,}).start();},})).current;return (<View style={styles.container}><Animated.View{...panResponder.panHandlers}style={[styles.box,{transform: [{ translateX: pan.x }, { translateY: pan.y }],},]}><Text style={styles.text}>Drag Me!</Text></Animated.View></View>);
};const styles = StyleSheet.create({container: {flex: 1,justifyContent: 'center',alignItems: 'center',},box: {width: 200,height: 200,backgroundColor: '#f0f0f0',justifyContent: 'center',alignItems: 'center',borderRadius: 10,},text: {fontSize: 18,},
});export default DraggableBox;
解释:
Animated.event
将手势移动事件绑定到pan
动画值。onPanResponderRelease
使用Animated.spring
实现回弹动画。
2.2.2 多点触控
PanResponder
支持多点触控,可以处理多个手指同时操作。
示例:
// MultiTouchBox.js
import React, { useRef } from 'react';
import { View, Text, StyleSheet, PanResponder, Animated } from 'react-native';const MultiTouchBox = () => {const scale = useRef(new Animated.Value(1)).current;const pan = useRef(new Animated.ValueXY()).current;const panResponder = useRef(PanResponder.create({onStartShouldSetPanResponder: () => true,onPanResponderMove: Animated.event([null,{dx: pan.x,dy: pan.y,scale: scale,},],{ useNativeDriver: false }),onPanResponderRelease: () => {Animated.spring(scale, {toValue: 1,useNativeDriver: false,}).start();Animated.spring(pan, {toValue: { x: 0, y: 0 },useNativeDriver: false,}).start();},})).current;return (<View style={styles.container}><Animated.View{...panResponder.panHandlers}style={[styles.box,{transform: [{ translateX: pan.x }, { translateY: pan.y }, { scale }],},]}><Text style={styles.text}>Multi-Touch!</Text></Animated.View></View>);
};const styles = StyleSheet.create({container: {flex: 1,justifyContent: 'center',alignItems: 'center',},box: {width: 200,height: 200,backgroundColor: '#f0f0f0',justifyContent: 'center',alignItems: 'center',borderRadius: 10,},text: {fontSize: 18,},
});export default MultiTouchBox;
解释:
- 通过
scale
动画值实现缩放效果。 - 支持多点触控,实现缩放和拖拽。
2.3 使用 react-native-gesture-handler
react-native-gesture-handler
是一个功能强大的手势处理库,支持更复杂的手势交互,如滑动、缩放、旋转等。
2.3.1 安装 react-native-gesture-handler
npm install react-native-gesture-handler
2.3.2 基本用法
示例:
// SwipeableCard.js
import React from 'react';
import { View, Text, StyleSheet, Animated } from 'react-native';
import { PanGestureHandler, State } from 'react-native-gesture-handler';const SwipeableCard = () => {const translateX = React.useRef(new Animated.Value(0)).current;const onGestureEvent = Animated.event([{ nativeEvent: { translationX: translateX } }],{ useNativeDriver: true });const onHandlerStateChange = (event) => {if (event.nativeEvent.state === State.END) {if (translateX._value > 100) {Animated.timing(translateX, {toValue: 300,duration: 300,useNativeDriver: true,}).start();} else {Animated.timing(translateX, {toValue: 0,duration: 300,useNativeDriver: true,}).start();}}};return (<View style={styles.container}><PanGestureHandler onGestureEvent={onGestureEvent} onHandlerStateChange={onHandlerStateChange}><Animated.View style={[styles.card, { transform: [{ translateX }] }]}><Text style={styles.text}>Swipe Me!</Text></Animated.View></PanGestureHandler></View>);
};const styles = StyleSheet.create({container: {flex: 1,justifyContent: 'center',alignItems: 'center',},card: {width: 200,height: 200,backgroundColor: '#f0f0f0',justifyContent: 'center',alignItems: 'center',borderRadius: 10,},text: {fontSize: 18,},
});export default SwipeableCard;
解释:
PanGestureHandler
处理滑动手势。Animated.event
将手势事件绑定到translateX
动画值。- 根据滑动距离实现卡片滑动效果。
2.3.3 高级用法
react-native-gesture-handler
支持多种手势识别器,如 PinchGestureHandler
, RotationGestureHandler
, TapGestureHandler
等。
作者简介
前腾讯电子签的前端负责人,现 whentimes tech CTO,专注于前端技术的大咖一枚!一路走来,从小屏到大屏,从 Web 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!
温馨提示:可搜老码小张公号联系导师