view是显示组件的基类,viewgroup继承自view是布局的基类
viewgroup包含view,viewgroup。
view的touch事件总是从view根节点开始向下传递,根据点击的位置判断传递给哪一个子view,直到子节点没有子节点,这个时候touch事件被该view消耗,事件传递结束。
如果该view没有使用,那么事件会依次向上传递,直到有view消耗这个事件,最后还没有view消耗,Activity就会处理。
解决滑动冲突的原理
viewtouch事件分发过程的三个重要函数:
dispatchTouchEvent负责touch的分发
onInterceptTouchEvent 负责拦截touch事件
ontouchEvent最终处理touch事件
解决办法(两种)
1.外部拦截法
当不想把事件传递给子控件时,在onInterceptTouchEvent返回true即可拦截,这个时候子控件将不会再接收到这一次的touch事件流(ACTION_DOWN,ACTION_MOVE,ACTION_UP)
public boolean onInterceptTouchEvent(MotionEvent ev) {
if ( condition ) {
return true;
}
return false;
}
2.内部拦截法
让父控件拦截除了ACTION_DOWN以外的所有事件,如果连ACTION_DOWN都拦截那么子控件将无法接收touch事件。
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
return false;
} else {
return true;
}
}
然后在控件内部分发事件的时候请求需要的事件。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
//通知父容器不要拦截事件
parent.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
if ( <condition> ){
//通知父容器拦截此事件
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
parent.requestDisallowInterceptTouchEvent(false);
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}