Android Touch事件分发机制总结

来源:互联网 发布:切换网络的软件 编辑:程序博客网 时间:2024/05/16 06:40

虽然时常写自定义控件,但对Touch事件分发机制只是简单的理解,这次深入研究了它。网上很多这种文章都介绍得太简单,甚至错误。最近也研究了NestedScrolling,顺便说句,传统的Touch机制也能将事件回传给父Layout,有些介绍NestedScrolling的文章说传统的Touch机制不可以,这是错误的。

要点都在下面的注释里:

MyLinearLayout.java

package com.customview;import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; /** * 一、dispatchTouchEvent  * 1、return super.dispatchTouchEvent(event);  * dispatchTouchEvent会处理ACTION_DOWN,然后分给onInterceptTouchEvent * 是否处理余下的事件ACTION_MOVE和ACTION_UP,看onInterceptTouchEvent和onTouchEvent *  * (1)onInterceptTouchEvent * onInterceptTouchEvent会处理ACTION_DOWN * 是否处理余下的事件,看自己和onTouchEvent *  * ——false,与super.onInterceptTouchEvent(event)等同, * 不拦截,会处理余下的事件,然后分发事件给子View,不会给onTouchEvent *  * ——true,拦截,不分发事件给子View,给onTouchEvent(也即只交事件给自己),是否处理余下事件看onTouchEvent *  *  * (2)onTouchEvent * ——false,只会处理ACTION_DOWN * ——true,与super.onTouchEvent(event)几乎等同,会处理完整事件 *  *  * 处理完整的ACTION事件按此顺序(如果都处理的话):ACTION_DOWN——>ACTION_MOVE(一个或多个)——>ACTION_UP * 处理ACTION事件的方法按此顺序(如果都处理的话): * dispatchTouchEvent——>onInterceptTouchEvent(return false)——>子View *                                              (return true)——>onTouchEvent *  *  * 2、return true * dispatchTouchEvent会处理完整事件,不会给onInterceptTouchEvent和onTouchEvent,更不会给子View *  * 3、return false * dispatchTouchEvent只会处理ACTION_DOWN,不会给onInterceptTouchEvent和onTouchEvent,更不会给子View *  *  *  */public class MyLinearLayout extends LinearLayout {     private final String TAG = "MyLinearLayout";      public MyLinearLayout(Context context, AttributeSet attrs) {         super(context, attrs);     }     @Override     public boolean dispatchTouchEvent(MotionEvent event) {         switch (event.getAction()) {          case MotionEvent.ACTION_DOWN:             Log.e(TAG, "dispatchTouchEvent action:ACTION_DOWN");             break;         case MotionEvent.ACTION_MOVE:             Log.e(TAG, "dispatchTouchEvent action:ACTION_MOVE");             break;         case MotionEvent.ACTION_UP:             Log.e(TAG, "dispatchTouchEvent action:ACTION_UP");             break;         }         return super.dispatchTouchEvent(event);//        return true;//        return false;    }      @Override     public boolean onInterceptTouchEvent(MotionEvent event) {     switch (event.getAction()) {         case MotionEvent.ACTION_DOWN:             Log.e(TAG, "onInterceptTouchEvent action:ACTION_DOWN");             break;         case MotionEvent.ACTION_MOVE:             Log.e(TAG, "onInterceptTouchEvent action:ACTION_MOVE");             break;         case MotionEvent.ACTION_UP:             Log.e(TAG, "onInterceptTouchEvent action:ACTION_UP");             break;         }     return super.onInterceptTouchEvent(event);//        return true; //    return false;    }      @Override     public boolean onTouchEvent(MotionEvent event) {         switch (event.getAction()) {         case MotionEvent.ACTION_DOWN:             Log.e(TAG, "---onTouchEvent action:ACTION_DOWN");             break;         case MotionEvent.ACTION_MOVE:             Log.e(TAG, "---onTouchEvent action:ACTION_MOVE");             break;         case MotionEvent.ACTION_UP:             Log.e(TAG, "---onTouchEvent action:ACTION_UP");             break;         }         return true;//        return super.onTouchEvent(event);//        return false;     }  } 

MyTextView.java

package com.customview;import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; /** * 一、dispatchTouchEvent  * 1、return super.dispatchTouchEvent(event);  * dispatchTouchEvent会处理ACTION_DOWN,然后分给onTouchEvent * 是否处理余下的事件ACTION_MOVE和ACTION_UP,看onTouchEvent *  * (1)onTouchEvent * ——false,与super.onTouchEvent(event)几乎等同,只会处理ACTION_DOWN,然后会回给父Layout作处理: *<1> 如果父的onTouchEvent是return true或者super.onTouchEvent(event), *则父的onTouchEvent先处理一下ACTION_DOWN,然后由父的dispatchTouchEvent和onTouchEvent处理ACTION_MOVE和ACTION_UP *<2> 如果父的onTouchEvent是return false *则父的onTouchEvent只会处理ACTION_DOWN,余下事件不作处理 *  * ——true,会处理完整事件,不回给父Layout *  * 2、return true * dispatchTouchEvent会处理完整事件,不会给onTouchEvent,也不回给父Layout *  * 3、return false * dispatchTouchEvent只会处理ACTION_DOWN,不会给onTouchEvent,然后会回给父Layout作处理: *<1> 如果父的onTouchEvent是return true *则父的onTouchEvent先处理一下ACTION_DOWN,然后由父的dispatchTouchEvent和onTouchEvent处理ACTION_MOVE和ACTION_UP *<2> 如果父的onTouchEvent是return false或者super.onTouchEvent(event), *则父的onTouchEvent只会处理ACTION_DOWN,余下事件不作处理 *  *  */public class MyTextView extends TextView {      private final String TAG = "MyTextView";      public MyTextView(Context context, AttributeSet attrs) {         super(context, attrs);     }      @Override     public boolean dispatchTouchEvent(MotionEvent event) {         switch (event.getAction()) {         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;         }         return super.dispatchTouchEvent(event);//        return false;//        return true;    }      @Override public boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {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;}//return true;return false;//return super.onTouchEvent(event);    }  }  

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <com.customview.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" >            <com.customview.MyTextView               android:id="@+id/tv"               android:layout_width="200px"               android:layout_height="200px"               android:background="#00ffee"               android:gravity="center"               android:text="点我"               android:textColor="#0000FF"               android:textSize="30sp" /> </com.customview.MyLinearLayout>  


0 0