Skip to content

手势API

这一小节我们来看一下 RN 中和手势相关的 API

文档地址:https://reactnative.cn/docs/panresponder

我们先来看一个简单的例子:

import React from 'react'
import { PanResponder, StyleSheet, View } from 'react-native'
export default function App() {
const panResponder = PanResponder.create({
onStartShouldSetPanResponder: function () {
console.log('shouldstart')
return true
},
onPanResponderMove: function () {
console.log('moving')
},
onPanResponderRelease: function () {
console.log('release')
},
})
console.log(panResponder.panHandlers)
return (
<View style={styles.container}>
<View style={styles.box} {...panResponder.panHandlers}></View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
box: {
backgroundColor: '#61dafb',
width: 80,
height: 80,
borderRadius: 4,
},
})

在上面的示例中,我们通过 PanResponder 这个 APIcreate 方法来创建一个手势方法的集合对象。该方法接收一个配置对象,配置对象中能够传递的参数如下:

image-20220623150525365

可以看到,配置对象对应的每一个配置值都是一个回调函数,每个回调函数都接收两个参数,一个是原生事件对象,另一个是 gestureState 对象。

nativeEvent 原生事件对象有如下字段:

一个 gestureState 对象有如下的字段:

例如我们通过 gestureState 对象来判断用户手指的移动方向:

const panResponder = PanResponder.create({
onStartShouldSetPanResponder: function () {
console.log('shouldstart')
return true
},
onPanResponderMove: function (e, gs) {
console.log(`正在移动: X轴: ${gs.dx}, Y轴: ${gs.dy}`)
},
onPanResponderRelease: function (e, gs) {
console.log(`结束移动: X轴移动了: ${gs.dx}, Y轴移动了: ${gs.dy}`)
if (gs.dx > 50) {
console.log('由左向右')
} else if (gs.dx < -50) {
console.log('由右向左')
} else if (gs.dy > 50) {
console.log('由上向下')
} else if (gs.dy < -50) {
console.log('由下向上')
}
},
})

最后,我们把上一节课介绍的 Animated 结合起来,书写一个拖动小方块的示例:

import { useState } from 'react'
import { Animated, PanResponder, StyleSheet, View } from 'react-native'
export default function App() {
const [transXY] = useState(new Animated.ValueXY())
const panResponder = PanResponder.create({
onStartShouldSetPanResponder: function () {
console.log('shouldstart')
return true
},
onPanResponderMove: Animated.event(
[
null,
{
dx: transXY.x,
dy: transXY.y,
},
],
{ useNativeDriver: false }
),
onPanResponderRelease: function () {
Animated.spring(transXY, {
toValue: { x: 0, y: 0 },
useNativeDriver: false,
}).start()
},
})
return (
<View style={styles.container}>
<Animated.View
style={[
styles.box,
{
transform: [{ translateX: transXY.x }, { translateY: transXY.y }],
},
]}
{...panResponder.panHandlers}
/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
box: {
backgroundColor: '#61dafb',
width: 80,
height: 80,
borderRadius: 4,
},
})