您的位置:首页 > 运维架构 > 网站架构

Android视图架构及事件分发处理机制

2016-07-26 00:12 411 查看
转载请标明出处:

http://blog.csdn.net/reakingf/article/details/52029575

本文出自:方耿佳的博客

1、视图View结构

在Android系统中,视图的结构是一种树形结构,父级View一般是个ViewGroup,而子View可以使ViewgGroup也可以是简单的View,这种树形结构称为View树或控件树。每一颗控件树的顶部都有一个ViewParent对象,且都以深度优先遍历来查找子View元素,下面给个例子表示下View树。



2、UI界面结构

我们都知道在Android中与用户进行互动的UI界面通常对应一个Activity,但是这个UI界面的结构是怎样的呢?让我们一起来看看。

每个Activity都会有一个Window对象,一般是PhoneWindow,而PhoneWindow下就是视图结构啦,最顶层的View称为root view,一般是一个DecorView,其中包含两个子结构:TitleView和ContentView。我们平时在
onCreate()
中调用的
setContentView()
就是设置activity的contentView,具体结构图如下。



当我们在
onCreate()
中调用
setContentView()
方法后,ActivityManagerService会回调
onResume()
方法,此时系统才会把整个DecorView添加到PhoneWindow中,并显示出来。

3、事件分发机制

Android中的事件分发机制主要由Touch事件触发,处理对象是ViewGroup和View。任何Touch事件都是以MotionEvent.ACTION_DOWN开始,以ACTION_UP或CANCEL结束,中间可能会有一个或多个ACTION_MOVE。其中,在Android的事件处理机制中,主要涉及3个方法:

dispatchTouchEvent
:负责事件分发的方法,该方法会调用
onTouch()
onTouchEvent()
(见下文)两个方法,但是
onTouch()
优先于
onTouchEvent()
,所以如果
onTouch()
返回ture则相当于该事件被
onTouch
消费了,不再执行
onTouchEvent()
,其中
onClick()
方法的执行就是在
onTouchEvent()
调用的。不过
onTouch()
要执行,必须满足两个条件,即mOnTouchListener的值不能为空(一般我们在
setOnTouchListener()
中对其进行赋值),和当前点击的控件必须是enable 的。

onInterceptTouchEvent
:负责事件拦截的方法,只存在于ViewGroup中,普通View中没有该方法。用于拦截向下分发的事件,若返回值为true则拦截,false则不拦截,继续向下分发。

onTouchEvent
:负责事件处理的方法,若返回值为false,则处理完事件后会将事件继续向上级传递,上级视图对该事件继续进行处理,即执行上级视图的onTouchEvent方法,若所有视图都不处理该事件,则最终该事件将传递给Activity处理;若为返回值true,则不再向上级视图传递;

具体逻辑是:当一个Touch Event发生时,都是从当前Acitivity开始,即Activity –> Window –> View ,顶级View接收到事件后,按照事件分发机制向下逐级分发事件。所以也可以直接当成由ViewGroup处理,即由最顶级的DecorView开始处理,DecorView获得事件后便开始向下级进行事件分发,然后获得事件的子级ViewGroup判断是否要拦截此事件,若要拦截,则该事件序列由该级视图处理,不再向下传递;若不拦截则继续往下分发,直到到达最底层,此时的最底层View执行onTouchEvent并判断是否向上级反映处理情况,若返回值为false,则可以理解为当前View没能处理好该事件,所以将继续向上级传递,由上级View继续调用onTouchEvent进行处理,该事件的后续事件(如ACTION_MOVE)也是这样传递的。即上面3个方法的执行顺序是:
dispatchTouchEvent
–>
onInterceptTouchEvent
–>
onTouchEvent




Tips:

若ViewGroup拦截最初的ACTION_DOWN,则该事件将传给该ViewGroup的
onTouchEvent
方法处理;

若ViewGroup拦截了一个中间事件,如ACTION_MOVE,则该事件将被系统处理为CANCEL事件,并传递给其子View,但不传递给自己的
onTouchEvent
,但在该事件后面的事件将只传递给该ViewGroup的
onTouchEvent
方法处理。即某个View决定拦截某个事件后,就默认它要拦截该事件序列,所以该事件序列内的所有事件都直接交给它处理,且不需再调用onInterceptEvent方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 事件分发