react-native系列(21)API篇:手势PanResponder详解

感谢作者,原文链接react-native系列(21)API篇:手势PanResponder详解-蒲公英云

为方便记录

PanResponder库用于处理用户的手势操作,如单点触摸滑屏、多点触摸放大缩小等手势。

PanResponder的创建代码如下:

 
  1. this._panResponder = PanResponder.create({
  2. // 返回ture时,表示该组件愿意成为触摸事件的响应者,如触摸点击。默认返回false。
  3. onStartShouldSetPanResponder: () => true,
  4. // 返回ture时,表示该组件愿意成为触摸(滑屏)事件的响应者,如触摸滑屏,默认返回false。
  5. onMoveShouldSetPanResponder: () => true,
  6. // 与onStartShouldSetPanResponder相同,当此组件A里包含了子组件B也为触摸事件响应者时,若此时设为true,则父组件A优先级更高
  7. onStartShouldSetPanResponderCapture: () => true,
  8. // 与onMoveShouldSetPanResponder相同,当此组件A里包含了子组件B也为触摸事件响应者时,若此时设为true,则父组件A优先级更高
  9. onMoveShouldSetPanResponderCapture: () => true,
  10. // 手势刚开始触摸(即刚接触屏幕时)时,若响应成功则触发该事件
  11. onPanResponderGrant: (evt, gestureState) => {},
  12. // 手势刚开始触摸(即刚接触屏幕时)时,若响应失败则触发该事件,失败原因有可能是其它组件正在响应手势且不肯放权
  13. onResponderReject: (evt, gestureState) => {},
  14. // 手势滑动时触发该事件
  15. onPanResponderMove: (evt, gestureState) => {},
  16. // 手势松开时触发该事件
  17. onPanResponderRelease: (evt,gestureState) => {},
  18. // 当其它组件需要响应手势时,此时为ture则表示本组件愿意放权给其它组件响应;为false时表示不放权,依然由本组件来响应手势事件
  19. onPanResponderTerminationRequest: (evt, gestureState) => true,
  20. // 当组件响应放权后(即由其它组件拿到了手势响应权)触发该事件
  21. onPanResponderTerminate: (evt, gestureState) => {}
  22. });

监听的事件中都会返回2个回调参数,evt 和 gestureState。

回调参数1: evt字段下的nativeEvent(evt.nativeEvent)对象格式如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

属性描述

changedTouches

所有发生变化的触摸事件的数组集合,该属性数据可用于多个触摸点

identifier

触摸点的 ID

locationX

触摸点相对于父元素的横坐标

locationY

触摸点相对于父元素的纵坐标

pageX

触摸点相对于根元素的横坐标

pageY

触摸点相对于根元素的纵坐标

target

触摸点所在的元素 ID

timestamp

触摸事件的时间戳,可用于移动速度的计算

touches

当前屏幕上的所有触摸点的集合。与changedTouches区别在于:当响应拖动Move事件时,与changedTouches数据一样。在响应释放Release事件时,touches将没有数据而changedTouches有。

回调参数2:gestureState字段格式: 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

属性描述

stateID

触摸状态的 ID。在屏幕上有至少一个触摸点的情况下,这个 ID 会一直有效。

moveX

触摸点相对于根元素的横坐标,该坐标值会随着手势移动而变化

moveY

触摸点相对于根元素的纵坐标,该坐标值会随着手势移动而变化

x0

当刚发生手势响应时触摸点相对于根元素的横坐标,该坐标值不会随着手势移动而变化

y0

当刚发生手势响应时触摸点相对于根元素的纵坐标,该坐标值不会随着手势移动而变化

dx

从触摸操作开始时的累计横向路程

dy

从触摸操作开始时的累计纵向路程

vx

当前的横向移动速度

vy

当前的纵向移动速度

numberActiveTouches

当前在屏幕上的有效触摸点的数量,如当只有一根手指头触摸屏幕时,值为1

