在 React Native 中,PanResponder 是一个用于处理触摸手势的底层 API,特别是用于处理平移(pan)手势(即用户在屏幕上拖动手指)。PanResponder 允许你捕获并响应一系列的触摸事件,如开始(start)、移动(move)、结束(end)和取消(cancel)。这使得开发者能够创建复杂的触摸交互,如拖拽、滑动等。
基本用法
const ExampleComponent = () => {
const panResponder = React.useRef(
PanResponder.create({
// 要求成为响应者:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onPanResponderGrant: (evt, gestureState) => {
// 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
// gestureState.d{x,y} 现在会被设置为0
},
onPanResponderMove: (evt, gestureState) => {
// 最近一次的移动距离为gestureState.move{X,Y}
// 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
},
onPanResponderTerminationRequest: (evt, gestureState) =>
true,
onPanResponderRelease: (evt, gestureState) => {
// 用户放开了所有的触摸点,且此时视图已经成为了响应者。
// 一般来说这意味着一个手势操作已经成功完成。
},
onPanResponderTerminate: (evt, gestureState) => {
// 另一个组件已经成为了新的响应者,所以当前手势将被取消。
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
// 默认返回true。目前暂时只支持android。
return true;
},
}),
).current;
return <View {...panResponder.panHandlers} />;
};
创建一个可以拖动的视图代码栗子:
import React, { useRef, useState } from 'react';
import { View, Animated, PanResponder } from 'react-native';
const DraggableView = () => {
const [position, setPosition] = useState({ x: 0, y: 0 });
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: (_, { dx, dy, x, y }) => {
// 允许在水平或垂直方向上移动超过一定阈值(例如 5)时成为响应者
return Math.abs(dx) > 5 || Math.abs(dy) > 5;
},
onPanResponderGrant: (_, { x, y }) => {
// 当开始拖动时,记录初始位置
setPosition((prev) => ({ ...prev, moveX: x, moveY: y }));
},
onPanResponderMove: (_, { dx, dy }) => {
// 在拖动过程中更新位置
setPosition((prev) => ({ ...prev, x: prev.x + dx, y: prev.y + dy }));
},
onPanResponderRelease: (_, { x, y, vx, vy }) => {
// 当拖动结束时,可以执行一些清理或动画逻辑
// 这里只是简单地停止更新位置
},
})
).current;
const animatedStyle = {
transform: [{ translateX: position.x }, { translateY: position.y }],
};
return (
<Animated.View
style={[styles.container, animatedStyle]}
{...panResponder.panHandlers}
>
{/* 视图内容 */}
<Text>Drag Me</Text>
</Animated.View>
);
};
const styles = {
container: {
width: 100,
height: 100,
backgroundColor: 'skyblue',
// 添加一些样式以确保视图可以拖动
marginTop: 50,
marginLeft: 50,
},
};
export default DraggableView;