Android关于Touch事件的dispatch、intercept以及onTouchEvent执行的理解

       对于dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent执行的顺序,及执行结果与返回值有什么关系一直很模糊,终于今天简单写了一个Demo进行测试,特此记录。

//main_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<com.wqy.view.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <com.wqy.view.MyTextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="测试触摸事件"
        android:textSize="18sp"/>

</com.wqy.view.MyLinearLayout>
LinearLayout和TextView是为了方便测试,自己写的,代码如下:

package com.wqy.view;

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 = "weiquanyun";
	
	public MyLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public MyLinearLayout(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch(ev.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"LinearLayout:dispatchTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"LinearLayout:dispatchTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"LinearLayout:dispatchTouchEvent-->UP");
			break;
		}
		return super.dispatchTouchEvent(ev);
	}

	//只有ViewGroup的子类才有此方法
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch(ev.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"LinearLayout:onInterceptTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"LinearLayout:onInterceptTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"LinearLayout:onInterceptTouchEvent-->UP");
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch(event.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"LinearLayout:onTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"LinearLayout:onTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"LinearLayout:onTouchEvent-->UP");
			break;
		}
		return super.onTouchEvent(event);
	}

}

package com.wqy.view;

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 = "weiquanyun";
	
	public MyTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public MyTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public MyTextView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch(ev.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"MyTextView:dispatchTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"MyTextView:dispatchTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"MyTextView:dispatchTouchEvent-->UP");
			break;
		}
		return super.dispatchTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch(event.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"MyTextView:onTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"MyTextView:onTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"MyTextView:onTouchEvent-->UP");
			break;
		}
		return super.onTouchEvent(event);
	}
}

package com.wqy.activity;

import com.wqy.testtouchevent.R;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;

public class MainActivity extends Activity {

	private final String TAG = "weiquanyun";
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_layout);
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch(ev.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"MainActivity:dispatchTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"MainActivity:dispatchTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"MainActivity:dispatchTouchEvent-->UP");
			break;
		}
		return true;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch(event.getAction()){
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG,"MainActivity:onTouchEvent-->DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			Log.d(TAG,"MainActivity:onTouchEvent-->MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.d(TAG,"MainActivity:onTouchEvent-->UP");
			break;
		}
		return super.onTouchEvent(event);
	}

}

在测试时,主要对返回值进行修改查看结果

1、所有的返回均为return super.xxxxTouchEvent(event);时:


















结果分析:可以看到MainActivity 的dispatchTouchEvent执行后就执行了MyLinearLayout的dispatchTouchEvent,之后是MyLinearLayout的onInterceptTouchEvent,再就是MyTextView的dispatchTouchEvent,和MyTextView的onTouchEvent。之前在我转的一片关于onTouch事件的博客中提到过:如果dispatchTouchEvent返回true,则交给这个view的onTouchEvent处理,否则交给这个view的onInterceptTouchEvent,所以return super.xxxTouchEvent(event)类似于return false,因此,在MyTextView的touch事件回依次向上传递到MainActivity中,随后的在移动和抬起事件中,MyTextView和MyLinearLayout将不会被触发,全部由MainActivity处理掉。

2、MainActivity dispatchTouchEvent返回true时,不管MainActivity的onTouchEvent返回何值,都是如下结果:




结果分析:跟api说明文档说明的一样,如果返回true或者false,就会在此方法中消耗掉触摸事件,不再传递

boolean com.wqy.activity.MainActivity.dispatchTouchEvent(MotionEvent ev)


Called to process touch screen events. You can override this to intercept all touch screen events before they are dispatched to the window. Be sure to call this implementation for touch screen events that should be handled normally.

Parameters:
ev The touch screen event.
Returns:
boolean Return true if this event was consumed.

但有点没明白,当返回false时MainActivity也没有分发事件

3、 MainActivity dispatchTouchEvent返回super.dispatchTouchEvent时,不管MainActivity的onTouchEvent返回何值,结果都与第一种情况一样。

4、MainActivity dispatchTouchEvent返回super.dispatchTouchEvent时,MyLinearLayout的dispatchTouchEvent返回false,结果如下:









可以看出来,MyLinearLayout并没有分发Touch事件。

5、MainActivity dispatchTouchEvent返回super.dispatchTouchEvent时,MyLinearLayout的dispatchTouchEvent返回true,结果如下:






6、MainActivity dispatchTouchEvent返回super.dispatchTouchEvent时,MyLinearLayout的dispatchTouchEvent返回super.dispatchTouchEventMyLinearLayout的onInterceptTouchEvent返回true时结果如下:









只有MyLinearLayout的onInterceptTouchEvent返回false和super.onInterceptTouchEvent(从源码中可以看到super.onInterceptTouchEvent正是返回false)时才会传递到MyTextView,也就是当onInterceptTouchEvent返回false时,该view不拦截触摸事件而是将其传递到子view:








7、如果MyTextView的dispatchTouchEvent返回了false则,MyTextView在执行ACTION_DOWN之后由于返回了false,就不在分发事件,结果为:














8、如果是MyTextView的dispatchTouchEvent返回了true,则就消耗该事件。















9、当MyTextView的dispatchTouchEvent返回super.dispatchTouchEvent时,才会继续分发,如果此时MyTextView的onTouchEvent返回true则就会在MyTextView的onTouchEvent中消耗掉触摸事件:













总结:从以上结果可以发现,dispatch只有在return super.dispatchTouchEvent(ev);时才能正常分发,而onInterceptTouchEvent返回false或者super.onInterceptTouchEvent时才能传给子view,onTouchEvent只有return true时才会消耗触摸事件,否则则向上传递,直到最上层的onTouchEvent或者在中间遇到了返回为true的onTouchEvent。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值