Android中View的事件分发和拦截机制

来源:互联网 发布:天刀慕情捏脸数据 编辑:程序博客网 时间:2024/05/22 05:27

1.关系到事件分发和拦截机制的三个方法

1.dispatchTouchEvent(MotionEvent event)方法2.onInterceptTouchEvent(MotionEvent event)方法3.onTouchEvent(MotionEvent event)方法

2.dispatchTouchEvent(MotionEvent event)分发事件

*该方法主要是用来事件分发的,返回值有三种情况    1.返回 super.dispatchTouchEvent(ev)        会将事件分发下去    2.返回true        不会将事件分发下去,自己就调用当前View的onTouchEvent方法处理了    3.返回false        不会将事件分发下去*该方法内部其实自己调用了onInterceptTouchEvent方法,进行事件拦截,默认情况下不会拦截事件,将事件放行。*子View可以申请父View进行拦截/不拦截,其实也就是在内部判断是否调用onInterceptTouchEvent进行事件拦截。    1.getParent().requestDisallowIntercept(true)        申请父View不拦截,那就执行自己的onTouchEvent事件    2.getParent().requestDisallowIntercept(false)        申请拦截,父View将其事抢夺过来,执行父View的onTouchEvent事件

3.onInterceptTouchEvent(MotionEvent event)拦截事件

三种返回值:    1.true        将事件拦截,不在分发下去,执行当前View的onTouchEvent    2.false        将事件方法(默认就是放行),那子View会继续分发事件执行disPatchTouchEvent。    3. super.onInterceptTouchEvent(ev)                默认情况下不拦截

4.onTouchEvent(MotionEvent event)

是用来处理事件的,接收到分发的事件,就调用该方法去进行事件的处理返回true,就不将事件回传给父View,自己消费掉返回false和super.onTouchEvent(ev),将事件回传给父View,并由父View的的onTouchEvent来接收

5.Demo(案例)

1.两个ViewPager嵌套关系出现的问题。当两个ViewPager嵌套的时候,(ViewPager自带滑动功能)在滑动内层(子)ViewPager的时候,在没有做处理的情况下,外层(父)的ViewPager会抢夺滑动事件,所以会出现,滑动子ViewPager的时候,父ViewPager滑动了,这种用户体验就很差2.解决办法    1)自定义一个类继承ViewPager,作为内层的ViewPafder    2)复写onDispatchEvent(MptionEvent event)方法,    3)定义条件,在满足什么样条件下申请父View不拦截或者拦截        比如:在子ViewPager滑动到第一个页面并且从左往右滑动的时候,申请父View拦截,getParent().requestDisallowInterceptEvent(false),而子ViewPager默认到了第一个页面的时候,再继续向前一个不存在的页面是不能滑动的,这个时候父ViewPager就进行滑动,滑到子ViewPager最后一个页面并且继续从右往左滑动,同样的申请父View拦截。在其他情况下申请父View不拦截getParent().requestDisallowInterceptEvent(true),那么父ViewPager将不会个子ViewPager抢夺滑动事件,子ViewPager可以顺畅的滑动。3.code(代码)@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {    /***     * 当多个view容器嵌套一起,事件分发机制会起冲突     * 比如当两个ViewPager嵌套使用的时候,子ViewPager滑动的时候父Viewpager可能抢夺事件,     * 这样滑动子ViewPager的时候,父ViewPager跟着滑动 这个时候我们只需要子ViewPager滑动,就可以     * 使用requestDisallowInterceptTouchEvent(true)     * 这个方法去申请父view容器的是否拦截,将其参数这是为true就是申请父view容器不拦截,不拦截子控件的事件,     * 那子控件就做自己的onTouchEvent事件,父view容器就不会抢夺事件了,     *      * 可以设置条件当子ViewPager滑动到第一个或者最后一个了,就可以申请拦截,那么子ViewPager不能滑动的时候     * 父ViewPager在子ViewPager申请拦截之后就可以拦截子ViewPager,然后自己执行onTouchEvent事件     */    // 申请父控件不拦截    getParent().requestDisallowInterceptTouchEvent(true);    // 分析:    // 当滑动到第一个页面,而且从左往右滑动的时候,就申请拦截,让父ViewPager滑动    // 当滑动到最后一个页面的时候,而且从右往左滑动的时候,申请拦截    // 其他情况申请不拦截,让子Viewpager滑动    switch (ev.getAction()) {    case MotionEvent.ACTION_DOWN:// 按下        // 获取按下的X Y坐标        downX = ev.getX();        downY = ev.getY();        break;    case MotionEvent.ACTION_MOVE:// 移动        // 获取移动的X Y 坐标        float moveX = ev.getX();        float moveY = ev.getY();        float dX = downX - moveX;        float dY = downY - moveY;        // 如果Y轴方向移动,什么事情都不做,值关注横向滑动        if (Math.abs(dX) > Math.abs(dY)) {            // 表示横向移动            // 如果是当前页面不是第一个页面 并且是从右往左滑动,申请不拦截            if (getCurrentItem() != 0 && dX < 0) {                getParent().requestDisallowInterceptTouchEvent(true);            } else if (getCurrentItem() < getChildCount() - 1 && dX > 0) {                //申请不拦截                getParent().requestDisallowInterceptTouchEvent(true);            } else {                // 申请拦截                getParent().requestDisallowInterceptTouchEvent(false);            }        }else{            //纵向  申请拦截            getParent().requestDisallowInterceptTouchEvent(false);        }        break;    }    //依然还是走父View中去分发事件    return super.dispatchTouchEvent(ev);}
原创粉丝点击