View的滑动冲突问题
1. 滑动冲突出现的三种情况
外部滑动方向和内部滑动方向不一致
外部滑动方向和内部滑动方向一致
上述两种情况的嵌套
但是这在使用ViewPager和listView的时候并不会出现滑动冲突的问题 那是因为ViewPager和listview已经替我们解决了滑动冲突的问题 但是如果是我们自己自定义的控件出现了问题 就没那么幸运了 因此我们还是要掌握滑动冲突的解决办法
2.滑动冲突的处理规则
滑动冲突虽然很烦人 但是它也不是很复杂 只要按照一定的处理规则就能解决
像第一种情况我们通常可以通过判断滑动的方向来进行事件的分发 如果水平方向滑动就交给水平方向滑动的控件处理,如果竖直方向滑动,那么就交给竖直方向的控件处理
对于第二种情况虽然无法根据滑动的角度判断交给哪个控件处理,但是它一定有既定的规则,我们只要按照这个规则来处理就可以了(不可能没有,如果没有如何判断哪个控件滑动呢?所以一定有)
对于第三种场景,类似与第二种 也要从业务上寻找分发事件的方式,虽然负责 但是一定可以实现
3.滑动冲突的两种解决办法
外部拦截法:
顾名思义,这个方法是在外部的控件中拦截事件 然后根据需要分发给控件的
伪代码如下:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
intercept = false;
break;
case MotionEvent.ACTION_MOVE:
if(满足父控件的要求){// 满足要求就拦截事件
intercept = true;
}else{
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
return intercept;
}
对于ACTION_DOWN 和 ACTION_UP 的intercept值的确定 是这个样子的
想象一下 事件开始的时候总是先响应 ACTION_DOWN 事件 如果在这个事件中设置了 intercept值为true 即中断了事件 那么不论滑动方向是如何的 都会被父控件拦截(因为ACTION_DOWN是事件序列的开头) 下面的ACTION_MOVE的判断就丝毫没有了意义 所以必须返回false 进入ACTION_MOVE 中判断是否需要拦截
ACTION_UP的道理也差不多 如果在ACTION_MOVE 中将事件交给了子控件处理 那么在ACTION_UP中 返回了true 又被父控件拦截了处理 也就是说子控件可能无法响应ACTION_UP事件 比如onclick方法 都可能无法响应 所以 这里要返回false
内部拦截法:
内部拦截法的意思是在子控件中处理拦截的逻辑 一般用的不是很多 外部拦截法使用比较多 但是这种方法也可以处理滑动冲突的问题
下面是伪代码:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
if(满足父控件的要求){// 满足要求就拦截事件
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(ev);
}
getParent().requestDisallowInterceptTouchEvent(false);这个方法 设置为true 表示父控件不拦截事件 false 表示父控件拦截事件
由于ACTION_DOWN事件不受这个的影响 所以不能让父控件拦截ACTION_DOWN事件 一旦拦截 那么所有的事件都不会传递到子控件中去 所以需要在父控件中 修改一下
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction()==MotionEvent.ACTION_DOWN){
return false;
}else{
return super.onInterceptTouchEvent(ev);
}
}
这样就可以解决滑动冲突问题了。。。