您的位置:首页 > 移动开发 > Android开发

一张图让你了解安卓事件处理流程的走向

2015-12-02 11:57 676 查看
转载请标明出处:http://blog.csdn.net/qq1940879801/article/details/50136965

最近小明遇到问题老是问我,其中有一个问题是这样的:

小明:在ScrollView嵌套ListView,ListView无发滑动

一看就知道他不懂安卓事件处理机制,然后我耐心帮他讲解,最后虽然他懂了,但是我还是觉得有必要总结下安卓事件处理机制。

一.什么是事件

事件就是对触摸屏幕的操作,比如触摸事件,单机事件,滑动事件等。

用户对触摸屏幕的所有操作,都是先按下去,最后弹起来,按下去的时候可以进行一段移动,再弹起来,也就是说说有基本事件都包括这三种事件状态:

按下(ACTION_DOWM)

移动(ACTION_MOVE)

弹起(ACTION_UP)

安卓为响应这些事件,提供一个类MotionEvent,其中有这样一句话:

Motion events are always delivered to views as a consistent stream of events. What constitutes a consistent stream varies depending on the type of device. For touch events, consistency implies that pointers go down one at a time, move around as a group and
then go up one at a time or are canceled.

翻译:请求事件总是依照一个始终如一的事件流传递给视图。什么是一个始终如一的流变化取决于设备的类型。对触摸事件,一致性意味着指针走一次,作为一个整体移动,然后向上一次或被取消。

也就是说事件从点击的子视图(View)开始,向上传递事件给父视图(ViewGroup),一直传递到传递到Activity。

而安卓的事件处理流程则是由Activity的dispatchTouchEvent,再到ViewGroup的dispatchTouchEvent,再到Viewgroup的onInterceptTouchEvent,一直传递到点击的子视图View

二.view的事件分发以及viewgroup的事件分发和拦截

通过查看view的源码,发现view只有dispatchTouchEvent,OnTouchEvent

通过查看Viewgroup的源码,发现viewgroup不仅有dispatchTouchEvent,OnTouchEvent,还有onInterceptTouchEvent

dispatchTouchEvent:方法用于事件的分发,Android中的所有事件都必须经过此方法的分发,然后决定是自身消费当前事件还是继续向下分发给 视图处理。返回true表示不在继续分发,事件被消费了。返回false则事件继续分发,如果是viewgroup则分发给onInterceptTouchEvent进行判断是否拦截

OnTouchEvent:方法用于事件的处理,返回true表示消费处理当前事件,返回false则不处理,交给子控件进行继续分发。

onInterceptTouchEvent:是ViewGroup中才有的方法,View中没有,它的作用是负责事件的拦截,返回true的时候表示拦截当前事件,不继续往下分发,交给自身的onTouchEvent进行处理。返回false则不拦截,继续往下传。这是ViewGroup特有的方法,因为ViewGroup中可能还有子View,而在Android中View中是不能再包含子View的

三.从一个案例让你了解事件执行流程

案例1:view的事件分发

1.自定义类JesseButton继承Button

2.重写dispatchTouchEvent和onTouchEvent方法

res/layout/activity_main.xml文件如下

输出结果:



温馨提示:这里鼠标要稍微滑动下,才能响应事件的移动状态(即才会有ACTION_MOVE)

由此可以看出,View事件执行流程是:

(Activity)dispatchTouchEvent-->(Button)dispatchTouchEvent-->(Button)onTouch-->(Button)onTouchEvent

案例2:viewgroup的事件分发和事件拦截

在原来基础上新增一个类JesseLinearLayout

res/layout/activity_main.xml文件改为如下

运行结果:



由此可以看出,Viewgroup事件执行流程是:

(Activity)dispatchTouchEvent-->(LinearLayout)diapatchTouchEvent-->(LinearLayout)onInterceptTouchEvent-->(Button)dispatchTouchEvent-->(Button)onTouch-->(Button)onTouchEvent

四.一张图让你了解事件处理流程的走向



默认执行流程是

(Activity)dispatchTouchEvent(ACTION_DOWM返回false)-->(LinearLayout)diapatchTouchEvent(ACTION_DOWM返回false)-->(LinearLayout)onInterceptTouchEvent(ACTION_DOWM返回false)-->(Button)dispatchTouchEvent(返回false)-->(Button)onTouch(返回false)-->(Button)onTouchEvent

假如在(LinearLayout)diapatchTouchEvent的ACTION_DOWM返回true,三种状态执行的事件是:

ACTION_DOWM状态执行的事件是:(Activity)dispatchTouchEvent(ACTION_DOWM返回false)-->(LinearLayout)diapatchTouchEvent(ACTION_DOWM返回false)

ACTION_MOVE状态执行的事件是:(Activity)dispatchTouchEvent(ACTION_MOVE返回false)-->(LinearLayout)diapatchTouchEvent(ACTION_MOVE返回false)-->(LinearLayout)onInterceptTouchEvent

ACTION_UP状态执行的事件是:(Activity)dispatchTouchEvent(ACTION_UP返回false)-->(LinearLayout)diapatchTouchEvent(ACTION_UP返回false)-->(LinearLayout)onInterceptTouchEvent

如果我们不想ACTION_UP状态的(LinearLayout)onInterceptTouchEvent执行,只需要(LinearLayout)diapatchTouchEvent(ACTION_UP返回true)即:

ACTION_UP状态执行的事件是:(Activity)dispatchTouchEvent(ACTION_UP返回false)-->(LinearLayout)diapatchTouchEvent(ACTION_UP返回true)

五.解释和总结:

继续重复-----事件包括最基本的三种状态:按下(ACTION_DOWM),移动(ACTION_MOVE),弹起(ACTION_UP)

1.我们单击view,这时候事件由view通过MotionEvent向上传递事件,先传递给ViewGroup再通过MotionEvent向上传递事件,直到Activity

2.事件默认处理流程则相反,由Activity的dispatchTouchEvent向下传递事件,先传递给ViewGroup的dispatchTouchEvent,再传递给ViewGroup的onInterceptTouchEvent,最后传递到View的dispatchTouchEvent

3.由dispatchTouchEvent和onInterceptTouchEvent的ACTION_DOWM决定该事件流程的走向(由dispatchTouchEvent决定是否分发给onInterceptTouchEvent,再通过onInterceptTouchEvent决定是否拦截)。这里只是决定事件的一个流程走向,至于某种状态(三种状态的一种)按照这个流程走向是否执行完所有流程,请看下面一条。

4.如果事件处理方法返回true,表示该状态(三种状态的一种)下的事件已经被消化了,该状态下的事件不再传递,但是并不影响其他状态(三种状态的一种)的事件处理。否则会继续向下传递事件

欢迎指出不足,没事下留言,你的支持,是我写下去的动力
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息