【转载+整理】Android中TouchEvent事件分析

原文地址:http://mobile.51cto.com/abased-374715.htm

一、知识回顾

  一个最简单的屏幕触摸动作触发了一系列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

五、结论

  1.当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View。

  2.TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由dispatchTouchEvent 方法进行分发。

    a)如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理。

    b)如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件。

  3.a)如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理。

   b)如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。

  如果事件传递到某一层的子 view 的 onTouchEvent 上并返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。

四、探索过程

通过语言描述这个处理逻辑很抽象,下面就用代码来具体说明一下。

a)实验代码:

1.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。

2.测试Activity代码

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);
    }
}     

3.ViewGroup用LineLayout,其代码:

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) {          c    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;      }  }                                  

4.Viewy用TextView,其代码如下:

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;       }  }  

b)输出及其结论

声明:为了指代方便,下面将MyLinearLayout简称为L,将MyTextView简称为 T,L.onInterceptTouchEvent=true 表示的含义为MyLinearLayout中的onInterceptTouchEvent方法返回值为true,通过程序运行时输出的Log来说明调用 时序。

1.第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.第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.第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.第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中TouchEvent事件分析

时间: 2024-08-24 22:53:28

【转载+整理】Android中TouchEvent事件分析的相关文章

Android中的事件分发机制

1. 一个小问题引发的思考 2. 通过源码探索View中的事件分发机制 3.通过源码探索ViewGroup的事件分发机制 最近的一个项目中涉及,布局为一个RelativeLayout包含了一个EditText和一个Button,当点击EditText时,弹出软键盘,点击RelativeLayout中除了EditText和Button之外其它的地方时,收起软键盘. 实现起来很简单,为EditText和RelativeLayout分别注册一个onTouch事件,为Button注册一个click事件,

Android中的事件分发机制(下)——View的事件处理

综述 在上篇文章Android中的事件分发机制(上)--ViewGroup的事件分发中,对ViewGroup的事件分发进行了详细的分析.在文章的最后ViewGroup的dispatchTouchEvent方法调用dispatchTransformedTouchEvent方法成功将事件传递给ViewGroup的子View.并交由子View进行处理.那么现在就来分析一下子View接收到事件以后是如何处理的. View的事件处理 对于这里描述的View,它是ViewGroup的父类,并不包含任何的子元

android中的事件传递和处理机制

一直以来,都被android中的事件传递和处理机制深深的困扰!今天特意来好好的探讨一下.现在的感觉是,只要你理解到位,其实事件的 传递和处理机制并没有想象中的那么难.总之,不要自己打击自己,要相信自己能掌握这块知识.好了,下面是我今天的收获,希望也 能对你有一点帮助. 一.拟人化来理解android中的事件机制 其实android中的事件传递与处理机制跟我们生活中的事件处理是一样的.这里有一个生活中的例子,很能说明这个问题.阐述如下: 你是一个公司的员工,你的上头有一个主管,主管上头呢还有一个经

Android中的事件分发机制——ViewGroup的事件分发

综述 Android中的事件分发机制也就是View与ViewGroup的对事件的分发与处理.在ViewGroup的内部包含了许多View,而ViewGroup继承自View,所以ViewGroup本身也是一个View.对于事件可以通过ViewGroup下发到它的子View并交由子View进行处理,而ViewGroup本身也能够对事件做出处理.下面就来详细分析一下ViewGroup对时间的分发处理. MotionEvent 当手指接触到屏幕以后,所产生的一系列的事件中,都是由以下三种事件类型组成.

一个demo让你彻底理解Android中触摸事件的分发

注:本文涉及的demo的地址:https://github.com/absfree/TouchDispatch 1. 触摸动作及事件序列 (1)触摸事件的动作 触摸动作一共有三种:ACTION_DOWN.ACTION_MOVE.ACTION_UP.当用户手指接触屏幕时,便产生一个动作为ACTION_DOWN的触摸事件,此时若用户的手指立即离开屏幕,会产生一个动作为ACTION_UP的触摸事件:若用户手指接触屏幕后继续滑动,当滑动距离超过了系统中预定义的距离常数,则产生一个动作为ACTION_MO

Android 中图片压缩分析(上)

作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情况下,改变图片的存储体积,而后者则是降低图像尺寸,达到相同目的. 由于本文的篇幅问题,分为上下两篇发布. 二.Android 质量压缩逻辑 在Android中,对图片进行质量压缩,通常我们的实现方式如下所示: ByteArrayOutputStream outputStream = new Byte

Android中的事件传递机制

Android源码版本:API Level 19(Android 4.4) Android事件构成 在Android中,事件主要包括点按.长按.拖拽.滑动等,点按又包括单击和双击,另外还包括单指操作和多指操作.所有这些都构成了Android中的事件响应.总的来说,所有的事件都由如下三个部分作为基础: 按下(ACTION_DOWN) 移动(ACTION_MOVE) 抬起(ACTION_UP) 所有的操作事件首先必须执行的是按下操作(ACTIONDOWN),之后所有的操作都是以按下操作作为前提,当按

[整理]android中几种常见的尺寸

获取屏幕宽高尺寸的三种代码形式 在Android上,目前我知道的获取屏幕尺寸的方法有三种不同的代码形式 方法1.在Activity中最常见的调用方式 WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); int screenWidth = display.getWidth(); int screenHeight = display.getHeig

PopupWindow在android中的使用分析

PopupWindow在android中的使用分析 PopupWindow是应用开发中经常用到的组建,使用它可以在当前屏幕的上层显示一个弹窗,同时也可以指定弹窗的位置以及背景色等特性,大大提高用户体验,那么这里我就以下几点介绍它的使用: 1 从指定的位置弹出这个窗口(淡入淡出动画) 2 从屏幕底部弹出这个窗口(带有透明度背景,自定义触摸其他位置自动关闭弹窗) 我的效果图如下: 下面直接上代码,具体如下所示(按开发顺序排列) 1 自定义一个继承自PopupWindow的类 publicclassP