发现问题
前几天想做一个外面viewPager里面嵌套一个横向得recyclerview的效果,选择用外部拦截法去完成。先自定义了一个horizonViewPager,(里面还没有加recyclerview)首先重写了onInterceptTouchEvent方法,代码如下:
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercepted = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
final int action = ev.getAction() & MotionEvent.ACTION_MASK;
switch (action) {
case ACTION_DOWN: {
intercepted = false;
Log.d("luchixiang", "onInterceptTouchEvent: "+"down");
break;
}
case MotionEvent.ACTION_MOVE: {
/*int count = getChildCount();
View child;
child = getChildAt(0).findViewById(R.id.luchixaing4);
int[] location = new int[2];
child.getLocationOnScreen(location);*/
Log.d("luchixiang", "onInterceptTouchEvent: " + 1);
intercepted =false;
//1 if (y >= location[1] && y < location[1] + child.getHeight()) {
// intercepted = false;
// } else intercepted = true;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
}
return intercept;
}
一段十分简单的代码,但是在滑动的时候里面的日志没有打印出来,也就是在move动作的时候没有经过onInterceptTouchEvent这个方法
问题所在
首先在明确下面几点
- 父容易的ACTION_DOWN一定要为false,因为一旦决定拦截down属性,后面的move和up将不再进行判断,而是直接全部由该容器处理
- 当子容器中没有能消费事件时,即touchEvent和dispatchTouchEvent没有返回true时,该事件又会返回父容器,并且最终由父容器进行消费,即调用父容器的touchEvent
- 原则上ACTION_UP也需要返回false,如果返回true,并且滑动事件交给子View处理,那么子View将接收不到ACTION_UP事件,子View的onClick事件也无法触发。而父View不一样,如果父View在ACTION_MOVE中开始拦截事件,那么后续ACTION_UP也将默认交给父View处理
- 那么问题所在就得到了分析,因为父容器的action_down返回了false,而我的子容器又没有能处理action_down的方法,所以action_down事件返回给我的viewpager进行处理,而一旦拦截了down事件后,后面的事件也就不经过onInterceptTouchEvent方法,日志自然也不会进行打印
解决问题
再里面放进去recyclerview(有那么一点坑),不过借此了解了事件分发机制,这波不亏