View,ViewGroup的Touch事件的分发机制



 

Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制

标签: AndroidViewviewGroupdispatchTouchEventonTouchEvent
  45976人阅读  评论(69)  收藏  举报
  分类:

转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/21696315),请尊重他人的辛勤劳动成果,谢谢!

今天这篇文章主要分析的是Android的事件分发机制,采用例子加源码的方式让大家深刻的理解Android事件分发的具体情况,虽然网上很多Android的事件分发的文章,有些还写的不错,但是我还是决定写这篇文章,用我自己的思维方式来帮助大家理解Android事件分发,Android事件分发到底有多重要呢?相信很多Android开发者都明白吧,这个我就不介绍了,我也写了很多篇文章里面涉及到Android的事件处理的问题,可能不理解Android事件分发的朋友会有点难理解吧,不过没关系,相信看了这篇文章的你会对Android事件分发有进一步的理解。我这篇文章分析的源码是Android 2.2的源码, 也许你会说,干嘛不去分析最新的源码呢?我这里要解释一下,Android 2.2的源码跟最新的源码在功能效果方面是一样的,只不过最新的源码相对于Android 2.2来说更加健壮一些, Android 2.2的事件处理的代码几乎都写在一个方法体里面,而最新的源码分了很多个方法写,如果用最新的源码调用方法会绕来绕去的,相信你看的也会晕,出于这个考虑,我就拿Android 2.2的源码来给大家分析。


ViewGroup的事件分发机制

我们用手指去触摸Android手机屏幕,就会产生一个触摸事件,但是这个触摸事件在底层是怎么分发的呢?这个我还真不知道,这里涉及到操作硬件(手机屏幕)方面的知识,也就是Linux内核方面的知识,我也没有了解过这方面的东西,所以我们可能就往上层来分析分析,我们知道Android中负责与用户交互,与用户操作紧密相关的四大组件之一是Activity, 所以我们有理由相信Activity中存在分发事件的方法,这个方法就是dispatchTouchEvent(),我们先看其源码吧

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public boolean dispatchTouchEvent(MotionEvent ev) {  
  2.   
  3.         //如果是按下状态就调用onUserInteraction()方法,onUserInteraction()方法  
  4.         //是个空的方法, 我们直接跳过这里看下面的实现  
  5.         if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
  6.             onUserInteraction();  
  7.         }  
  8.           
  9.         if (getWindow().superDispatchTouchEvent(ev)) {  
  10.             return true;  
  11.         }  
  12.           
  13.         //getWindow().superDispatchTouchEvent(ev)返回false,这个事件就交给Activity  
  14.         //来处理, Activity的onTouchEvent()方法直接返回了false  
  15.         return onTouchEvent(ev);  
  16.     }  
这个方法中我们还是比较关心getWindow()的superDispatchTouchEvent()方法,getWindow()返回当前Activity的顶层窗口Window对象,我们直接看Window API的superDispatchTouchEvent()方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * Used by custom windows, such as Dialog, to pass the touch screen event 
  3.      * further down the view hierarchy. Application developers should 
  4.      * not need to implement or call this. 
  5.      * 
  6.      */  
  7.     public abstract boolean superDispatchTouchEvent(MotionEvent event);  
这个是个抽象方法,所以我们直接找到其子类来看看superDispatchTouchEvent()方法的具体逻辑实现,Window的唯一子类是PhoneWindow,我们就看看PhoneWindow的superDispatchTouchEvent()方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public boolean superDispatchTouchEvent(KeyEvent event) {  
  2.         return mDecor.superDispatcTouchEvent(event);  
  3.     }  
里面直接调用DecorView类的superDispatchTouchEvent()方法,或许很多人不了解DecorView这个类,DecorView是PhoneWindow的一个final的内部类并且继承FrameLayout的,也是Window界面的最顶层的View对象,这是什么意思呢?别着急,我们接着往下看


我们先新建一个项目,取名AndroidTouchEvent,然后直接用模拟器运行项目, MainActivity的布局文件为

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context=".MainActivity" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_centerHorizontal="true"  
  11.         android:layout_centerVertical="true"  
  12.         android:text="@string/hello_world" />  
  13.   
  14. </RelativeLayout>  
利用hierarchyviewer工具来查看下MainActivity的View的层次结构,如下图





我们看到最顶层就是PhoneWindow$DecorView,接着DecorView下面有一个LinearLayout, LinearLayout下面有两个FrameLayout

上面那个FrameLayout是用来显示标题栏的,这个Demo中是一个TextView,当然我们还可以定制我们的标题栏,利用getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.XXX); xxx就是我们自定义标题栏的布局XML文件
下面的FrameLayout是用来装载ContentView的,也就是我们在Activity中利用setContentView()方法设置的View,现在我们知道了,原来我们利用setContentView()设置Activity的View的外面还嵌套了这么多的东西

我们来理清下思路,Activity的最顶层窗体是PhoneWindow,而PhoneWindow的最顶层View是DecorView,接下来我们就看DecorView类的superDispatchTouchEvent()方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public boolean superDispatchTouchEvent(MotionEvent event) {  
  2.             return super.dispatchTouchEvent(event);  
  3.         }  
在里面调用了父类FrameLayout的dispatchTouchEvent()方法,而FrameLayout中并没有dispatchTouchEvent()方法,所以我们直接看ViewGroup的dispatchTouchEvent()方法
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.     * {@inheritDoc} 
  3.     */  
  4.    @Override  
  5.    public boolean dispatchTouchEvent(MotionEvent ev) {  
  6.        final int action = ev.getAction();  
  7.        final float xf = ev.getX();  
  8.        final float yf = ev.getY();  
  9.        final float scrolledXFloat = xf + mScrollX;  
  10.        final float scrolledYFloat = yf + mScrollY;  
  11.        final Rect frame = mTempRect;  
  12.   
  13.        //这个值默认是false, 然后我们可以通过requestDisallowInterceptTouchEvent(boolean disallowIntercept)方法  
  14.        //来改变disallowIntercept的值  
  15.        boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;  
  16.   
  17.        //这里是ACTION_DOWN的处理逻辑  <li style="border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; background-color: rgb(248,%2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随与博主沟通,第一间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值