Android Touch事件原理加实例分析

摘要:
Android中有各种事件来响应用户操作。这些事件可分为关键事件和触摸屏事件。触摸事件是触摸屏事件的基本事件,在Android开发中经常使用,因此有必要深入了解其原理和机制。AndroidTouch事件原理描述了一个简单的屏幕触摸动作触发一系列触摸事件:action_ DOWN->动作_移动->诉讼,诉讼_

       Android中有各种各样的事件,以响应用户的操作。这些事件可以分为按键事件和触屏事件。而Touch事件是触屏事件的基础事件,在进行Android开发时经常会用到,所以非常有必要深入理解它的原理机制。

       Android Touch事件原理描述

       一个最简单的屏幕触摸动作触发了一系列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 的话,这个事件就会“消失”,而且接收不到下一次事件。

       Android Touch事件实例分析

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

       layout配置文件 main.xml:

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <test.lzqdiy.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:gravity="center" >  
  7.        <test.lzqdiy.MyTextView    
  8.             android:layout_width="200px"  
  9.             android:layout_height="200px"  
  10.             android:id="@+id/tv"  
  11.             android:text="lzqdiy"  
  12.             android:textSize="40sp"  
  13.             android:textStyle="bold"  
  14.             android:background="#FFFFFF"  
  15.             android:textColor="#0000FF"/>  
  16. </test.lzqdiy.MyLinearLayout>  

       节点层次很简单,一个LinearLayout中添加了一个TextView。

       下面是java代码:

Java代码
  1. package test.lzqdiy;   
  2.   
  3. import android.app.Activity;   
  4. import android.os.Bundle;   
  5.   
  6. public class TestTouchEventApp extends Activity {   
  7.     /** Called when the activity is first created. */  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {   
  10.         super.onCreate(savedInstanceState);   
  11.         setContentView(R.layout.main);   
  12.     }   
  13. }   
  14. package test.lzqdiy;   
  15.   
  16. import android.content.Context;   
  17. import android.util.AttributeSet;   
  18. import android.util.Log;   
  19. import android.view.MotionEvent;   
  20. import android.widget.LinearLayout;   
  21.   
  22. public class MyLinearLayout extends LinearLayout {   
  23.     private final String TAG = "MyLinearLayout";   
  24.   
  25.     public MyLinearLayout(Context context, AttributeSet attrs) {     
  26.         super(context, attrs);     
  27.         Log.d(TAG, TAG);     
  28.     }   
  29.   
  30.     @Override  
  31.     public boolean dispatchTouchEvent(MotionEvent ev) {   
  32.         int action = ev.getAction();  
  33.    
  34.         switch (action) {     
  35.         case MotionEvent.ACTION_DOWN:     
  36.             Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN"); 
  37.             break;     
  38.         case MotionEvent.ACTION_MOVE:     
  39.             Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE"); 
  40.             break;     
  41.         case MotionEvent.ACTION_UP:     
  42.             Log.d(TAG, "dispatchTouchEvent action:ACTION_UP"); 
  43.             break;     
  44.         case MotionEvent.ACTION_CANCEL:     
  45.             Log.d(TAG, "dispatchTouchEvent action:ACTION_CANCEL"); 
  46.             break;     
  47.         }   
  48.  
  49.         return super.dispatchTouchEvent(ev);   
  50.     }   
  51.   
  52.     @Override  
  53.     public boolean onInterceptTouchEvent(MotionEvent ev) {     
  54.         int action = ev.getAction();  
  55.    
  56.         switch (action) {     
  57.         case MotionEvent.ACTION_DOWN:     
  58.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_DOWN"); 
  59.             break;     
  60.         case MotionEvent.ACTION_MOVE:     
  61.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_MOVE"); 
  62.             break;     
  63.         case MotionEvent.ACTION_UP:     
  64.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_UP"); 
  65.             break;     
  66.         case MotionEvent.ACTION_CANCEL:     
  67.             Log.d(TAG, "onInterceptTouchEvent action:ACTION_CANCEL"); 
  68.             break;     
  69.         }     
  70.         return false;     
  71.     }   
  72.   
  73.     @Override  
  74.     public boolean onTouchEvent(MotionEvent ev) {     
  75.         int action = ev.getAction();   
  76.   
  77.         switch (action) {     
  78.         case MotionEvent.ACTION_DOWN:     
  79.             Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");     
  80.             break;     
  81.         case MotionEvent.ACTION_MOVE:     
  82.             Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");     
  83.             break;     
  84.         case MotionEvent.ACTION_UP:     
  85.             Log.d(TAG, "---onTouchEvent action:ACTION_UP");     
  86.             break;     
  87.         case MotionEvent.ACTION_CANCEL:     
  88.             Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");   
  89.             break;     
  90.         }   
  91.   
  92.         return true;   
  93.     }   
  94.   
  95. }   
  96.   
  97. package test.lzqdiy;   
  98.   
  99. import android.content.Context;   
  100. import android.util.AttributeSet;   
  101. import android.util.Log;   
  102. import android.view.MotionEvent;   
  103. import android.widget.TextView;   
  104.   
  105. public class MyTextView extends TextView {   
  106.   
  107.     private final String TAG = "MyTextView";   
  108.   
  109.     public MyTextView(Context context, AttributeSet attrs) {     
  110.         super(context, attrs);     
  111.     }   
  112.   
  113.     @Override  
  114.     public boolean dispatchTouchEvent(MotionEvent ev) {   
  115.         int action = ev.getAction();   
  116.   
  117.         switch (action) {     
  118.         case MotionEvent.ACTION_DOWN:     
  119.             Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN"); 
  120.             break;     
  121.         case MotionEvent.ACTION_MOVE:     
  122.             Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE"); 
  123.             break;     
  124.         case MotionEvent.ACTION_UP:     
  125.             Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");     
  126.             break;     
  127.         case MotionEvent.ACTION_CANCEL:     
  128.             Log.d(TAG, "onTouchEvent action:ACTION_CANCEL");     
  129.             break;     
  130.         } 
  131.   
  132.         return super.dispatchTouchEvent(ev);   
  133.     }   
  134.   
  135.     @Override  
  136.     public boolean onTouchEvent(MotionEvent ev) {     
  137.         int action = ev.getAction();   
  138.   
  139.         switch (action) {     
  140.         case MotionEvent.ACTION_DOWN:     
  141.             Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");     
  142.             break;     
  143.         case MotionEvent.ACTION_MOVE:     
  144.             Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");     
  145.             break;     
  146.         case MotionEvent.ACTION_UP:     
  147.             Log.d(TAG, "---onTouchEvent action:ACTION_UP");     
  148.             break;     
  149.         case MotionEvent.ACTION_CANCEL:     
  150.             Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");     
  151.             break;     
  152.         }   
  153.   
  154.         return true;     
  155.     }     
  156. }  

       为了指代方便,下面将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 Touch事件原理加实例分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇NGUI系列教程三友盟+《小程序用户增长白皮书》:从五个角度入手分析小程序数据下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

