当你作为一名应届生去面试的时候,面试官可能就是简单的问你Android的四大组件,各种布局等基础知识,但你作为一名有工作经验的应聘者就不会那么简单了,今天就来讨论很多面试官喜欢问的Android的事件分发.

Android为什么要有事件分发呢?因为它是按照层排列,他如何知道你点击的哪一层呢,就需要用到事件分发了.

说到事件分发可能就会想起那三个威武的方法:事件分发(dispatchTouchEvent(MotionEvent ev))、事件拦截(onInterceptTouchEvent(MotionEvent ev))、事件响应(onTouchEvent(MotionEvent ev)),其中ViewGroup响应这三个方法,View要看它是否有子View,没有子View时不响应事件拦截,Activity不响应事件拦截.

这里先给出一张事件分发的流程图


当然不是所有情况下都这么走,当你的View和ViewGroup都是系统默认的情况下,是根据上图的流程走,只要View或者ViewGroup中的任何一个对事件感兴趣,流程就不一定是什么样子了,这个需要具体问题具体分析

下面通过一个demo分析一下具体问题,demo只贴一下代码,不提供代码,希望自己动动手,写写,看看到底是什么样子的

我写的demo一个有三部分,Activity,View,ViewGroup三部分,重写了一下那三个威武的函数,当然像activity这样的就不用写事件拦截,学着灵活运用

1,activity代码

package com.thea.guo;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.view.Menu;import android.view.MotionEvent;import android.view.View;import android.widget.Button;public class MainActivity extends Activity {Button button;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MainActivity.dispatchTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MainActivity.dispatchTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MainActivity.dispatchTouchEvent is up");break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MainActivity.onTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MainActivity.onTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MainActivity.onTouchEvent is up");break;}return super.onTouchEvent(event);}}

2.view代码

/** *  */package com.thea.guo.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.Button;import android.widget.TextView;/** * @author 子墨 * * 2015-1-15 */public class MyView extends TextView {public MyView(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyView.dispatchTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyView.dispatchTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyView.dispatchTouchEvent is up");break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyView.onTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyView.onTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyView.onTouchEvent is up");break;}return super.onTouchEvent(event);}}

3.ViewGroup代码

/** *  */package com.thea.guo.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;/** * @author 子墨 * * 2015-1-15 */public class MyViewGroup extends LinearLayout {public MyViewGroup(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyViewGroup.dispatchTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyViewGroup.dispatchTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyViewGroup.dispatchTouchEvent is up");break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyViewGroup.onInterceptTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyViewGroup.onInterceptTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyViewGroup.onInterceptTouchEvent is up");break;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyViewGroup.onTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyViewGroup.onTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyViewGroup.onTouchEvent is up");break;}return super.onTouchEvent(event);}}

4.xml代码

        

以上就是全部代码了,其实你还可以吧一部分代码封装一下更好,例如down,Move,up部分都是一样的,你可以把这部分封装.下面开始分析一下上文提到的特殊情况

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.修改ViewGroup的dispatchTouchEvent(事件分发)返回值

(1)返回值为true

上面两张图片比较醒目的解释了它的分发过程,首先从activity的dispatchTouchEvent开始分发,系统默认的情况下继续分发,分发给ViewGroup的dispatchTouchEvent,ViewGroup的dispatchTouchEvent返回true,也就是说它对这个事件比较感兴趣,它想留着自己处理,事件停止分发.

(2)返回值为false



同样是从activity的dispatchTouchEvent开始分发,分发给ViewGroup的dispatchTouchEvent,ViewGroup的dispatchTouchEvent返回false,ViewGroup不感兴趣,但是它也不配合你,他直接不给你往下传递了,这时候就需要onTouchEvent来处理了,由于view是从activity开始发起,所以就需要activity的OnTouchEvent来处理了

2.修改ViewGroup的onInterceptTouchEvent返回值

(1)返回值为true



还是从activity的dispatchTouchEvent开始分发,分发给ViewGroup的dispatchTouchEvent,ViewGroup判断一下是否拦截,由于这里onInterceptTouchEvent的返回值为true,不好意思它拦截了,它想让它的OnTouchEvent处理这个事件,ViewGroup的OnTouchEvent处理完成后继续向下传递给activity的OnTouchEvent

(2)返回值为false



上图是不是似曾相识啊,没错,ViewGroup中的onInterceptTouchEvent默认就是不拦截的,先从activity中的dispatchTouchEvent开始分发,分发给ViewGroup中的dispatchTouchEvent,然后判断ViewGroup是否拦截,这里返回false,表示它不拦截,然后继续分发,分发给View中的dispatchTouchEvent,View下没有子View了,于是他就直接给自己的onTouchEvent处理了,onTouchEvent对这个也不感兴趣,继续传递

3.修改View的dispatchTouchEvent返回值

(1)返回值为true



这里还是那个分发过程,当分发到View时,它返回了true,也就是说它很感兴趣,它想自己处理.

(2)返回值为false



还是那个配方还是那个味道,View中dispatchTouchEvent返回false,它直接不给分发了,留给OnTouch处理,由于view是从ViewGroup传递过来的,那也要ViewGroup的自个处理.

4.修改view中OnTouchEvent的返回值

(1)返回值为true



事件还是一如既往的传递,当传递到View中的OnTouchEvent时,返回true,它要say sorry了,不给你们传递了,到这它要自己处理了

(2)返回值为false



后面的OnTouchEvent跟view的都差不多了,这里不再啰嗦,下面来个总结,结束这篇博客


1.dispatchTouchEvent(事件分发)

当dispatchTouchEvent返回true时,由它自己处理

当dispatchTouchEvent返回false时,交给OnTouchEvent处理

系统默认的情况下,分发给onInterceptTouchEvent

2.onInterceptTouchEvent(事件拦截)

当onInterceptTouchEvent返回true,由他自己的OnTouchEvent处理

当onInterceptTouchEvent返回false,继续分发

系统默认不拦截

3.onTouchEvent(事件响应)

当onTouchEvent返回true时自己处理

当onTouchEvent返回false,继续传递

系统默认继续传递

更多相关文章

  1. android 监控软键盘确定 搜索 按钮并赋予点击事件
  2. Android事件分发机制详解:史上最全面、最易懂
  3. android一个很恶心的东西
  4. Android中的事件分发机制
  5. Android(安卓)事件分发
  6. Android读写XML(中)——SAX
  7. android window类解析
  8. Android读写XML(中)——SAX
  9. Android事件分发机制详解

随机推荐

  1. sql server中死锁排查的全过程分享
  2. Sql Server 数据库中调用dll文件的过程
  3. sql server数据库高可用日志传送的方法
  4. SqlServer 获取字符串中小写字母的sql语
  5. Sql Server 如何去掉内容里面的Html标签
  6. SQL Server 远程更新目标表数据的存储过
  7. 使用sqlplus创建DDL和DML操作方法
  8. 详解SqlServer数据库中Substring函数的用
  9. SQL Server Management Studio(SSMS)复制数
  10. Windows下SQL Serever 2012彻底卸载删除