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