Android里面事件传递机制还是非常重要的。
下面记录一下Touch事件:
涉及Activity 、View 、ViewGroup
Touch 事件相关方法 | 方法功能 | ViewGroup | View | Activity |
dispatchTouchEvent(MotionEvent ev) | 事件分发
| Yes | Yes | Yes |
onInterceptTouchEvent(MotionEvent ev) | 事件拦截
| Yes | No | No |
onTouchEvent(MotionEvent ev) | 事件处理 | yes | yes | yes |
用代码来测试:
如上图,有三个控件,最外侧是LinearLayout、第二层也是LinearLayout,里面是一个View
Touch事件传递,Activity----》MyLinearLayout1----》MyLinearLayout2----》MyView
下面我用图来描述事件传递的过程。
红色表示返回值为true,蓝色表示返回值为false
小结:
· Android中事件传递按照从上到下进行层级传递,事件处理从Activity开始到ViewGroup再到View。
· 事件传递方法包括dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent,其中前两个是View和ViewGroup都有的,最后一个是只有ViewGroup才有的方法。这三个方法的作用分别是负责事件分发、事件处理、事件拦截。
· onTouch事件要先于onClick事件执行,onTouch在事件分发方法dispatchTouchEvent中调用,而onClick在事件处理方法onTouchEvent中被调用,onTouchEvent要后于dispatchTouchEvent方法的调用。
· Touch事件里面有down、move、up三种事件。先传入down事件,如果我们的界面上的所有地方都没有消费掉这个down事件,那么android系统就会认为我们的界面上不需要处理Touch事件,那么后面的move、up事件都不会再传入进来。(非常重要)
上图是我们的测试日志,里面的数字0表示Down事件。
MyLinearLayout1 、MyLinearLayout2,MyView我都没有处理Touch事件。从上图可以看出根本就没有Move(2)、UP(1)的事件。
概念的东西先就说这么多,下面说一个我遇到的例子:
了解了这些之后,我们就可以在做项目的时候更好的利用事件传递机制了。比如最近项目里面有一个需求是,在一个播放pdf或视频的界面,如果用户一分钟没有操作屏幕上面的任何东西就要暂停播放,并且弹出对话框询问用户是否离开。用户点击对话框上的“我在的”按钮,就dismiss对话框继续播放。(想出这个需求的人真是TM的淫才,纯粹没事找事干)。
要实现这个功能笨一点的方法是在界面上的每个控件上都注册onTouch事件或者onClick事件。界面简单的话,这个方法是可以的。但是要是界面上有十几二十个控件怎么办呢。
现在了解了android的事件传递机制就简单了。
最牛逼彻底的方法是:在 Activity 的 dispatchTouchEvent 方法中处理。这是事件最先到达的地方,之后才会传到 Window 里面,再然后才到界面的布局中。这样写又方便又维护简单。