android 开发 实现一个自定义布局的AlertDialog对话框

   对话框有很多实现方法,最常见的是在一个点击事件中代码直接写出对话框。如下: package com.example.lenovo.mydemo2; import android.content.DialogInterface; import android.support.v7.app.AlertDialog; import android.sup...

Android 4.0 SDK的离线方式安装(转)

转自:http://networking.ctocio.com.cn/110/12195610.shtml  作 为一个IT技术人员,迫不及待地就奔向了http://developer.android.com去看看有没有新的SDK公布出来,当时是上午,没见到 有更新,心想一定是若干天后才会发布。没想到同事下午告诉我,新版的SDK已经发布了。当时是临下班,...

Android的两种事件处理机制

UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理。 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事件监听器;对于基于回调的事件处理而言,主要做法是重写Android组件特定的回调函数,Android大部分界面组件都提供了事件响应的回调函数,我们主要重写它们...

Android ROM开发ubuntu下编译CyanogenMod生成SDK

由于CM2.3.7存在某些问题,所以如果需要使用稳定版本的CyanogenMod 2.3.4编译并且相应的vendor文件的话,可以到我的网盘中下载。 vendor下载地址:http://115.com/file/dpi59mxv 在开发定制ROM的时候经常会在源码中添加自定义的SDK,比如小米的MIUI里很多添加进来的功能在编码的时候都是使用自定义的方法...

android自定义控件及自定义组合控件

一、构建自定义控件 构建自定义组件 Android中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button)、文本框(TextView),可编辑文本框(EditText),列表框(ListView),复选框(CheckBox),单选框(RadioButton),滚动条(Gallery),微调器(Spinner), 等等,还有一些比较先...

android网络交互之DNS优化知识整理

android网络交互之DNS优化知识整理 之前的工作中,经常会遇到DNS解析出问题导致网络交互的操作无法正常进行。 UnknownHostException 在很多的移动开发过程中,与服务端的交互的url通常是包含域名的。而在实际的网络交互的过程中,第一步就需要对域名进行dns解析。 复杂的网络环境里面,dns解析会耗费很长的时间、甚至是解析失败。这是经...