关于Android触摸事件分发的原理详析_第1页
关于Android触摸事件分发的原理详析_第2页
关于Android触摸事件分发的原理详析_第3页
关于Android触摸事件分发的原理详析_第4页
关于Android触摸事件分发的原理详析_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第关于Android触摸事件分发的原理详析目录一:前言二:说在前面的知识三:整体流程1:activity2:window就是PhoneWindow3:viewgroup4:view四:一些关键点五:从源码看触摸事件分发总结

一:前言

最近在学Android的触摸事件分发,我觉得网上说的太杂太乱,而且有很多博客都有明显的错误。什么自顶向下分发,自下向顶分发,什么拦截又一直消费什么什么之类,非常难懂。为了自己将来回顾可以更好的理解这块知识,也为了后来之人可以更好的学习,我写下这篇博客。

二:说在前面的知识

点击,滑动,松手都是由MotionEvent这个类来表示。屏幕上的一个事件序列是指以一个MotionEvent.action_down按下开始,以若干个MotionEvent.action_move移动事件在中间,再以一个MotionEvent.action_up作为结束的事件流。viewgroup是view的子类。viewgroup和view都有dispatchTouchEvent方法;viewgroup有onTnterceptTouchEvent和onTouchEvent方法,view只有onTouchEvent方法。

三:整体流程

1:activity

我们点击屏幕的所有事件,都会被第一个接收。

publicbooleandispatchTouchEvent(MotionEventev){

if(ev.getAction()==MotionEvent.ACTION_DOWN){

onUserInteraction();//是一个空方法,如果想知道按下了屏幕,可以重写这个方法打印日志

if(getWindow().superDispatchTouchEvent(ev)){//把这个事件传给window属性

returntrue;

returnonTouchEvent(ev);

}

2:window就是PhoneWindow

每一个activity都会对应一个PhoneWindow(在onCreate方法之前、activity内部的attach方法中创建)。PhoneWindow含有一个decorview属性(setContentView中创建),phonewindow把事件传给decorview。decorview继承于viewgroup。点击事件现在传到decorview这里,就开始viewgroup的事件分发逻辑了。

3:viewgroup

viewgroup收到点击事件,进入dispatchTouchEvent,如果满足以下二个条件中的任何一个条件:

事件为down事件有一个子view或子viewgroup在处理着事件流了

mFirstTouchTarget!=null

就进入判断,如果没有被禁用拦截(子view调用parent.requestDisallowed....)就执行,onInterceptTouchEvent代码。

如果决定拦截,后面还会把mFirstTouchTarget置为null,这样,之后就不会在调用onInterceptTouchEvent了。而且之后的事件流都会由这个viewgroup的dispatchTouchEvent处理

如果不决定拦截,就遍历子view、子viewgroup,挨个调用它们的dispatchTouchEvent。如果没有人接收,那就调用自己的super.dispatchTouchEvent.viewgroup的super.dispatchTouchEvent就是自己view那部分的dispatchTouchEvent。

4:view

在view这一层,对于down事件,返回true就表示消费这个down事件之后的序列。具体看图。

view调用setOnTouchLIstener可以设置OnTouchListener,重写onTouch方法。从源码中可以看出,若onTouch返回true,将不再回调onTouchEvent方法。不回调onTouchEvent的话,那onClickListener也不能回调了。

四:一些关键点

即使有view消费着一组事件,事件流由底向上传递时,依然会调用每一个viewgroup的intercept拦截方法判断是否拦截。当一个viewgroup遍历它所有的子view没有一个接收时,就会进入view模式,调用自己继承于view的那一个dispatchTouchEvent方法。如果自己不接收,那会交给调用自己的dispatchTouchEvent的那个父view.

事件流没有什么自上而下,就是自下而上的。

ViewGroup的实现负责将触摸事件沿着控件树向子控件进行派发,而View的实现则主要用于事件接收与处理工作。当viewgroup没有子view接收时,viewgroup作为一个view去处理。

五:从源码看触摸事件分发

由于专栏关注自定义控件,所以关于系统如何从硬件获取触摸事件以及传递到Activity的dispatchTouchEvent就不详细分解,下面将从Activity的dispatchTouchEvent方法来一步步看事件是如何被分发传递的:

Activity中的dispatchTouchEvent:

publicbooleandispatchTouchEvent(MotionEventev){

if(ev.getAction()==MotionEvent.ACTION_DOWN){

onUserInteraction();

if(getWindow().superDispatchTouchEvent(ev)){

returntrue;

returnonTouchEvent(ev);

}

其中onUserInteraction();是一个空实现,是系统留给我们的一个修改事件分发的一个方法,这里可以忽略。

所以实际上Activity的dispatchTouchEvent方法是调用的PhoneWindow的superDispatchTouchEvent方法,如果superDispatchTouchEvent返回false,没有消费掉事件,那么才会再交给activity的onTouchEvent方法去处理,从这个角度来讲,如果所有地方都没有消费掉事件,最后接收事件的会是Activity的onTouchEvent方法。

那么下面我们来看看PhoneWindow中的superDispatchTouchEvent方法:

@Override

publicbooleansuperDispatchTouchEvent(MotionEventevent){

returnmDecor.superDispatchTouchEvent(event);

}

发现实际上调用的是DecorView对象mDecor的superDispatchTouchEvent方法,来看看DecorView的superDispatchTouchEvent方法:

publicbooleansuperDispatchTouchEvent(MotionEventevent){

returnsuper.dispatchTouchEvent(event);

}

调用的super.dispatchTouchEvent,而再来看看这个DecorView的继承关系:

privatefinalclassDecorViewextendsFrameLayoutimplementsRootViewSurfaceTaker

所以调用的是FrameLayout中的dispatchTouchEvent方法,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论