Android控件架构与自定义控件详解(四)——事件拦截机制分析

来源:互联网 发布:linux上如何卸载mysql 编辑:程序博客网 时间:2024/05/17 23:15

为了能够方便地了解事件拦截机制的整个流程,设计这样一个实例:

  1. MyViewGroupA——最外层的ViewGroup
  2. MyViewGroupB——中间的ViewGroup
  3. MyView——最底层的View

效果图如下:

这里写图片描述

代码只是重写了事件拦截和处理的几个方法,并给它们加上一些Log而已。

对于ViewGroup来说,重写了如下三个方法。

    /**     * 该方法虽然是事件分发的第一步,但一般情况下,我们不太会去改写这个方法     * @param ev     * @return     */    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        Log.d("xys", "ViewGroupA dispatchTouchEvent" + ev.getAction());        return super.dispatchTouchEvent(ev);    }    /**     * 事件拦截的核心方法     * @param ev     * @return     */    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        Log.d("xys", "ViewGroupA onInterceptTouchEvent" + ev.getAction());        return super.onInterceptTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d("xys", "ViewGroupA onTouchEvent" + event.getAction());        return super.onTouchEvent(event);    }

对于View来说,重写了如下两个方法。

    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d("xys", "View onTouchEvent" + event.getAction());        return super.onTouchEvent(event);    }    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        Log.d("xys", "View dispatchTouchEvent" + event.getAction());        return super.dispatchTouchEvent(event);    }

ViewGroup级别比较高,比View多了一个方法——onInterceptTouchEvent()方法。

(一)
我们先不修改任何返回值,运行程序后,点击一下MyView,Log日记记录如下:

05-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: View dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: View onTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onTouchEvent0

可以看见,正常情况下,事件的传递顺序是:
MyViewGroupA——>MyViewGroupB——>MyView。事件传递的时候,执行dispatchTouchEvent()方法,再执行onInterceptTouchEvent()方法。

事件的处理顺序是:
MyView——>MyViewGroupB——>MyViewGroupA。事件处理都是执行onTouchEvent()方法。

事件传递的返回值非常容易理解:true,拦截,不继续;false,不拦截,继续流程。

事件处理的返回值也类似:true,处理了;false, 给父ViewGroup处理。

初始情况下,返回值都是false。

(二)
如果我们让MyViewGroupA把事件拦截了,即让MyViewGroupA的onInterceptTouchEvent()方法返回true,Log日志如下:

05-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onTouchEvent0

MyViewGroupA把所有的事都干了,也就没有后面的人的事了。

(三)
再比如我们让MyViewGroupB把事件拦截了,即让MyViewGroupB的onInterceptTouchEvent()方法返回true,Log日志如下:

05-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onTouchEvent0

MyViewGroupB把事情干了,MyView就不用干活了。

(四)
在事件的处理中,最开始时MyView把事情干完了,需要向父布局报告,所以MyView的事件处理返回false,但若MyView的onTouchEvent()方法返回true,再看看Log日志:

05-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: View dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: View onTouchEvent0

看以看到,事件传递和以前一样,但是事件处理,到MyView这就结束了,因为MyView返回true,表示不用向父布局汇报了。

(五)
若MyViewGroupB的onTouchEvent()方法返回true,整个事件也就到此为止了,Log日志如下:

05-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupA onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onInterceptTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: View dispatchTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: View onTouchEvent005-15 19:15:24.730 31442-31442/com.imooc.viewlayout D/xys: ViewGroupB onTouchEvent0

代码地址

0 0