http://my.oschina.net/fuckboogie/blog/343131
http://blog.csdn.net/yanbober/article/details/45912661
http://www.th7.cn/Program/Android/201405/202993.shtml
深入理解android中的View.
http://www.incoding.org/admin/archives/179.html
http://www.2cto.com/kf/201407/313429.html
http://www.2cto.com/kf/201407/313429.html
http://www.2cto.com/kf/201211/171106.html
http://www.2cto.com/kf/201211/171106.html
http://www.2cto.com/kf/201211/171106.html
http://www.2cto.com/kf/201407/313429.html
http://blog.csdn.net/myarrow/article/details/14223493
http://blog.csdn.net/sunny2come/article/details/8899138
http://blog.csdn.net/yanbober/article/details/45932123
http://www.360doc.com/content/12/0823/21/7662927_231975556.shtml
http://blog.csdn.net/xipiaoyouzi/article/details/8098506
http://blog.csdn.net/chziroy/article/details/44401615
http://blog.csdn.net/mydreamongo/article/details/29812395
http://www.open-open.com/lib/view/open1434465083583.html
http://www.infoq.com/cn/articles/android-event-delivery-mechanism
magnet:?xt=urn:btih:f9e0079a2c1f2372529271b3667b0e8155143465
好,大家上一次我给大家分享了一下 android中的消息处理模型。
接下来我将继续把我对 android中的事件处理机制的理解 毫无保留的 分享给大家 。
希望大家能从我所分享的内容中学到一些东西。
好,我为什么想给大家分享 android中的事件处理模型,主要是这部分内容:
是我们自定义View过程中的核心知识点和难点。
深入理解了 android中的事件处理 模型 能够帮助我们 更好 的去 开发自定义控件,和去解决一些 莫名其妙的问题。
当然要想 开发 酷炫 的 自定义控件,只是理解 android中的事件处理 模型 是不够的。
因为自定义控件的开发 是一门 综合的知识点 ,它不仅需要我们理解 android中的事件处理 模型
它还需要我们掌握 android中的View 绘制 原理 和 各种数学函数 和 各种View动画 的使用 。
关于 View 绘制 原理 和 各种动画的使用 , 如果有时间的的 后边我会给大家一一的分享
今天主要是带大家学习一下 android中的 事件处理模型。
好,
讲android的事件处理 模型之前我们先明白以下几个概念 。
什么是触摸事件? 由用户触摸(Touch)手机屏幕 所触发的软件事件。
触摸事件发生的过程中会有好多的事件状态 :
ACTION_DOWN, //表示用户手指按下了屏幕。
ACTION_MOVE,//表示用户手指在屏幕上进行了移动。
ACTION_UP //表示用户手指离开了屏幕
ACTION_CANCEL //表示取消手势,不会由用户产生,而是由程序产生的
触摸事件你从何处来: 触摸事件如何进行分发?
一个触摸事件首先是在硬件层面触发,然后逐层传递到软件直至我们的app,前面的细节一般来说不用了解,我们讨论的事件入口从Activity开始。
当我们用手指触摸 屏幕的时候 ,
我们都知道 每一个界面都是一个activity, Activity的作用是用来展示相应的界面并且和用户进行交互。 Activity中所展示的内容 通常是各种各样的视图组件(View)或ViewGroup 。 我们大家都知道 ViewGroup和View 它们都是屏幕上的一个矩形区域并且负责界面绘制和处理事件,它们都是用来构建用户界面组件 的基类
它们的区别是 ? ViewGroup 继承自View,它可以是一组View的集合,它可以包涵 很多的子View和子VewGroup,
而View是界面展示区域的最小单位,它是不能包含子View的。
这些都是我们所知道的内容, 由此我们可以设想 android中的事件分发机制 是 由activity来开始分发的 , 在上一节我给大家讲android消息 分发的机制的时候给大家讲过当一个消息从MessageQueue中被取出后,会调用Message的成员变量handler的 dispatchMessage方法来分发这个消息,而当我们用手指去触摸屏幕的时候,是否也会有一个类似怎样的 dispatch 方法 来 分发我们的 Touch事件呢 ? 这个时候我们是不是得到actiivty中看一下有没有怎样的一个方法呀。 好,我们看一下,这个图是截取的activity源码当中的 方法
/**
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
*
* @param ev The touch screen event.
*
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
好,大家看一下这个方法的注释:
注释是说调用这个方法去处理触摸屏事件,在它分发到窗口之前,你可以去复写这个方法去拦截所有的触摸屏事件,
好,由此也给大家证明了android中的触摸事件的分发是以 activity中的 dispatchTouchEvent方法为入口函数的。
好,接下来我们就以这个方法去顺藤摸瓜就一下android中的触摸事件是怎样进行分发的。
大家可以看到,这个方法首先判断了 触摸事件是否为 按下事件,如果是的话,就会调用 onUserInteraction();方法。
紧接着调用了getWindow().superDispatchTouchEvent(ev)方法 ,如果这个方法返回true,就代表这个事件被
消费掉了, 好,那我们看一下getWindow方法中做了什么事件,好,这个方法返回了一个 Window mWindow
对象 ,这个对象在什么时候被创建出来的呢?我们看一下 , 是在activity的attach 方法中被创建出来的 ,那attach方法是在什么时候
被调用的呢? 在上一讲中我给大家提到过, activity生命周期的调度是通过activityThread来完成的,好 那我们接下来来看一下
activityThread中的方法,好,大家这个类当中有一个 performLaunchActivity 方法,
这个方法的作用 就是为应用程序进程中创建一个新的Activity实例 ,好那我们看一下这个方法当中 都做了什么事件,
这个方法首先 通过 ActivityClientRecord来得到当前要启动的ActivityInfo,ActivityInfo的作用是用来描述当前正在启动的Activity组件的,
然后调用 r.intent.getComponent(); 方法 从ActivityInfo中得到我们要启动的组件信息Component, ,然后调用 r.packageInfo.getClassLoader();方法来
得到 我们的类加载器 , 紧接着 调用 了 mInstrumentation.newActivity( cl, component.getClassName(), r.intent);方法 用反射的方式 来 创建我们的activity实例
,activity的实例创建出来之后 ,接着调用 了 activity.attach()方法 ,好,我们继承看一下 activity.attach()方法方法中都做了什么事情 。
这个方法中调用了 PolicyManager.makeNewWindow(this); 方法来为我们创建了一个 mWindow 的实例对象 。 由于 Window 中 一个接口,接着我们继续分析
一下它具体创建的是那一个实现类。 好,我们看一下 PolicyManager.makeNewWindow(this);方法内部 它调用了sPolicy.makeNewWindow(context);方法
sPolicy是什么,大家看一下这个类的静态方法块 , 在这个静态方法块是 它通过 调用 Class.forName 方法来得到我们要的这个类的字节码文件对象 ,
接着调用了 policyClass.newInstance(); 来实例这个 Policy 对象,然后又调用了 Policy身上的 makeNewWindow方法 ,好,我们继续看一下 Policy身上的
makeNewWindow方法都做了什么事情 ,好,大家可以看到这个方法直接 给我们返回了一个 PhoneWindow(context) 对象 。
由此我们就知道 了 activity中的getWindow()方法就是返回给我们一个 PhoneWindow对象 .
好,那我们继续看一下 PhoneWindow 对象的 superDispatchTouchEvent 方法中都做了什么事情 。
好,大家可以看到这个方法中 又调用了 mDecor.superDispatchTouchEvent(event) 方法, 那mDecor 是什么它又是在什么时候创建出来的呢?
我们来搜一下 ,我们可以看到 mDecor 是在 installDecor()方法 中被赋值的 ,好,那我们在来看一下 generateDecor() 方法内部做了什么事件 。
好,大家这个方法内部直接 给我们返回了一个 DecorView 对象 。 由此我们也就知道 mDecor.superDispatchTouchEvent(event) 就是调用了
DecorView身上的 superDispatchTouchEvent 方法 , 好,那我们继续看一下 superDispatchTouchEvent 方法中都做了什么事情 。
那,它调用了 super.dispatchKeyEvent(event) ,super关键字代表父类的意思,它调用了父类的 dispatchKeyEvent 方法,
那它的父类是谁呢,我们看一下 ,DecorView extends FrameLayout ,它的父类是 FrameLayout ,而 FrameLayout的父类又是 ViewGroup
所以它最终还是调用了 ViewGroup的 dispatchKeyEvent 。
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
当Activity中所有的视图View都不处理该事件的是就交给Activity的onTouchEvent方方来处理。
DecorView的分发事件代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Callback cb = getCallback();
return cb != null && mFeatureId < 0 ? cb.dispatchTouchEvent(ev) : super
.dispatchTouchEvent(ev);
}
1)ViewGroup永远不会对拦截,因为他的onInterceptTouchEvent(MotionEvent ev)始终返回的是false!这样DecorView对到来的事件MotionEvent就只有分发到子View并由子View进行拦截和处理此事件了.
这里所说的事件是指手指按下(down)、移动(move)、抬起(up)此为一个事件集合或者说是事件序列
android控件对事件处理的优先级:onTouch>onTouchEvent>onClick
这个View是所有视图的根视图,Activity界面中你能见到的各个View都是DecorView的子View。到此为止事件已经分发到View上面,View获取到事件后有两个选择:处理和不处理该事件,如果处理该事件那事件就不会继续向其子View分发下去;否则就继续分发下去交给子View对该事件做同样的判断,其实就是个递归的过程。
1 ,onTouch和onTouchEvent有什么区别
我们讨论的事件入口从Activity开始。
触摸事件你到何处去: 触摸事件如何进行响应?
触摸事件的传递顺序是:
Activity -> 当前活动窗口(PhoneWindow) -> 窗口的Top-Level View(DecorView) -> 各级ViewGroup (如各种Layout) -> ... -> 各级ViewGroup -> 叶子节点 View
而触摸事件的处理顺序则刚好相反:
叶子节点 View -> 各级ViewGroup -> ... -> 各级ViewGroup -> (Window和DecorView只有分发没有处理) -> Activity
当叶子节点View接受到事件之后,会试图做出处理,如果它处理了,则上面各层不再处理,如果它没有处理则往上由它的父ViewGroup处理,这样逐层向上按顺序试图处理,直到Activity。
- Android中事件传递按照从上到下进行层级传递,事件处理从Activity开始到ViewGroup再到View。
在View和ViewGroup中都存在dispatchTouchEvent和onTouchEvent方法,但是在ViewGroup中还有一个onInterceptTouchEvent方法,
MotionEvent继承于InputEvent,用于标记各种动作事件。
- dispatchTouchEvent方法用于事件的分发,Android中所有的事件都必须经过这个方法的分发,然后决定是自身消费当前事件还是继续往下分发给子控件处理。返回true表示不继续分发,事件没有被消费。返回false则继续往下分发,如果是ViewGroup则分发给onInterceptTouchEvent进行判断是否拦截该事件。
- onTouchEvent方法用于事件的处理,返回true表示消费处理当前事件,返回false则不处理,交给子控件进行继续分发。
- onInterceptTouchEvent是ViewGroup中才有的方法,View中没有,它的作用是负责事件的拦截,返回true的时候表示拦截当前事件,不继续往下分发,交给自身的onTouchEvent进行处理。返回false则不拦截,继续往下传。这是ViewGroup特有的方法,因为ViewGroup中可能还有子View,而在Android中View中是不能再包含子View的(iOS可以)。
http://www.infoq.com/cn/articles/android-event-delivery-mechanism
在android开发设计模式中,最广泛应用的就是监听、回调,进而形成了事件响应的过程。
ViewGroup?它和普通的View有什么区别?
1 ,onTouch和onTouchEvent有什么区别
ViewGroup 继承自View,它可以就是一组View的集合,它包涵 很多的子View和子VewGroup,
注册一个监听对象
实现监听对象的监听事件
当某一触发事件到来,在触发事件中通过注册过的监听对象,回调注册对象的响应事件,来完成用户自定义实现。
dispatchTouchEvent: 函数负责事件的分发
onTouchEvent: 函数负责执行事件的处理,负责处理事件,主要处理MotionEvent.ACTION_DOWN、
MotionEvent.ACTION_MOVE 、
MotionEvent.ACTION_UP这三个事件。
http://blog.csdn.net/androiddevelop/article/details/18898971
http://blog.csdn.net/androiddevelop/article/details/18898971
http://blog.csdn.net/androiddevelop/article/details/18898971
http://my.oschina.net/banxi/blog/56421
http://my.oschina.net/banxi/blog/56421
重要:
http://www.incoding.org/admin/archives/179.html
1 ,dispatchTouchEvent主要用来分发事件,函数主要作用是来决定当前的事件是交由自己消费处理,还是交由子控件处理。
2 ,onInterceptTouchEvent主要来决定当前控件是否需要拦截传递给子控件,如果返回True表示该控件拦截,并交由自己父类的dispatchTouchEvent处理消费,如果返回false表示不拦截,允许传递给子控件处理。
3,dispatchTransformedTouchEvent主要根据传来的子控件,决定是自身处理消费,还是交由子控件处理消费。
4 ,ViewGroup中 onInterceptTouchEvent 默认是返回false的。
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}