Android事件分发、拦截与处理的理解
来源:互联网 发布:cdn 云计算 编辑:程序博客网 时间:2024/05/01 16:42
转载请注明出处
http://blog.csdn.net/guodongAndroid/article/details/51727272
本文来自【孫小逗的博客】
一、概述
昨天,某位黑同学问了个很奇葩的问题:禁止ViewPager的左右滑动。好吧,被问到的一瞬间就想是不是他傻X。ViewPager不滑动,干嘛还要用ViewPager,唉,无语。无语归无语,事情还是要干的。随手给他写了个自定义的ViewPager。。。。(吹牛一点都不好)
二、事件分发、拦截与处理
首先需要知道事件分发、拦截与处理分别对应着
- dispatchTouchEvent(MotionEvent ev)
- onInterceptTouchEvent(MotionEvent ev)
- onTouchEvent(MotionEvent event)
ViewGroup比View多了onInterceptTouchEvent(MotionEvent ev)
方法,即事件拦截方法。因为ViewGroup可以包含子View,所以与子View的事件有冲突时可以进行拦截。
这三个方法默认返回值都为false。
下面看个例子会更容易理解:
自定义了两个LinearLayout和一个View,代码如下:
FirstViewGroup.java
public class FirstViewGroup extends LinearLayout{ private final static String TAG = "FirstViewGroup"; public FirstViewGroup(Context context) { this(context, null); } public FirstViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FirstViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setBackgroundColor(0x88FF0000); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.d(TAG, "dispatchTouchEvent:" + ev.getAction()); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.d(TAG, "onInterceptTouchEvent:" + ev.getAction()); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.d(TAG, "onTouchEvent:" + event.getAction()); return super.onTouchEvent(event); }}
SecondViewGroup.java
public class SecondViewGroup extends LinearLayout{ private final static String TAG = "SecondViewGroup"; public SecondViewGroup(Context context) { this(context, null); } public SecondViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SecondViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setBackgroundColor(0x88FFFF00); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.d(TAG, "dispatchTouchEvent:" + ev.getAction()); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.d(TAG, "onInterceptTouchEvent:" + ev.getAction()); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.d(TAG, "onTouchEvent:" + event.getAction()); return super.onTouchEvent(event); }}
MyView.java
public class MyView extends View{ private final static String TAG = "MyView"; public MyView(Context context) { this(context, null); } public MyView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setBackgroundColor(0x6600FF00); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.d(TAG, "dispatchTouchEvent: " + event.getAction()); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.d(TAG, "onTouchEvent: " + event.getAction()); return super.onTouchEvent(event); }}
可以看到两个ViewGroup实现了事件分发、拦截与处理三个方法,并打印了Log,MyView实现了事件分发与处理两个方法,也打印了Log。
下面看看布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.sun.androidqyz.FirstViewGroup android:layout_width="match_parent" android:layout_height="match_parent" android:padding="40dp"> <com.sun.androidqyz.SecondViewGroup android:layout_width="match_parent" android:layout_height="match_parent" android:padding="60dp"> <com.sun.androidqyz.MyView android:layout_width="match_parent" android:layout_height="match_parent"/> </com.sun.androidqyz.SecondViewGroup> </com.sun.androidqyz.FirstViewGroup></RelativeLayout>
效果如图所示:
可以看到最外层的ViewGroup的背景色是浅红色,第二层的ViewGroup的背景色是橙色,最里面的View背景色是绿色。
现在我们点击最外层的ViewGroup,看下打印的Log如下:
可以发现事件处理的顺序是先调用事件分发(dispatchTouchEvent)——>事件拦截(onInterceptTouchEvent)——>事件处理(onTouchEvent)
接下来我们点击第二层ViewGroup,看下打印的Log如下:
可以发现现在事件处理的顺序是先调用FirstViewGroup事件分发(dispatchTouchEvent)——>FirstViewGroup事件拦截(onInterceptTouchEvent)——>SecondViewGroup事件分发(dispatchTouchEvent)——>SecondViewGroup事件拦截(onInterceptTouchEvent)——>SecondViewGroup事件处理(onTouchEvent)——>FirstViewGroup事件处理(onTouchEvent)
相信看到这,当我们点击MyView的时候,打印的Log您已经知道是什么了,让我们看看吧:
是不是和你想的一样呢?事件的分发、拦截与处理就像现实生活中领导A分发个任务给领导B,领导再把任务分发给你(MyView),你处理(onTouchEvent)完时需要向上汇报给领导B,领导B处理(onTouchEvent)完,再汇报给领导A。
在自定义控件时,很少去复写dispatchTouchEvent方法,所以这里我们只看事件拦截(onInterceptTouchEvent)。
如果领导A觉得这个任务自己就可以完成,就不去派给领导B,我们就把FirstViewGroup的onInterceptTouchEvent方法返回true,当我们点击SecondViewGroup或MyView时,我们看下Log:
说明此时领导A已经把任务拦截下,自己处理了,如果领导B拦截了任务会是怎样的呢?点击MyView时的Log如下:
如果你(MyView)受不了领导的压迫,要反抗,处理完任务后返回了true,点击MyView的Log如下:
看来是真要反抗了,处理完任务都不向领导汇报了。
三、总结
Android事件分发、拦截与处理是个复杂的过程,在开发的过程中运用的场景也很多,是Android开发必须掌握的技能。现在回过头来,不从源码的角度看看Android的事件分发、拦截与处理和现实生活中的领导分派任务又有什么区别呢?
- Android事件分发、拦截与处理的理解
- Android触摸事件的分发、拦截、处理
- android事件分发,拦截,处理
- Android事件的分发与拦截机制
- Android---事件分发与拦截
- Android的事件分发(dispatchTouchEvent),拦截(onInterceptTouchEvent)与处理(onTouchEvent)
- Android事件分发,拦截,处理机制
- android事件分发、拦截、处理(未完)
- 包子理论解释Android点击事件的拦截与分发
- Android事件机制之ViewPager的分发与拦截
- Android事件分发,事件拦截,事件处理总结
- Android事件分发,事件拦截,事件处理总结
- 事件分发与拦截
- Android 事件拦截分发
- ViewGroup的事件拦截、事件分发、事件处理
- Android事件分发,拦截的流程梳理
- Android事件的分发、拦截和执行
- Android事件的分发、拦截和执行
- Windows下架设自己的DNS服务器
- 秒懂inner join, left join, right join, full join 的区别!!
- Material design 学习笔记
- js 设置radio默认选中
- java中String.split()的常用方法
- Android事件分发、拦截与处理的理解
- 利用Java反射机制创建对象,Spring管理Bean原理 例子。
- mysql远程登录并设置密码
- 数据库索引
- Spring学习-AOP
- 简介mybatis一对多的collection
- 找不到 Class BASE64Decoder 的解决办法
- Volley
- nginx地址重定向