android控件的事件传播机制
来源:互联网 发布:华为云计算认证招聘 编辑:程序博客网 时间:2024/05/05 04:53
事件相关的三个事件方法
dispatcherEvent 负责分发事件的, 函数主要作用是来决定当前的事件是交由自己消费处理,还是交由子控件处理。
返回true,表示事件不再向下分发,事件在这次分发中消费掉。
返回false表示该组件不参与事件分发,事件交由上层组件的onTouchEvent处理。
返回值为super.dispatcherEvent时,表示事件将向下分发。
onInterceptTouchEvent 决定是否要拦截这个事件。 返回true,则事件不再向下传递,交由组件的onTouchEvent处理。 返回false,则事件继续向下传递。onTouchEvent 决定事件是否继续向上冒泡。 返回true则事件不再向上冒泡,事件被直接消费掉。 返回false则事件向上冒泡。
调用顺序
dispatcherEvent -> onInterceptTouchEvent - > onTouchEvent
下面用一实例来证明上面的结论。
我写了三个简单的控件继承已有的控件,并实现其中事件响应的方法。
public class MyViewGroup1 extends RelativeLayout{ //...省略构造方法@Override public boolean onTouchEvent(MotionEvent event) { String msg = "MyViewGroup1 -> onTouchEvent"; Log.d(TAG, msg); return super.onTouchEvent(event); } /** * 返回false 拦截事件 返回true 放 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { String msg = "MyViewGroup1 -> onInterceptTouchEvent"; Log.d(TAG, msg); return super.onInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { isFirst = false; String msg = "MyViewGroup1 -> dispatchTouchEvent"; Log.d(TAG, msg); return super.dispatchTouchEvent(ev); } }}
-------public class MyViewGroup2 extends RelativeLayout{ //...省略构```/** * 返回false 拦截事件 * 返回true 放 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { String msg = "MyViewGroup2 -> onInterceptTouchEvent"; Log.d(TAG, msg); return super.onInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { String msg = "MyViewGroup2 -> dispatchTouchEvent"; Log.d(TAG, msg); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { String msg = "MyViewGroup2 -> onTouchEvent"; Log.d(TAG, msg); return super.dispatchTouchEvent(ev); } }}--------------public class MyView1 extends TextView {private static final String TAG = "MyViewGroup2";private boolean isFirst = true;@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {String msg = "MyView1 -> dispatchTouchEvent";Log.d(TAG, msg);return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (isFirst) {isFirst = false;String msg = "MyView1 -> onTouchEvent";Log.d(TAG, msg);return super.dispatchTouchEvent(ev);} else {return true;}}}//为了让防止点击时响应多次点击,加入以上代码中的isFirst判断----------------------------------------
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <wei.jiang.selfview.eventtest.MyViewGroup1 android:id="@+id/outGroup" android:layout_width="match_parent" android:layout_height="match_parent" > <wei.jiang.selfview.eventtest.MyViewGroup2 android:id="@+id/inGroup" android:layout_centerInParent="true" android:background="@android:color/darker_gray" android:layout_width="200px" android:layout_height="200px" > <wei.jiang.selfview.eventtest.MyView1 android:id="@+id/content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_centerInParent="true" android:text="内容" > </wei.jiang.selfview.eventtest.MyView1> </wei.jiang.selfview.eventtest.MyViewGroup2> </wei.jiang.selfview.eventtest.MyViewGroup1></LinearLayout>
这是我们画出的组件,其中文字部分是MyView1, 灰色部分是MyViewGroup2, 白色部分是MyViewGroup1,
我们在不修改任务事件方法的情况下,日志如下。
图1
可以看出只有最里层的子控件响应了onTouchEvent.
首先来实验dispatchTouch方法,这里我们改改MyViewGroup2即中间控件组的dispatchTouch方法的返回值,结果如下: return true ->
图2
可以 看到事件到了viewGroup2的dispatchTouchEvent方法时就直接被消耗掉。
return false ->
图3
事件又返回到上层父控件的onTouchEvent的方法响应。这里父控件响应了这次的touch事件,并。
这里可以得到结论。
dispatchTouchEvent
返回true,表示事件不再向下分发,事件在这次分发中消费掉。
返回false表示该组件不参与事件分发,事件交由上层组件的onTouchEvent处理。
返回值为super.dispatcherEvent时,表示事件将向下分发。
现在来看onInterceptTouchEvent, 查看父类源码可发现父类直接返回了false,所以这里修改成true看结果。
return true ->
图4
这里可以看出事件都是在viewGroup2的onTouchEvent中被响应,但事件并没有被消耗掉,事件会不断的在MyViewGroup2中传递。
最后我们来修改onTouchEvent的返回值,
return true ->
图5
可以看出事件到了MyViewGroup2被正常消耗掉。事件被拦截了一次
return false ->
图6 事件被MyViewGroup2响应,并且冒泡给了MyViewGroup2的onTouchEvent方法响应。
做到这里,上面的关于三个事件分发方法的结论已经得到了验证。但还有一个问题就是事件的消耗的问题,
做到这里,上面的关于三个事件分发方法的结论已经得到了验证。但还有一个问题就是事件的消耗的问题,
1. 当dispatchTouch方法返回true或者onTouchEvent方法返回true时 如图2,事件被耗掉,日志中会有两次响应的过程,
但只有第一次响应了onInterceptTouchEvent方法,如图5,查看源码可以发现onInterceptTouchEvent对拦截做过判断,
说明这是两次事件过程,个人理解是按下与松开的事件。
2. 当事件返回到上层父控件响应后,事件响应过程只有一次,如图3,6, 说明事件被冒泡到上层后被上层消耗掉,之后相同事件将会直接被上层响应。(侍论证) 3,当事件没有被消耗掉时,如图4,事件会在子控件中不断的响应,这里应该是由onTouchEvent方法内部不断的循环调用造成。
- android控件的事件传播机制
- android控件的事件传播机制
- Android 事件传播机制
- android 事件传播机制
- Android View事件传播机制
- 黑马程序员12——android之事件传播机制
- android学习_Handler信息的传播机制
- JavaScript事件传播(冒泡机制)
- DOM2和IE的事件传播机制(捕捉,起泡)
- Android控件之View的事件分发机制探索
- Spring的事件传播
- Android的事件机制
- 【自定义控件】android事件分发机制
- web2.0中的事件传播机制
- DOM模型事件传播机制应用
- android 触屏事件上下view间的传播
- Android消息机制Looper与VSync的传播
- 简单记录控件事件的分发机制
- (转)理解Javascript_01_理解内存分配
- tsung安装使用
- 给你n个整数,求他们中所有奇数的乘积。
- phpstorm10.0.0破解(10.0.2已失效)
- 013 - Roman to Integer
- android控件的事件传播机制
- java去除html代码
- APK path is not specified for module
- ubuntu12.04 安装时提示 无法将grub-efi-amd64-signed软件包安装到/target
- iOS开发UITabBarController设置选中图片
- IO端口和IO内存
- fullPage插件全屏滑动效果
- charles使用教程指南
- Jackson和Gson的使用