`
gjhappyyy
  • 浏览: 259547 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

android事件拦截处理机制详解

 
阅读更多

【转:http://blog.csdn.net/chunqiuwei/article/details/41084921】

前段时间刚接触过android手机开发,对它的事件传播机制不是很了解,虽然网上也查了相关的资料,但是总觉得理解模模糊糊,似是而非,于是自己就写个小demo测试了一下。总算搞明白了它的具体机制。写下自己的结论,分享之,希望对初学android的人有所帮助

布局效果如图所示:

                      图1

 

参照上图先说说具体得到的结论:

1) onInterceptTouchEvent负责对touch事件进行拦截,对于嵌套的view最先执行的是事件拦截方法的是最外层的那个viewonInterceptTouchEvent方法,然后依次执行子视图的onInterceptTouchEvent,然后在执行子视图的子视图的事件拦截方法(当然在这里假设所有嵌套视图的onInterceptTouchEvent都会得到执行,让每个视图的onInterceptTouchEvent返回false即可)。参照上图,所以onInterceptTouchEvent执行顺序就是A--->B--->C--->D.也就是由父视图到子视图传递。总之,事件拦截机制是由父视图开始发起对事件的拦截(出事了老子先上,儿子稍后)。参照上图当手指触摸事件时,父视图A首先发起对该起事件的拦截,如果A拦截失败,就交给它的子视图B进行拦截;如果B拦截失败就交给B的子视图C再进行拦截..直到某一子视图对该次事件拦截成功。

2)某一视图拦截事件成功与否的判断标识是onInterceptTouchEvent方法的返回值,当返回true的时候说明拦截成功,返回false的时候说明当前视图对事件拦截失败。

3)下面说说拦截成功的情况,假设C视图对当前touch事件拦截成功。拦截成功意味着此次事件不会再传递到D视图了。所以此时的D视图的onInterceptTouchEvent就得不到运行(事件没法到达了,还拦截谁呢?)事件拦截成功后,紧接着就会对事件进行处理,处理的方法教给onTouchEvent方法处理。此时C视图拦截成功,那么紧接着就会执行C视图的onTouchEvent方法这是不是就意味着当前touch事件是由C视图的onTouchEvent方法来处理的呢?这要由C视图的onTouchEvent方法的返回值来决定C视图的onTouchEvent返回true的时候,当前事件就由C全权处理,处理的当然是事件的各种action,什么MotionEvent.ACTION_MOVE,ACTION_UP都交给了ConTouchEvent方法进行处理。所以此时就可以在ConTouchEvent方法中进行switch(event.getAction)判断执行相关逻辑了。如果返回的false,说明C视图对此事件不做处理或者处理不了,怎么办呢?儿子不行老爸来,于是事件就交到了B视图的onTouchEvent方法中。同样B对此事件处理与否还是看BonTouchEvent返回值,具体的解释就跟C一样了,不复多言。

4)A B C DonInterceptTouchEventonTouchEvent都返回false的情况下,方法执行的顺序依次为A.onInterceptTouchEvent-->B.onInterceptTouchEvent-->C.onInterceptTouchEvent-->D.touchEvent(最深的子视图没重写onInterceptTouchEvent)-->C.touchEvent-->B.touchEvent-->A.touchEvent.也就是说拦截事件是父视图优先有子视图进行拦截,处理事件是子视图优先父视图进行处理。

 总结:onInterceptTouchEvent负责对事件进行拦截,拦截成功后交给最先遇到onTouchEvent返回true的那个view进行处理

下面将要详细讲解上面结论是怎么得出的,准备分两部分进行一步步讲解。如果上面说的看明白的话,下面的内容就不要看了,因为会很啰嗦

图1的布局代码如下所示:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. <com.example.demo.AView 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.   
  6.     <com.example.demo.BView  
  7.         android:layout_width="match_parent"  
  8.         android:layout_height="match_parent" >  
  9.   
  10.         <com.example.demo.CView  
  11.             android:layout_width="match_parent"  
  12.             android:layout_height="match_parent" >  
  13.   
  14.             <com.example.demo.DView  
  15.                 android:layout_width="match_parent"  
  16.                 android:layout_height="match_parent"  
  17.                 android:text="测试demo" />  
  18.         </com.example.demo.CView>  
  19.     </com.example.demo.BView>  
  20.   
  21. </com.example.demo.AView>  

 

 

其中最后一个D是一个自定义的TextView,与A B C三个View的区别就是D只重写了onTouchEvent方法,A B C 这三个自定义控件还重写了onInterceptEvent方法。

D的代码如下,A B C代码基本上除了类名和输出log不一样外其余的都一样,所以为了减少这里只贴出其中的一个。

DView的代码:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class DView extends TextView{  
  2.     private static String tag = "D";  
  3.     public DView(Context context, AttributeSet attrs, int defStyle) {  
  4.         super(context, attrs, defStyle);  
  5.     }  
  6.   
  7.     public DView(Context context, AttributeSet attrs) {  
  8.         super(context, attrs);  
  9.     }  
  10.   
  11.     public DView(Context context) {  
  12.         super(context);  
  13.     }  
  14.     
  15.     @Override  
  16.     public boolean onTouchEvent(MotionEvent event) {  
  17.         Log.e(tag, "--onTouchEvent--D");      
  18.         return false;  
  19.     }  
  20. }  


AView的代码和C D的整体差不多,就贴出来一个:

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public class AView extends RelativeLayout{  
  2.     private static String tag = "A";  
  3.     public AView(Context context) {  
  4.         super(context);  
  5.     }  
  6.   
  7.     public AView(Context context, AttributeSet attrs, int defStyle) {  
  8.         super(context, attrs, defStyle);  
  9.     }  
  10.   
  11.     public AView(Context context, AttributeSet attrs) {  
  12.         super(context, attrs);  
  13.     }  
  14.        
  15.     @Override  
  16.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  17.         Log.e(tag,"--onInterceptTouchEvent--A");  
  18.         return false;  
  19.     }  
  20.       
  21.     @Override  
  22.     public boolean onTouchEvent(MotionEvent event) {  
  23.         Log.e(tag,"--onTouchEvent---A" );  
  24.         return false;  
  25.     }  
  26. }  

 

 

刚开始的时候重写的方法全部返回false运行点击的效果输出log为:

转换成效果图为:


 

 

从此图可以看出,onInterceptTouchEvent事件的执行顺序是由父控件到子控件,并且优先于自己控件的onTouchEvent方法执行,onTouchEvent事件执行的顺序正好相反由子控件到父控件。注意由于此时都返回了false,是没有哪一个view来处理此次的touch事件的各个ACTION的,这也是为什么onTouchEvent为什么会一直传递到A的原因。所以ACTION_MOVE和ACTION_UP等事件得不到相应(处理),此种情况下即使你在D的onTouchEvent方法里面写了如下代码,也不会得到执行。

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. if(event.getAction()==MotionEvent.ACTION_MOVE){  
  2.             Log.e(tag, "--onTouchEvent--*****");  
  3.         }  

 

1)如果A的InterceptTouchEvent返回了true,其余的仍然返回false,那么执行输出的log为:

 

 

转换成效果图为:

 

 

可以发现此时A拦截了此次Touch事件,事件不再向A的子控件B C D传递。此时所有的action事件比如手指移动事件ACTION_MOVE或者ACTION_UP事件啦等等事件都交给A的onTouchEvent方法去处理(当然这是在onTouchEvent方法返回true的情况下,如果返回false经过测试时不会相应这些action的)。B,C ,D控件是的事件处理拦截方法和事件处理方法是无法得到执行的。

 

2)只有B的onIntercepteTouchEvent事件返回了true的情况下,打印的log为

 

转换成效果图为:

 

此时由B拦截了此次Touch事件,并不会向C D子控件传递;同样的由于onTouchEvent事件返回为false,所以此次事件的event.getAction()的各种action都不会得到处理。

 

4)同理可知,C控件的onIntercept方法返回了true的情况下,其余的仍然返回false的情况下,输出log为

 

转换成效果图为

下面说说各个view的onTouchEvent返回true的情况

由于onTouchEvent事件是从子控件到父控件传递的,当D的onTouchEvent返回true的时候,经测试输出效果如下

转换成效果图为:

经过测试发现,此时D处理了此次Touch事件的各种action,C B D是的onTouchEvent的没有得到执行。

同理当C的onTouchEvent方法返回了true的时候,输出的log如下

转换成效果图如下:

经过测试发现,此时事件的各个action都在CView的onTouchEvent方法得到了响应,而D的onTouchEvent是不会相应MotionEvent.ACTION_XX的。其余情况一次类推,就不在啰嗦了。经过一步步的测试得出了文章开头的结文章有点啰嗦,希望可以对阅读此文的人有所帮助。

分享到:
评论

相关推荐

    Android事件处理机制详解及源码

    Android事件处理机制是Android应用程序开发中的关键组成部分,它使得用户与应用之间能够进行有效的交互。在Android系统中,事件处理主要包括触摸事件、键盘事件、广播事件等,这些事件的处理方式直接影响到应用的...

    Android控件架构与自定义控件详解(四)——事件拦截机制分析

    事件拦截机制是Android UI框架中的一个重要组成部分,它允许我们精确地控制事件的传递流程,从而实现复杂的用户交互逻辑。本篇文章将深入探讨Android控件架构,特别是事件拦截机制,并通过`onTouchEvent`方法进行...

    Android事件的分发机制详解

    Android事件的分发机制是Android UI交互中的核心概念,它决定了用户对屏幕上的控件进行触摸操作时,事件如何从顶级视图逐级传递到具体的处理者。在深入讲解之前,我们先理解两个基本概念:View和ViewGroup。View是...

    Android事件分发机制的详解

    同时,机制的复杂性也可能会导致事件处理的混乱和错误。 Android事件分发机制是Android系统中非常重要的机制之一,它直接关系到应用程序的用户体验。理解和掌握Android事件分发机制,可以让开发者更好地设计和实现...

    Android事件处理机制ViewGroup的事件传递

    Android事件处理机制主要涉及三类对象:事件(Event)、事件源(Event Source)和事件监听器(EventListener)。在本主题中,我们将深入探讨`ViewGroup`的事件传递,即事件分发过程。 1. **事件模型** Android事件...

    android事件分发机制

    ### Android事件分发机制详解 #### 一、触摸事件涉及的核心类 在Android系统中,触摸事件主要由两类核心对象负责处理:`ViewGroup` 和 `View`。 1. **ViewGroup**:作为容器,继承自 `View`,用于容纳多个 `View`...

    Android 事件分发机制视频讲解

    在Android开发中,事件处理是用户界面交互设计的核心组成部分。对于开发者来说,理解事件如何被分发到各个控件中至关重要,因为这直接影响到应用的用户体验。本文将从源码层面深入探讨Android中的事件分发机制,并...

    Android广播机制详解

    本文将详细解析Android广播机制的核心概念、工作原理以及如何使用。 一、广播基本概念 1. 广播Intent:广播Intent是Android系统中用于发送和接收广播消息的对象。它包含一个动作(Action)、数据(Data)、类型...

    Android触摸事件的应用详解

    Android 系统中触摸事件的传递机制是指当用户执行触摸动作时,系统如何将事件传递给相应的 View 组件。 Android 触摸事件的应用详解可以解决什么样的问题?在实际开发中,我们经常会遇到滑动冲突的问题,例如在 ...

    详解Android事件的分发、拦截和执行

    这个时候我们就需要了解Android的事件分发机制。 Android的触摸事件分发过程由三个很重要的方法来共同完成:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent。我先将这三个方法大体的介绍一下。  •...

    Android View 事件分发机制详解

    Android View 事件分发机制是Android用户界面交互的基础,它决定了触摸事件如何在视图层次结构中传递和处理。在Android开发中,理解和掌握这一机制至关重要,因为它涉及到UI的响应性和用户体验。 首先,事件分发...

    Android View事件分发机制详解

    PhoneWindow的superDispatchTouchEvent()方法是一个抽象方法,实际的事件处理在PhoneWindow的实现中完成。如果这个方法返回true,表示事件已经被处理,事件分发链路结束;如果返回false,事件将回溯到Activity的...

    Android 滑动监听的实例详解

    这一机制对于我们实现复杂的触摸事件处理逻辑非常重要。它意味着我们可以根据需要在不同的组件层级上处理触摸事件,从而实现丰富多变的用户交互体验。 需要注意的是,在开发中,由于触摸事件处理不当可能会导致多个...

    reactnative触摸事件机制详解及高仿微信通讯录功能

    2. **事件传递与阻塞**:在React Native中,事件处理分为两个阶段:`bubbling`(冒泡)和`capture`(捕获)。默认情况下,事件首先在最深的子组件(冒泡阶段)触发,然后逐级向上,最后到达根节点。如果在捕获阶段...

    Android事件传递

    ### Android事件传递详解 #### 一、概览 在Android应用程序开发过程中,触摸事件的处理是一项重要的技术。本文档基于观看Google官方视频的...希望本文档能帮助开发者更好地理解和应用Android触摸事件处理的相关知识。

Global site tag (gtag.js) - Google Analytics