android菜鸟之路-事件分发机制总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android菜鸟之路-事件分发机制总结相关的知识,希望对你有一定的参考价值。

ViewGroup事件分发机制

自己定义一个LinearLayout,ImageView和Button,小二,上代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context=".MainActivity" >  
    <com.example.aaaaa.MyLinear
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#956456"
        >
        <com.example.aaaaa.MyImage  
        android:id="@+id/id_ll"  
        android:layout_width="150dp"  
        android:layout_height="150dp" 
        android:src="@drawable/ic_launcher"
        android:text="click me" />  
        <com.example.aaaaa.MyButton  
        android:id="@+id/id_btn"  
        android:layout_width="150dp"  
        android:layout_height="150dp" 
        android:src="@drawable/ic_launcher"
        android:text="click me" />  
    </com.example.aaaaa.MyLinear>
</LinearLayout> 

public class MyLinear extends LinearLayout{
	private static final String TAG =MyLinear.class.getSimpleName();

	public MyLinear(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyLinear(Context context) {
		super(context);
	}

	@Override  
	public boolean onTouchEvent(MotionEvent event)  
	{  
		int action = event.getAction();  

		switch (action)  
		{  
		case MotionEvent.ACTION_DOWN:  
			Log.e(TAG, "LinearLayout+onTouchEvent ACTION_DOWN");  
			break;  
		case MotionEvent.ACTION_MOVE:  
			Log.e(TAG, "LinearLayout+onTouchEvent ACTION_MOVE");  
			break;  
		case MotionEvent.ACTION_UP:  
			Log.e(TAG, "LinearLayout+onTouchEvent ACTION_UP");  
			break;  
		default:  
			break;  
		}  
		return super.onTouchEvent(event);  
	}  

	@Override  
	public boolean dispatchTouchEvent(MotionEvent event)  
	{  
		int action = event.getAction();  

		switch (action)  
		{  
		case MotionEvent.ACTION_DOWN:  
			Log.e(TAG, "LinearLayout+dispatchTouchEvent ACTION_DOWN");
			//			return true;
			break;  
		case MotionEvent.ACTION_MOVE:  
			Log.e(TAG, "LinearLayout+dispatchTouchEvent ACTION_MOVE");  
			break;  
		case MotionEvent.ACTION_UP:  
			Log.e(TAG, "LinearLayout+dispatchTouchEvent ACTION_UP");  
			break;  

		default:  
			break;  
		}  
		boolean a=super.dispatchTouchEvent(event);
//		Log.e(TAG, "LinearLayout:a="+a); 
		return a;  
	}  

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return super.onInterceptTouchEvent(ev);
	}
}

public class MyButton extends Button  
{  
	private static final String TAG = MyButton.class.getSimpleName();  
	public MyButton(Context context, AttributeSet attrs)  
	{  
		super(context, attrs);  
	}  

	@Override  
	public boolean onTouchEvent(MotionEvent event)  
	{  
		int action = event.getAction();  

		switch (action)  
		{  
		case MotionEvent.ACTION_DOWN:  
			Log.e(TAG, "button+onTouchEvent ACTION_DOWN");  
			break;  
		case MotionEvent.ACTION_MOVE:  
			Log.e(TAG, "button+onTouchEvent ACTION_MOVE");  
			break;  
		case MotionEvent.ACTION_UP:  
			Log.e(TAG, "button+onTouchEvent ACTION_UP");  
			break;  
		default:  
			break;  
		}  
		return super.onTouchEvent(event);  
	}  

	@Override  
	public boolean dispatchTouchEvent(MotionEvent event)  
	{  
		int action = event.getAction();  

		switch (action)  
		{  
		case MotionEvent.ACTION_DOWN:  
			Log.e(TAG, "button+dispatchTouchEvent ACTION_DOWN");
//			return true;
			break;  
		case MotionEvent.ACTION_MOVE:  
			Log.e(TAG, "button+dispatchTouchEvent ACTION_MOVE");  
			break;  
		case MotionEvent.ACTION_UP:  
			Log.e(TAG, "button+dispatchTouchEvent ACTION_UP");  
			break;  

		default:  
			break;  
		}  
		boolean a=super.dispatchTouchEvent(event);
//		Log.e(TAG, "button:a="+a); 
		return a;
//		return super.dispatchTouchEvent(event);  
	}  
}