以下是一个单点触摸拖动效果的代码:

 
  1. import React from 'react';
  2. import { View, PanResponder, StyleSheet } from 'react-native';
  3. // 触屏手势
  4. class PanResponderAPI extends React.Component {
  5. UNSAFE_componentWillMount() {
  6. this._previousLeft = 0;
  7. this._previousTop = 0;
  8. this._circleStyles = {
  9. style: {
  10. left: this._previousLeft,
  11. top: this._previousTop
  12. },
  13. };
  14. }
  15. constructor(props){
  16. super(props);
  17. this._panResponder = PanResponder.create({
  18. onStartShouldSetPanResponder: () => true, // 返回ture时,表示该组件愿意成为触摸事件的响应者,如触摸点击。默认返回false。
  19. onMoveShouldSetPanResponder: () => true, // 返回ture时,表示该组件愿意成为触摸(滑屏)事件的响应者,如触摸滑屏,默认返回false。
  20. onStartShouldSetPanResponderCapture: () => true, // 与onStartShouldSetPanResponder相同,当此组件A里包含了子组件B也为触摸事件响应者时,若此时设为true,则父组件A优先级更高
  21. onMoveShouldSetPanResponderCapture: () => true, // 与onMoveShouldSetPanResponder相同,当此组件A里包含了子组件B也为触摸事件响应者时,若此时设为true,则父组件A优先级更高
  22. onPanResponderGrant: () => {}, // 手势刚开始触摸(即刚接触屏幕时)时,若响应成功则触发该事件
  23. onResponderReject: () => {}, // 手势刚开始触摸(即刚接触屏幕时)时,若响应失败则触发该事件,失败原因有可能是其它组件正在响应手势且不肯放权
  24. onPanResponderMove: (evt, gestureState) => {
  25. this._circleStyles.style.left = this._previousLeft + gestureState.dx;
  26. this._circleStyles.style.top = this._previousTop + gestureState.dy;
  27. this._updateNativeStyles();
  28. }, // 手势滑动时触发该事件
  29. onPanResponderRelease: (evt,gestureState) => {
  30. // 写法 一
  31. // this._previousLeft = evt.nativeEvent.pageX-evt.nativeEvent.locationX;
  32. // this._previousTop = evt.nativeEvent.pageY-evt.nativeEvent.locationY;
  33. // 写法 二
  34. this._previousLeft += gestureState.dx;
  35. this._previousTop += gestureState.dy;
  36. }, // 手势松开时触发该事件
  37. onPanResponderTerminationRequest: () => true, // 当其它组件需要响应手势时,此时为ture则表示本组件愿意放权给其它组件响应;为false时表示不放权,依然由本组件来响应手势事件
  38. onPanResponderTerminate: () => {} // 当组件响应放权后(即由其它组件拿到了手势响应权)触发该事件
  39. });
  40. }
  41. _updateNativeStyles() {
  42. this.circle && this.circle.setNativeProps(this._circleStyles);
  43. }
  44. render(){
  45. return(
  46. <View style={
  47. {backgroundColor:'green', flex:1, marginLeft: 100}}>
  48. <View
  49. ref={circle => {
  50. this.circle = circle ;
  51. }}
  52. style={[styles.container]}
  53. {...this._panResponder.panHandlers}
  54. ></View>
  55. </View>
  56. );
  57. }
  58. }
  59. const styles = StyleSheet.create({
  60. container: {
  61. width: 100,
  62. height: 100,
  63. borderWidth: 1,
  64. borderRadius: 100,
  65. backgroundColor: 'yellow'
  66. }
  67. });
  68. export default PanResponderAPI;

效果:

 

这里有一个细节,当黄球拖动出绿色区域后,将无法拖动。因为PanResponder的事件传递仅冒泡当父元素一级就会停止冒泡,故拖动黄球到白色区域(其父元素以外的层级)时并不会触发onPanResponderMove事件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值