Android开发app开发Android开发

你在Android中遇到过哪些滑动冲突?

2016-08-20  本文已影响505人  cooperise

对于滑动冲突,相信安卓开发的人都会有这种体会:本来从网上下载的demo运行得好好的,但是只要出现滑动冲突,demo就无法正常工作了。许多开发者面对滑动冲突都会显得束手无策,(包括小编)于是小编就赶紧到处学习方法,并整理了下面的滑动冲突类型及解决方法,希望对和小编一样的初学者有帮助。

常见的冲突场景

外部滑动方向和内部滑动方向不一致

在主流应用中,几乎都会出现这种效果:首页可以通过左右滑动来切换页面,而每个页面内部往往又是一个ListView,这种情形下是有滑动冲突的(但是ViewPager内部处理了这种滑动冲突)

处理规则

—— 根据用户滑动的方向决定让内部View还是外部View拦截点击事件

外部滑动方向和内部滑动方向一致

在这类场景里,可以想象父View可以通过上下滑动切换页面,然而内部还是一个ListView,当用户滑动的时候系统不知道该将滑动事件分发给谁

处理规则

—— 根据业务的规定决定让内部View还是外部View拦截点击事件

比如说上述例子,可以采用内部拦截法,优先将滑动事件交给内部ListView处理,当ListView已经到达顶部或者底部已经无法再进行同方向的滑动时,就将滑动事件交回给外部View处理,实现换页功能。

多种情况的嵌套冲突

这类场景也很常见,假如你的首页是一个ViewPager,可以来回切换不同页面,每个页面中又有各自的ListView,然后其实还隐藏着一个SlidingMenu在左侧。

处理规则

—— 根据业务的规定决定让内部View还是外部View拦截点击事件

主要是最SlidingMenu的处理,业务上可以要求当用户的向右滑动是从app最左侧边缘开始时才将事件交给SlidingMenu处理。其他部分可以跟第一个场景一样。

常用解决方式

public boolean onInterceptTouchEvent(MotionEvent event){
     boolean intercepted = false;
     int x = (int) event.getX();
     int y = (int) event.getY();
     switch (event.getAction()){
     case MotionEvent.ACTION_DOWN:{
          // 对于ACTION_DOWN这个事件,父容器必须返回false,因为父容 器一旦拦截了
          // ACTION_DOWN,后续的ACTION_MOVE和ACTION_UP也都会直接交由父容器处理
          intercepted = false;
          break;
     }
     case MotionEvent.ACTION_MOVE:{
          if (父容器需要当前点击事件) {
               intercepted = true;
          } else {
               intercepted = false;
          }
          break;
     }
     case MotionEvent.ACTION_UP:{
          intercepted = false;
          break;
     }
     default:
          break;
     }
     mLastXIntercept = x;
     mLastYIntercept = y;
     return intercepted;
}
public boolean dispatchTouchEvent(MotionEvent event){
     int x = (int) event.getX();
     int y = (int) event.getY();
     switch (event.getAction()){
     case MotionEvent.ACTION_DOWN:{
          parent.requestDisallowInterceptTouchEvent(true);
          break;
     }
     case MotionEvent.ACTION_MOVE:{
          int deltaX = x - mLastX;
          int deltxY = y - mLastY;
          if (父容器需要当前点击事件) {
               parent.requestDisallowInterceptTouchEvent(false);
          } 
          break;
     }
     case MotionEvent.ACTION_UP:{
          break;
     }
     default:
          break;
     }
     mLastX = x;
     mLastY = y;
     return super.dispatchTouchEvent(event);
}

另外,父容器也要做如下修改:

public boolean onInterceptTouchEvent(MotionEvent event){
      int action = event.getAction();
      if (action == MotionEvent.ACTION_DOWN) {
          return false;
      } else {
          return true;
      }
}
上一篇下一篇

猜你喜欢

热点阅读