Android Touch事件分发机制总结

虽然时常写自定义控件,但对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>  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值