public class MyImage extends ImageView  
{  
	private static final String TAG = MyImage.class.getSimpleName();  

	public MyImage(Context context, AttributeSet attrs)  
	{  
		super(context, attrs);  
	}  

	@Override  
	public boolean onTouchEvent(MotionEvent event)  
	{  
		int action = event.getAction();  

		switch (action)  
		{  
		case MotionEvent.ACTION_DOWN:  
			Log.e(TAG, "onTouchEvent ACTION_DOWN");  
			break;  
		case MotionEvent.ACTION_MOVE:  
			Log.e(TAG, "onTouchEvent ACTION_MOVE");  
			break;  
		case MotionEvent.ACTION_UP:  
			Log.e(TAG, "onTouchEvent ACTION_UP");  
			break;  
		default:  
			break;  
		}  
		return super.onTouchEvent(event);  
	}  

	@Override  
	public boolean dispatchTouchEvent(MotionEvent event)  
	{  
		int action = event.getAction();  

		switch (action)  
		{  
		case MotionEvent.ACTION_DOWN:  
			Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
			return false;
//			break;  
		case MotionEvent.ACTION_MOVE:  
			Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");  
			break;  
		case MotionEvent.ACTION_UP:  
			Log.e(TAG, "dispatchTouchEvent ACTION_UP");  
			break;  

		default:  
			break;  
		}  
		boolean a=super.dispatchTouchEvent(event);
//		Log.e(TAG, "ImageView:a="+a); 
		return a;
//		return super.dispatchTouchEvent(event);  
	}  
} 
public class MainActivity extends Activity  
{  
	protected static final String TAG = "MainActivity";  
	private MyImage imageView;
	private MyButton button;
	@Override  
	protected void onCreate(Bundle savedInstanceState)  
	{  
		super.onCreate(savedInstanceState);  
		setContentView(R.layout.activity_main);  
		imageView=(MyImage) findViewById(R.id.id_ll);
		button=(MyButton) findViewById(R.id.id_btn);
		imageView.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Log.e(TAG, "setOnClickListener000");
			}
		});
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Log.e(TAG, "button+setOnClickListener000");
			}
		});
		
		final LinearLayout ll = (LinearLayout) findViewById(R.id.linear);
