阅读更多

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

         以前写 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读写XML(中)——SAX
  2. Android中触摸事件传递机制
  3. Android中系统触摸相关辅助类总结
  4. IOS/Android(安卓)移动端原生及自定义控件开发集v0.1
  5. Android(安卓)辅助功能(无障碍)自定义开发类似微信抢红包插件
  6. Android高手进阶教程(二十三)之---Android中的日历读写操作!!!
  7. Android(安卓)的消息机制(Handler消息传递机制)
  8. Android使用JNI实现Java与C之间传递数据
  9. Android界面编程——Android基本控件

随机推荐

  1. Javascript日期/时间函数是否依赖于客户
  2. 为什么在JavaScript中[5,6,8,7][1,2]= 8
  3. 【第2篇】TypeScript - 基本类型详解
  4. RxJs分组热观测值的笛卡尔积
  5. 取消/中止angularJs中的所有待处理请求
  6. 如何根据最新到最旧的id值对Json进行排序
  7. CSS3(jQUery?)当它悬停时隐藏元素“a”,这样
  8. LeetCode14.最长公共前缀 JavaScript
  9. ECMAScript6(6):数组的扩展
  10. 运行一次后停止执行函数