Android dispatchTouchEvent介绍
一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP
当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是 ViewGroup来处理Touch事件,还是子view来处理Touch事件呢?这个并不一定。为什么呢?看看下面的调查结果就明白了。
android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由 dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。
通过语言描述这个处理逻辑很抽象,下面就用代码来具体说明一下。
layout配置文件 main.xml:
- <?xml version="1.0" encoding="utf-8"?>
- <test.lzqdiy.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="center" >
- <test.lzqdiy.MyTextView
- android:layout_width="200px"
- android:layout_height="200px"
- android:id="@+id/tv"
- android:text="lzqdiy"
- android:textSize="40sp"
- android:textStyle="bold"
- android:background="#FFFFFF"
- android:textColor="#0000FF"/>
- </test.lzqdiy.MyLinearLayout>
节点层次很简单,一个LinearLayout中添加了一个TextView。
下面是java代码:
- package test.lzqdiy;
- import android.app.Activity;
- import android.os.Bundle;
- public class TestTouchEventApp extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- }
- package test.lzqdiy;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.widget.LinearLayout;
- public class MyLinearLayout extends LinearLayout {
- private final String TAG = "MyLinearLayout";
- public MyLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- Log.d(TAG, TAG);
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_CANCEL");
- break;
- }
- return super.dispatchTouchEvent(ev);
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "onInterceptTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "onInterceptTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "onInterceptTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "onInterceptTouchEvent action:ACTION_CANCEL");
- break;
- }
- return false;
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "---onTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");
- break;
- }
- return true;
- }
- }
- package test.lzqdiy;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.widget.TextView;
- public class MyTextView extends TextView {
- private final String TAG = "MyTextView";
- public MyTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "onTouchEvent action:ACTION_CANCEL");
- break;
- }
- return super.dispatchTouchEvent(ev);
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "---onTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");
- break;
- }
- return true;
- }
- }
为了指代方便,下面将MyLinearLayout简称为L,将MyTextView简称为 T,L.onInterceptTouchEvent=true 表示的含义为MyLinearLayout中的onInterceptTouchEvent方法返回值为true,通过程序运行时输出的Log来说明调用 时序。
第1种情况 L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=true 输出下面的Log:
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(11865): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_MOVE
D/MyTextView(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyTextView(11865): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_UP
D/MyTextView(11865): dispatchTouchEvent action:ACTION_UP
D/MyTextView(11865): ---onTouchEvent action:ACTION_UP
结论:TouchEvent完全由TextView处理。
第2种情况 L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=false 输出下面的Log:
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_UP
结论:TextView只处理了ACTION_DOWN事件,LinearLayout处理了所有的TouchEvent。
第3种情况 L.onInterceptTouchEvent=true&& L.onTouchEvent=true 输出下面的Log:
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_UP
结论:LinearLayout处理了所有的TouchEvent。
第4种情况 L.onInterceptTouchEvent=true&& L.onTouchEvent=false 输出下面的Log:
D/MyLinearLayout(13452): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): ---onTouchEvent action:ACTION_DOWN
结论:LinearLayout只处理了ACTION_DOWN事件,那么其他的TouchEvent被谁处理了呢?答案是LinearLayout最外层的Activity处理了TouchEvent。
Android dispatchTouchEvent介绍的更多相关文章
- android Animation介绍
Animation介绍: 在Android SDK介绍了2种Animation模式: 1. Tween Animation:间动画,通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果,即 ...
- android AsyncTask介绍(转)
android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...
- Android monkey介绍
Android monkey介绍 原文地址 1 简略 monkey是android下自动化测试比较重要的的一个工具,该工具可以运行在host端或者设备(模拟器或真实设备).它会向系统发送随机事件流(即 ...
- [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍
注:为了看上去比较清晰这里只转载了中文 原地址: [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍 本章将引导您完成安装和设置开发环境,然后你就可 ...
- 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ A2DP.SINK.sink_connect.s ...
- Android bluetooth介绍(四): a2dp connect流程分析
关键词:蓝牙blueZ A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_ ...
- android动画介绍之 自己定义Animation动画实现qq抖一抖效果
昨天我们介绍了Animation的基本使用方法.小伙伴们了解的怎么样了?假设还没有了解过Animation的小伙伴能够看看这篇博客 android动画介绍--Animation 实现loading动画 ...
- android动画介绍之 自定义Animation动画实现qq抖一抖效果
昨天我们介绍了Animation的基本用法.小伙伴们了解的怎么样了?如果还没有了解过Animation的小伙伴可以看看这篇博客 android动画介绍--Animation 实现loading动画效果 ...
- android动画介绍--Animation 实现loading动画效果
Animation的使用方法并不难.这里简单的介绍一下使用方法. 先看效果图: 效果还是不错的吧. 下面来看看使用方法. 动画效果是通过Animation来实现的,一共有四种,分别为: AlphaAn ...
随机推荐
- AngularJS学习笔记(1)
<!DOCTYPE html> <html> <body> <div ng-app=""> <p>在输入框中尝试输入:& ...
- C#深度拷贝和浅度拷贝方法
C#浅度拷贝多用于值类型的复制,即 int a=1;int b=a; 设置b=2后不会影响a的值. 但如果对于引用类型class a=new class(); class b=a; 设置b.name= ...
- 获取su后执行的脚本的返回值
错误的方式: # su - testuser -c "/tmp/test.sh; echo $?"Sun Microsystems Inc. SunOS 5.10 G ...
- MagicalRecord 多表关联数据操作
最近在使用MagicalRecord做数据持久层CoreData的操作库,今天做了一个多表关联数据的操作,整理了一个demo,特此记录一下. 关于如何使用Cocopads 和 MagicalRecor ...
- C#中的var类型
var关键字是C#3.0开始新增的特性,称为推断类型(其实也就是弱化类型的定义) . VAR可代替任何类型,编译器会根据上下文来判断你到底是想用什么类型,类似 OBJECT,但是效率比OBJECT高点 ...
- 关于asp的运行环境配置
xp系统的配置方法http://jingyan.baidu.com/article/4f7d571289ac441a201927da.html win7系统的配置方法http://jingyan.ba ...
- WPF的Binding学习笔记(一)
原文: http://www.cnblogs.com/pasoraku/archive/2012/10/20/2732427.html 一.binding的一般步骤 1,准备数据源 数据源需要 ...
- ios项目接入sdk事项
使用cocos2d-x引擎创建的项目在xcode里可以看到都带有一个ios目录,把要接入的sdk的包含.framework库文件和.bundle的资源文件的父目录拖入到xcode项目里的这个ios目录 ...
- strncpy基本用法
见百度百科. 注意这句话: (c/c++)复制src中的内容(字符,数字.汉字....)到dest,复制多少由num的值决定,返回指向dest的指针.如果遇到null字符('\0'),且还没有到num ...
- 2009年到2013年甲子园ED
2009年 2010年 最喜欢的一个!看过N遍 2011年 也不错! 2012年 超级好听啊~^_^比10年的还好,看过N+1遍……o(╯□╰)o 2013年春季甲子园 2013年夏季 印象最深的 ...