• Android Touch事件原理加实例分析


          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。

  • 相关阅读:
    K8S实战(十七)| 通过 StorageClass 实现动态卷供应
    K8S实战(十六)| 持久化存储卷
    K8S实战(十五)| 存储卷概念
    K8S实战(十四)| ConfigMap 对象
    K8S实战(十三)| Secret 对象
    K8S实战(十二)| 为 Ingress 以及后端 Nginx 增加证书
    批量删除git 本地分支、远程分支、tag
    React 页面间传值的个人总结
    搭建一个属于自己的webpack config(-)
    HTTP 2 新特性
  • 原文地址:https://www.cnblogs.com/xiaochao1234/p/3831917.html
Copyright © 2020-2023  润新知