阅读更多

         本文只讨论由触摸触发的事件,暂不讨论轨迹球等事件。

         以前写 android ,对事件的处理没有太深入,只是简单的 onTouchEvent 、setOnTouchListener就 ok 了,现在写的 UI ,很多自定义组件,父 view 和子view 都需要接收事件,然后处理,这就要求对事件传递机制有一定的了解。

         Android的事件:onClick, onScroll, onFling等等,都是由许多个Touch组成的。其中Touch的第一个状态肯定是 ACTION_DOWN, 表示按下了屏幕, ACTION_MOVE 表示为移动手势 ACTION_UP  表示为离开屏幕 ,本文就着中讨论这三种事件的传递。

         在Android中,有一类控件是中还可以包含其他的子控件,这类控件是继承于ViewGroup类,例如:LinearLayout, RelativeLayout。还有一类控件是不能再包含子控件,例如:TextView,Button。

         本文以LinearLayout中嵌套LinearLayout,LinearLayout中再嵌套TextView的布局来讨论Touch事件传递机制。

            对于ViewGroup类的控件,有一个很重要的方法,就是onInterceptTouchEvent(),用于处理事件并改变事件的传递方向,它的返回值是一个布尔值,决定了Touch事件是否要向它包含的子View继续传递,这个方法是从父View向子View传递。而方法onTouchEvent(),用于接收事件并处理,它的返回值也是一个布尔值,决定了事件及后续事件是否继续向上传递,这个方法是从子View向父View传递。

先来看下布局文件

<?xml version="1.0" encoding="utf-8"?>                

 OuterTouchLinearLayout,TouchLinearLayout分别重写了onInterceptTouchEvent、onTouchEvent,TouchTextView重写了onTouchEvent,并在Activity里重写了dispatchTouchEvent,onTouchEvent,在其中加入了打印代码,在此偷个懒,少打点字,以A代替Activity,以O代表外层(父)OuterTouchLinearLayout,I代表TouchLinearLayout,T代表 TouchTextView,d代表 dispatchTouchEvent,t代表onTouchEvent,i代表onInterceptTouchEvent。(如Ad代表触发了Activity的dispatchTouchEvent方法

        在TextView上划屏下,记录结果,并分别改变重写方法的返回值,得到如下结果集

测试结果 1、默认
0 ad-oi-ii-tt-it-ot-at 2 ad-at-ad-at 1 ad-at

2、a d
0 ad 2 ad-ad-ad 1 ad

3、ad at
0 ad 2 ad-ad-ad 1 ad

4、at
0 ad-oi-ii-tt-it-ot-at 2 ad-at-ad-at 1 ad-at

5、oi
0 ad-oi-ot-at 2 ad-at-ad-at 1 ad-at

6 oi ot
0 ad-oi-ot 2 ad-ot-ad-ot 1 ad-ot

7 ot
0 ad-oi-ii-tt-it-ot 2 ad-ot-ad-ot 1 ad-ot

8 ii
0 ad-oi-ii-it-ot-at 2 ad-at-ad-at 1 ad-at

9 ii it
0 ad-oi-ii-it 2 ad-oi-it-ad-oi-it 1 ad-oi-it

10 it
0 ad-oi-ii-tt-it 2 ad-oi-it 1 ad-oi-it

11 tt
0 ad-oi-ii-tt 2 ad-oi-ii-tt 1 ad-oi-ii-tt

 分析这些结果,可以得出结论:

 

        ACTION_DOWN事件首先会传到Activity的dispatchTouchEvent中,若返回false,则事件传递到ViewGroup类的onInterceptTouchEvent,onInterceptTouchEvent如果返回false,则DOWN事件继续向子ViewGroup类的onInterceptTouchEvent传递,如果子View不是ViewGroup类的控件,则传递给子View的onTouchEvent。

 

            另外:只要onInterceptTouchEvent()返回false,而且目标控件View::onTouchEvent()返回true,那么事件的每一个动作(按下、移动、抬起等)会都会首先传递到onInterceptTouchEvent()中。

 

        如果onInterceptTouchEvent返回了true,则DOWN事件传递给VIewGroup的onTouchEvent,不再继续传递,并且之后的后续事件也都传递给它的onTouchEvent。

 

        如果某View的onTouchEvent返回了false,则DOWN事件继续向其父ViewGroup类的onTouchEvent传递;如果返回了true,则后续事件会直接传递给其onTouchEvent继续处理。(后续事件只会传递给对于必要事件ACTION_DOWN返回了true的onTouchEvent)

 

 

 

Activity的onTouchEvent方法是事件最后被处理的地方。如果不处理,系统将抛弃这个事件。暂时没有发现这个方法的返回值对程序有什么意义。我觉得可以这样理解,就如我们说话给别人听,当所有需要听到的人听到这句话了,那这句话就完成了它的意义,在这之后不管又传了多远,还是被墙壁吸收了,都没啥影响。

 

 

更多相关文章

  1. Android使用JNI生成.so文件并调用(使用传统生成.h的方法)
  2. Android自定义控件——仿ios开关按钮
  3. 写了个android gif显示控件,很简单很方便,开源了
  4. android studio运行编译速度慢的解决方法
  5. Android模拟产生事件
  6. android中共享全局数据的方法
  7. Android的内存优化方法
  8. Android中事件分发机制

随机推荐

  1. Android 禁止横竖屏切换
  2. Android子控件超出父控件方法
  3. android 邮件乱码问题
  4. Android(安卓)截图实现(2)
  5. 2014年 Android 学习计划
  6. 安装 Mono for Android Visual Studio 20
  7. 安装Android 时 SDK AVD MANAGER时更新报
  8. [Android]Awind.inc系列android软件破解
  9. Android 问题汇总
  10. 自动换行