//		ll.setOnClickListener(new OnClickListener() {
//			@Override
//			public void onClick(View v) {
//				Log.e(TAG, "LinearLayout+setOnClickListener000");
//			}
//		});
//
		ll.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				int action = event.getAction();  

				switch (action)  
				{  
				case MotionEvent.ACTION_DOWN:  
					Log.e(TAG, "LinearLayout+onTouch ACTION_DOWN");
					Log.e(TAG, "LinearLayout+000"+ll.isClickable());
//					return false;
					break;  
				case MotionEvent.ACTION_MOVE:  
					Log.e(TAG, "LinearLayout+onTouch ACTION_MOVE");  
					Log.e(TAG, "LinearLayout+000"+ll.isClickable());
//					return false;
					break;  
				case MotionEvent.ACTION_UP:  
					Log.e(TAG, "LinearLayout+onTouch ACTION_UP"); 
					Log.e(TAG, "LinearLayout+000"+ll.isClickable());
					break;  
				default:  
					break;  
				}  

				return true;  
			}  
		});
		
		
		imageView.setOnTouchListener(new OnTouchListener()  
		{  
			@Override  
			public boolean onTouch(View v, MotionEvent event)  
			{  
				int action = event.getAction();  

				switch (action)  
				{  
				case MotionEvent.ACTION_DOWN:  
					Log.e(TAG, "onTouch ACTION_DOWN");
					Log.e(TAG, "000"+imageView.isClickable());
//					return false;
					break;  
				case MotionEvent.ACTION_MOVE:  
					Log.e(TAG, "onTouch ACTION_MOVE");  
					Log.e(TAG, "000"+imageView.isClickable());
//					return false;
					break;  
				case MotionEvent.ACTION_UP:  
					Log.e(TAG, "onTouch ACTION_UP"); 
					Log.e(TAG, "000"+imageView.isClickable());
					break;  
				default:  
					break;  
				}  

				return true;  
			}  
		});  
		
		button.setOnTouchListener(new OnTouchListener()  
		{  
			@Override  
			public boolean onTouch(View v, MotionEvent event)  
			{  
				int action = event.getAction();  
				
				switch (action)  
				{  
				case MotionEvent.ACTION_DOWN:  
					Log.e(TAG, "button+onTouch ACTION_DOWN");
//					Log.e(TAG, "button+000"+button.isClickable());
//					return false;
					break;  
				case MotionEvent.ACTION_MOVE:  
					Log.e(TAG, "button+onTouch ACTION_MOVE");  
//					Log.e(TAG, "button+000"+button.isClickable());
//					return false;
					break;  
				case MotionEvent.ACTION_UP:  
					Log.e(TAG, "button+onTouch ACTION_UP"); 
//					Log.e(TAG, "button+000"+button.isClickable());
					break;  
				default:  
					break;  
				}  
				
				return false;  
			}  
		});  
	}  
}
代码都很easy,基本都是信息打印,OK。那我们開始測试吧
假设轻轻点击自己定义Button,并手抖一下。会打印出什么信息呢?让我们来look一look
技术分享
假设轻轻点击自己定义ImageView。并手抖一下,又会打印出什么信息呢?让我们来look一look
技术分享
为什么会这样呢?
由于我在自己定义ImageView的dispatchTouchEvent方法里的MotionEvent.ACTION_DOWN事件推断里返回了false,还记得我们上一篇结尾说的么?

***切记,仅仅有每一个ACTION_DOWN。ACTION_MOVE,ACTION_UP事件相应的dispatchTouchEvent方法都返回true。才干依次往后运行,就是说假设dispatchTouchEvent方法里此时的event.getAction()==ACTION_DOWN,  你返回了false,那么后面的dispatchTouchEvent方法都不会运行(说白了,每一个动作事件都会运行一次dispatchTouchEvent,运行ACTION_DOWN的时候返回了false,后面一系列其他的action就不会再得到运行了,也就是ACTION_MOVE,ACTION_UP事件将不会得到运行。

到了这里我建议先结合两位大神的源代码看看吧


看完以后再看看这张图,是不是瞬间明确了
技术分享

实在想不明确的朋友能够把我上面的代码拷过去。依据自己的想法改一改,然后执行执行,非常快你就会豁然开朗


总结:当点击布局里的控件时。首先会调用ViewGroup的dispatchTouchEvent方法,假设onInterceptTouchEvent方法返回的是false,那么就会调用子View的dispatchTouchEvent方法(这种方法返回true就表示子View把事件消费掉了)。假设onInterceptTouchEvent方法返回的是true,那么就会调用ViewGroup的父类(也就是View)的dispatchTouchEvent方法,接下来调用布局的onTouch、onTouchEvent方法。

能够这么记着:布局把事情交给子View处理,子View的dispatchTouchEvent方法返回true表示它把事情干完了,布局就不处理了。假设返回false,就是子View没处理完,那么布局就要处理了。

(再回过头去看  ***切记那里,明确了么?朋友。假设一个事件你返回了false,后面的就是布局在处理了,所以子View后面的事件不会运行)

好吧。我承认这篇写的有点水,事实上主要是提供代码给大家执行着试试。自己动手。丰衣足食。






















以上是关于android菜鸟之路-事件分发机制总结的主要内容,如果未能解决你的问题,请参考以下文章

Android触摸事件分发机制总结

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

Android View框架总结KeyEvent事件分发机制

Android 事件分发机制分析及源码详解

Android 事件分发机制分析及源码详解

Android :安卓学习笔记之 事件分发机制 的简单理解和使用