枕上从妨一夜睡,灯前读尽十年诗。这篇文章主要讲述Android 事件机制相关的知识,希望能为你提供帮助。
一、简介
触摸事件就是捕获触摸屏幕后产生的事件。android为触摸事件封装了一个类—
—
MotionEvent,如果重写onTouchEvent(MotionEvent event)方法,就会发现该方法的参数就是一个MotionEvent类实例。
事件触发分为三个阶段,捕获、目标、冒泡。
第一个阶段为事件捕获,事件从根节点流向目标对象节点。途中经过各个层次的View节点,并在各节上触发捕获事件,直到到达事件的目标节点。
第二个阶段为目标阶段,事件进入到目标阶段,事件在目标节点上被触发,然后会逆向回流,直到传播至最外层的根节点。
第三个阶段为事件冒泡,事件在目录View节点上触发后,并不在这个元素上终止,它会随着节点树一层层向上冒泡,回溯到根节点上。
二、事件拦截机制分析
Android的View结构就是一个树形结构,View可以放在一个ViewGroup里面,这个ViewGroup又放在另一个ViewGroup里面,甚至还有可能继续嵌套,一层层地叠起来。触摸事件就一个,到底该分给谁?同一个事件,子View和父ViewGroup都有可能想要进行处理,因此就产生了“
事件拦截机制”
。
假设,你所在公司,有一个总经理,级别最高;他下面有一个部长,级别次之;最低层,就是干活的你,没有级别。现在董事会交给总经理一个任务,总经理将这项任务布置给了部长,部长又把任务安排给了你。而当你完成了这项任务,你就把任务交给部长,部长觉得任务完成的不错,于是就签了他的名字,将任务交给了总经理,总经理看了也觉得不错,就也签了名字交给董事会。这个,一个任务就顺利完成了。
一个总经理—
—
MyViewGroupA,最外层的ViewGroup;
一个部长—
—
MyViewGroupB,中间层ViewGroup;
一个干活的你—
—
MyView,在最低层;
对于ViewGroup,需要重写三个方法:
1 @Override 2 public boolean dispatchTouchEvent(MotionEvent event) 3 { 4Log.d(TAG, "ViewGroup dispatchTouchEvent" + event.getAction()); 5return super.dispatchTouchEvent(event); 6 } 7 8 @Override 9 public boolean onInterceptTouchEvent(MotionEvent event) 10 { 11Log.d(TAG, "ViewGroup onInterceptTouchEvent" + event.getAction()); 12return super.onInterceptTouchEvent(event); 13 } 14 15 @Override 16 public boolean onTouchEvent(MotionEvent event) 17 { 18Log.d(TAG, "ViewGroup onTouchEvent" + event.getAction()); 19return super.onTouchEvent(event); 20 }
对于View,需要重写如下两个方法:
1 @Override 2 public boolean dispatchTouchEvent(MotionEvent event) 3 { 4Log.d(TAG, "View dispatchTouchEvent" + event.getAction()); 5return super.dispatchTouchEvent(event); 6 } 7 8 @Override 9 public boolean onTouchEvent(MotionEvent event) 10 { 11Log.d(TAG, "View onTouchEvent" + event.getAction()); 12return super.onTouchEvent(event); 13 }
当点击View后的Log如下所示:
1 D/MyViewGroupA : ViewGroupA dispatchTouchEvent 2 D/MyViewGroupA : ViewGroupA onInterceptTouchEvent 3 D/MyViewGroupB : ViewGroupB dispatchTouchEvent 4 D/MyViewGroupB : ViewGroupB onInterceptTouchEvent 5 D/MyView : View dispatchTouchEvent 6 D/MyView : View onTouchEvent 7 D/MyViewGroupB : MyViewGroupB onTouchEvent 8 D/MyViewGroupA : MyViewGroupA onTouchEvent
从其中可以看到,事件传递顺序是:总经理(MyViewGroupA)— 部长(MyViewGroupB)— 你(MyView),这个过程就是事件的捕获阶段;
PS:事件传递,即捕获,就是执行dispatchTouchEvent()方法,再执行onInterceptTouchEvent()方法。
事件的处理顺序:在你去干活的过程就是事件的目标阶段,即View的onTouchEvent()方法执行;
【Android 事件机制】你(MyView)— 部长(MyViewGroupB)— 总经理(MyViewGroupA),这个过程就是事件的冒泡阶段;
PS:事件处理就是执行onTouchEvent()方法。
假设1:总经理(MyViewGroupA)发现这个任务太简单了,觉得自己就可以完成,完全没必要再找下属。因此,事件就被总经理(MyViewGroupA)onInterceptTouchEvent()方法把事件拦截了,即让onInterceptTouchEvent()方法返回值为True,下面再看看Log:
1 D/MyViewGroupA : ViewGroupA dispatchTouchEvent 2 D/MyViewGroupA : ViewGroupA onInterceptTouchEvent 3 D/MyViewGroupA : MyViewGroupA onTouchEvent
假设2:部长(MyViewGroupB)发现这个任务太简单了,觉得自己就可以完成,完全没必要再找下属。因此,事件就被部长(MyViewGroupB)onInterceptTouchEvent()方法把事件拦截了,即让onInterceptTouchEvent()方法返回值为True,下面再看看Log:
1 D/MyViewGroupA : ViewGroupA dispatchTouchEvent 2 D/MyViewGroupA : ViewGroupA onInterceptTouchEvent 3 D/MyViewGroupB : ViewGroupB dispatchTouchEvent 4 D/MyViewGroupB : ViewGroupB onInterceptTouchEvent 5 D/MyViewGroupB : MyViewGroupB onTouchEvent 6 D/MyViewGroupA : MyViewGroupA onTouchEvent
这两种情况下,可以看到总经理或者部长,MyViewGroupA或者MyViewGroupB将事件拦截了。
事件的返回值含义:当事件在传递的过程中,返回值:True,拦截,不继续;False,不拦截,继续流程,传递给下一级。
当事件在处理的过程中,返回值:True,处理了,不用审核了;False,交给上一级处理。
推荐阅读
- Android XML Drawable
- Android View的测量
- Android 本地序列化
- Android Activity的四种LaunchMode
- Ionic创建混合App
- androidj基础(从网上下载图片)
- Android状态栏着色
- Android 动画进阶之动画切换
- Android View的绘制