在移动应用中,手势交互 是提升用户体验的重要手段。通过手势,用户可以更直观、自然地与应用进行交互。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 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!
温馨提示:可搜老码小张公号联系导师