React Native之PanResponder讲解与应用

         在原生的开发中,如果要自定义一些控件,可能会用到touch的相关方法,而React Native也有一套touch机制,说白了就是用JS写了一套方法打通android和ios平台,这里简单讲解下React Native(RN)的touch机制,这里先不过多深入研究,先熟悉下流程,至于RN的touch分发机制之后再详细讲解.

     PanResponder:可以将多点触摸操作协调成一个手势。它使得一个单点触摸可以接受更多的触摸操作,也可以用于识别简单的多点触摸手势。

    下面来看下如何创建:

componentWillMount(evt, gestureState){
    this._panResponder=PanResponder.create({
      onStartShouldSetPanResponder:this.onStartShouldSetPanResponder,
      onMoveShouldSetPanResponder:this.onMoveShouldSetPanResponder,
      onPanResponderGrant:this.onPanResponderGrant,
      onPanResponderMove:this.onPanResponderMove,
      onPanResponderRelease:this.onPanResponderEnd,
      onPanResponderTerminate:this.onPanResponderEnd,
    });
  }
上面代码相对比较清晰,至于为什么,这里我贴部分源码看下你就豁然明朗啦,,


具体的作用这里简单说明下:

onStartShouldSetPanResponder:用户开始触摸屏幕的时候,是否愿意成为响应者;默认返回false,无法响应,当返回true的时候则可以进行之后的事件传递。

onMoveShouldSetPanResponder:在每一个触摸点开始移动的时候,再询问一次是否响应触摸交互;

onPanResponderGrant:开始手势操作,也可以说按下去。给用户一些视觉反馈,让他们知道发生了什么事情!(如:可以修改颜色)

onPanResponderMove:最近一次的移动距离.如:(获取x轴y轴方向的移动距离 gestureState.dx,gestureState.dy)

onPanResponderRelease:用户放开了所有的触摸点,且此时视图已经成为了响应者。

onPanResponderTerminate:另一个组件已经成为了新的响应者,所以当前手势将被取消。

下面以一个简单的例子跑下整个流程。

功能:可以拖拽的小球,当松开那一刻判断小球是属于屏幕左边还是屏幕右边,属于左边则让小球紧靠屏幕左边,如靠屏幕右侧,则让小球靠屏幕右侧。

首先要成为响应者:

  //用户开始触摸屏幕的时候,是否愿意成为响应者;
  onStartShouldSetPanResponder(evt, gestureState){
   return true;
  }
  //在每一个触摸点开始移动的时候,再询问一次是否响应触摸交互;
  onMoveShouldSetPanResponder(evt, gestureState){
   return true ;
  }
比如我要门要修改点击小球后的颜色,可以在onPanResponderGrant方法中处理:

  // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
  onPanResponderGrant(evt, gestureState){
    console.log('onPanResponderGrant...');
   this.setState({
     style:{
         backgroundColor:'red',
         left:_previousLeft,
         top:_previousTop,
     }
   });
  }
_previousLeft和_previousTop是两个变量,用来记录小球移动坐标

接下来我们看下onPanResponderMove方法:

// 最近一次的移动距离为gestureState.move{X,Y}
  onPanResponderMove(evt, gestureState){
     _previousLeft=lastLeft+gestureState.dx;
     _previousTop=lastTop+gestureState.dy;

     if(_previousLeft<=0){
       _previousLeft=0;
     }
     if(_previousTop<=0){
       _previousTop=0;
     }
     if(_previousLeft>=Util.size.width-CIRCLE_SIZE){
       _previousLeft=Util.size.width-CIRCLE_SIZE;
     }
     if(_previousTop>=Util.size.height-CIRCLE_SIZE){
       _previousTop=Util.size.height-CIRCLE_SIZE;
     }
    //实时更新
    this.setState({
      style:{
          backgroundColor:'red',
          left:_previousLeft,
          top:_previousTop,
      }
    });
  }
主要是限制小球拖拽移动的时候不许出屏幕外部。

最后来看下当用户松开的onPanResponderRelease回调方法:

  // 用户放开了所有的触摸点,且此时视图已经成为了响应者。
  // 一般来说这意味着一个手势操作已经成功完成。
  onPanResponderEnd(evt, gestureState){
    lastLeft=_previousLeft;
    lastTop=_previousTop;

    this.changePosition();
  }
  /**
   根据位置做出相应处理
  **/
  changePosition(){

  if(_previousLeft+CIRCLE_SIZE/2<=Util.size.width/2){
    _previousLeft=lastLeft=0;

    this.setState({
              style:{
                  left:_previousLeft,
                  top:_previousTop,
                  }
             });
  }else{
  _previousLeft=lastLeft=Util.size.width-CIRCLE_SIZE;

  this.setState({
              style:{
                  left:_previousLeft,
                  top:_previousTop,
                    }
               });
       }
  }
主要就是判断下释放的那一刻,所处的位置,若属于左侧则置left=0,为右侧则至left=Util.size.width-CIRCLE_SIZE;

一切准备就绪,最后看我们如何运用在组件上吧,非常的简单:

<View
      {...this._panResponder.panHandlers}
      style={[styles.circle,this.state.style]}/>
这三个点其实就是对象的扩展运算符,说白了就是把panHandlers对象里面所有的属性填充到View中。通过源码我们也可以知道View中其实定义了一系列相关的属性:

propTypes: {
。。。
。。。
 onResponderGrant: PropTypes.func,
 onResponderMove: PropTypes.func,
 onResponderTerminationRequest: PropTypes.func,
 onStartShouldSetResponder: PropTypes.func,
}


到这里就结束了,整体上还算不复杂,就几个回调函数记住了就可以了。

最后看下效果图吧:



github:react-native-float-menu


 RN开发群:527459711.欢迎大伙加入.


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值