题外话:
/** * A ViewGroup is a special view that can contain other views * (called children.) The view group is the base class for layouts and views * containers. This class also defines the * android.view.ViewGroup.LayoutParams class which serves as the base * class for layouts parameters.
一个ViewGroup是一个可以包含其他view的特别的View(是View的子类),ViewGroup是各个Layout和View组件的基类,这个类还定义了LayoutParams类来指定这个基类的布局参数。
正题:
之所以先了解一下ViewGroup,是因为ViewGroup是了解一个界面组织的基本元素,只有知道这个元素,我们才好描述Touch事件的分发。关于Touch事件的分发,很多人都做过研究,比如Android中OnTouch事件的研究:
在触发OnTouch事件的时候Android的GroupView会调用如下三个函数:
1 public boolean dispatchTouchEvent(MotionEvent ev) 用于事件的分发 2 public boolean onInterceptTouchEvent(MotionEvent ev) 用于事件的拦截 3 public boolean onTouchEvent(MotionEvent ev) 处理事件
当然我们可以在容器类中如继承自LinearLayout的类中重写这三个方法。而继承View类的子类只能重写dispatch和onTouchEvent两个方法。当点击后这三个方法相继执行。
自己写了一个TextView子类MyTextView和LinearLayout子类MyLinearLayout,TextView包含在LinearLayout中。
当点击MyTextView时,程序会先进入到LinearLayout的dispatchTouchEvent中,这个类必须调用super.dispatchTouchEvent(ev); 否在后面的两个方法无法触发,所以傻蛋发现这个方法根本没有必要重写,因为框架是在super.dispatchTouchEvent(ev);中来调用onInterceptTouchEvent和onTouchEvent方法的,所以手动的设置dispatchTouchEvent的返回值是无效的,除非你不想让框架触发这两个方法。
当执行完dispathTouchEvent后会执行onInterception方法,如果返回为true,这表示MyLinearLayout把这个Touch事件拦截了,就会执行自己的OnTouch方法。如果为false则表示不拦截,此事件会分发到把事件传递给它的子控件MyTextView中。
当事件传递到MyTextView后,会执行dispatchTouchEvent,然后会执行onTouchEvent。当在MyTextView中的onTouchEvent返回为false的话,当执行完onTouchEvent中的事件后,事件会再分发给MyLinearLaytout,执行LinearLayout的onTouchEvent。
博客作者(傻蛋?)使用一个LinearLayout和一个TextView来做实验,我们可以得出如下的结论:
1)事件的初始触发者是父组件(LinearLayout),父组件有权决定是分发这个事件还是拦截这个事件;
2)如果父组件分发这个事件,则子控件会收到这个事件,子控件调用onTouchEvent方法处理事件,如果onTouchEvent返回的是false,则事件还会交给父组件处理。
总结论是:
Android的触摸事件分发是从最上层的Activity开始的,然后dispatch到子View,当分发到触发事件的View时,再逐层往回调用onTouchEvent函数,下面是实例代码。
更明白一点:
Android 消息队列的分发流程是:Activity -> ViewGroup1 -> ViewGroup1的直接子ViewGroup –> ×××××× -> 叶子View
消息处理流程,从子到父,如果消息处理一直返回的是 false。则一直是从子到父的依次处理。处理到没有可以处理的人了,或者返回了true到此为止。
(还需要继续,自己实验,自己研究源码)