Android解决滑动冲突的方式

来源:互联网 发布:信用社支票打印软件 编辑:程序博客网 时间:2024/05/22 16:57

一般滑动冲突有三种情况:

1,外部View的滑动方向和内部View的滑动方向一致
2,外部View的滑动方向和内部View的滑动方向不一致
3,两种情况结合

一般我们解决滑动冲突时利用事件的分发机制进行处理。有两种方式:

外部拦截法
内部拦截法

外部拦截法

外部拦截是通过父容器对事件进行拦截处理,如果父容器不需要该事件,则不进行拦截,将该事件传递给子View。如果父容器决定拦截,则在父容器的onTouchEvent 方法中直接进行该事件的处理。这种方式符合事件的分发机制。

具体措施是修改父容器的拦截事件方法onInterceptTouchEvent中,在达到某一个条件的时候返回True,就可以将事件拦截下来交给onTouchEvent方法进行处理。

需要注意的是:如果只是想在某些时候拦截,有一些情况还是要讲事件分发给子View来进行处理,则父容器不能对 DOWN 事件进行拦截。因为如果在拦截事件方法中将 DOWN方法拦截下来了,那么后续的MOVE、UP事件就只能在当前View的处理时间方法OnTouchEvent中处理了,这样拦截就没有意义了。
拦截只是在满足一定条件下的时候进行拦截,并不是所有的情况都进行拦截。

内部拦截法

父容器不拦截任何事件,所有事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交由父容器处理。这种方法与Android中的事件分发机制不一致,需要配合 requestDisallowInterceptTouchEvent()方法才能正常工作。

requestDisallowInterceptTouchEvent()方法子View用来告诉父容器不要拦截我的事件,

public boolean dispatchTouchEvent(MotionEvent event) {    ...    switch (action) {      case MotionEvent.ACTION_MOVE:            getParent().requestDisallowInterceptTouchEvent(true);        break;      case MotionEvent.ACTION_MOVE:        if(子元素需要处理此事件)              getParent().requestDisallowInterceptTouchEvent(true);        break;      case MotionEvent.ACTION_UP: {        break;    }    ...    return super.dispatchTouchEvent(event);;  }

父容器中,不能对Move时间进行拦截

public boolean onInterceptTouchEvent(MotionEvent ev) {      int action=ev.getAction();      if(action==MotionEvent.ACTION_DOWN){        return false;      }else {        return true;      }    }

为什么要除了DOWN事件以外呢?因为如果一旦父容器拦截了DOWN事件,那么后续事件将 不再会传递到子元素了,内部拦截法也就失去作用了;DOWN是所有事件的开始,如果一个View把DOWN事件拦截了,那么MOVE、UP也将会被拦截。

外部拦截法是符合正常逻辑的,按照事件隧道式分发过程,如果父容器需要就直接拦截,不需要则传递到子View;内部拦截法相当于人为干预分发这个 过程,我会保证事件先都到子View上面,至于子View需不需要就要看我自己了,如果我不需要就回传给父容器了,需要的话自己就消耗掉了;感觉这两种方 式只是父容器和子View处理事件的优先级不同而已;

原创粉丝点击