安卓爬坑系列之事件分发机制

发现问题

前几天想做一个外面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(有那么一点坑),不过借此了解了事件分发机制,这波不亏

你可能感兴趣的:(安卓爬坑系列之事件分发机制)