React Native通过修改ScrollableTabView和ViewPager来解决左右滑动冲突的问题

1.背景

  在文章例子中的RN(以下用RN表示React Native)版本是0.43.3。RN官方和非官方提供了很多左右滑动的控件和组件,作者使用的比较多的就是react-native-scrollable-tab-view和react-native-viewpager(之前作为一个Android开发者,对ViewPager情有独钟),它们在单独使用的时候并没有什么问题,使用的方法也很简单。但是在实际的开发中,比如主页面左右滑动切换Tab,同时子页面中又有左右切换轮播图的组件,这个时候就会有左右滑动冲突的问题,如果不加以处理的话,实际的效果体检就会很差。俗话说站在巨人的肩膀上看得远(其实是作者比较菜,能力有限),本文就是在这两个控件的基础上进行改进来解决这个问题。

http://www.jianshu.com/p/22d25be7782e

2.下载组件

  接下来要用到的两个组件的Github地址分别为,
https://github.com/skv-headless/react-native-scrollable-tab-view
https://github.com/race604/react-native-viewpager
上面都有它们的介绍,相关Api以及如何使用的例子,在这里就不多加以介绍了,这里主要讲如何修改去解决活动冲突的问题

3.问题分析和解决思路

  那么问题来了,该怎么去解决这个滑动冲突的问题呢?
  如果开发过Android项目可能知道,遇到这种问题的解决方式一般是使用ViewPager(父View),和ChildViewPager(子View),一般的做法就是在子View中接管Touch事件,当子Viewr中可以进行左滑和右滑操作时,禁止父View的滑动,而当子View滑动到底的时候,把Touch事件交出来给父View,同时允许父View进行滑动。基本的解决思路就是这样的。首先在开始之前,对于RN下手势事件不了解不熟悉的可以看下RN官方中文网站的介绍,地址如下:http://reactnative.cn/docs/0.43/gesture-responder-system.html

4.解决问题

  首先我们找到ViewPager中对于手势控制的代码,同时将我们的分析思路用代码进行实现

onMoveShouldSetPanResponder: (e, gestureState) => {
          let needMove=false;
          //手指从左往右滑动
          if(gestureState.dx>0&&this.state.currentPage>0){
              needMove=true;
          }
          //手指从右往左滑动
          if(gestureState.dx<0&&this.state.currentPage<this.props.dataSource.getPageCount()-1){
              needMove=true;
          }
        if (Math.abs(gestureState.dx) > Math.abs(gestureState.dy)&&needMove) {
          if (this.props.locked !== true && !this.fling) {
             this.props.hasTouch && this.props.hasTouch(true);
             return true;
          }
        }
      },

  判断手指是从左往右滑动的时候,并且当处于非第0项的时候,或者手指是从右往左滑动的时候,并且当处于非最后一项时候,那么此时的手势操作应该交给子View,同时可以看到代码
this.props.hasTouch && this.props.hasTouch(true); 意思就是告诉父View,此时我接管了手势操作,并且本次滑动操作成功。那么同理,当不需要滑动操作的时候应该告诉父View,我不需要滑动操作了。果然在ViewPager的release方法中找到了该方法的调用

var release = (e, gestureState) => {
      var relativeGestureDistance = gestureState.dx / deviceWidth,
          //lastPageIndex = this.props.children.length - 1,
          vx = gestureState.vx;

      var step = 0;
      if (relativeGestureDistance < -0.5 || (relativeGestureDistance < 0 && vx <= -1e-6)) {
        step = 1;
      } else if (relativeGestureDistance > 0.5 || (relativeGestureDistance > 0 && vx >= 1e-6)) {
        step = -1;
      }

      this.props.hasTouch && this.props.hasTouch(false);

      this.movePage(step, gestureState);
    }

  有了这些之后,我们就可以在父View之中根据这状态来进行相关的操作了

 <ScrollableTabView
                    locked={this.state.isLocked}
                      >
                    {this._getChildItem()}
 </ScrollableTabView>

 //true表示内部需要滑动,此时外部需要lock住
    _hasTouch = (isTouch) => {
        this.setState({isLocked: isTouch})
  }

  通过对ScrollableTabView属性的修改来进行左右滑动的控制。我们来看下分别在ios和android下的效果


ios上的效果

android上的效果


  从效果上来看偶尔会有误触的情况,但是总体上的效果还可以接受

5.最后

  作者接触RN还不到一个月的时间,之前一直是Android开发,能力有限,现在更多的是使用一些比较成熟的框架或者组件。当然要根据一些业务的需求进行修改。最后,奉上例子的Github地址:https://github.com/hzl123456/ChildViewPagerDemo
(记得修改ViewPager的代码)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值