最近学习 Android,感觉Android事件传递机制很有意思,搞懂这个基础知识点是必须的,于是收集资料,做个Demo加深印象,记录之。
Demo比较简单,一个ViewGroup上放置一个按钮。
自定义VieGroup继承自LinearLayout:
package com.example.mydispatchtouchevent; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.LinearLayout; public class MyView extends LinearLayout implements OnClickListener,OnTouchListener{ public MyView(Context context) { super(context); setOnClickListener(this); } @Override public void onClick(View v) { Log.i("TAG","viewgroup_doClick"); } @Override public boolean onTouch(View v, MotionEvent event) { Log.i("TAG","viewgroup_onTouch="+event.getAction()); return false; } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("TAG","viewgroup_onTouchEvent="+event.getAction()); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i("TAG","viewgroup_dispatchTouchEvent="+event.getAction()); return super.dispatchTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("TAG","viewgroup_onInterceptTouchEvent"); return super.onInterceptTouchEvent(ev); } }
自定义Button:
package com.example.mydispatchtouchevent; import android.content.Context; import android.util.Log; import android.widget.Button; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.View.OnClickListener; public class MyButton extends Button implements OnTouchListener, OnClickListener { public MyButton(Context context) { super(context); setOnTouchListener(this); setOnClickListener(this); this.setText("测试"); } @Override public boolean onTouch(View v, MotionEvent event) { Log.i("TAG", "button_onTouch=" + event.getAction()); return false; } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("TAG", "button_onTouchEvent=" + event.getAction()); return super.onTouchEvent(event); //return false; } @Override public void onClick(View v) { Log.i("TAG", "button_doClick"); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i("TAG", "button_dispatchTouchEvent=" + event.getAction()); return super.dispatchTouchEvent(event); } }
Activity:
package com.example.mydispatchtouchevent; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; public class MainActivity extends Activity { Button myBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewGroup viewGroup = new MyView(this); Button button = new MyButton(this); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); button.setLayoutParams(params); viewGroup.addView(button); setContentView(viewGroup); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("TAG", "Activity_onTouchEvent=" + event.getAction() + " / " + "event=" + event.hashCode()); return super.onTouchEvent(event); } }
给自定义ViewGroup实现dispatchTouchEvent,onInterceptTouchEvent,onTouch,onTouchEvent,onClick;Button实现dispatchTouchEvent,onTouch,onTouchEvent,onClick,Activity上实现onTouchEvent。
点击按钮,运行结果:
02-16 02:45:18.209: I/TAG(2535): viewgroup_dispatchTouchEvent=0 02-16 02:45:18.209: I/TAG(2535): viewgroup_onInterceptTouchEvent 02-16 02:45:18.209: I/TAG(2535): button_dispatchTouchEvent=0 02-16 02:45:18.209: I/TAG(2535): button_onTouch=0 02-16 02:45:18.209: I/TAG(2535): button_onTouchEvent=0 02-16 02:45:18.313: I/TAG(2535): viewgroup_dispatchTouchEvent=1 02-16 02:45:18.313: I/TAG(2535): viewgroup_onInterceptTouchEvent 02-16 02:45:18.313: I/TAG(2535): button_dispatchTouchEvent=1 02-16 02:45:18.313: I/TAG(2535): button_onTouch=1 02-16 02:45:18.313: I/TAG(2535): button_onTouchEvent=1 02-16 02:45:18.321: I/TAG(2535): button_doClick
顺序一目了然,viewgroup_dispatchTouchEvent先得到event,然后是viewgroup_onInterceptTouchEvent,接下来就把event转交给button,ACTION_DOWN和ACTION_UP各走一遍后,最后执行button_doClick。
这些方法的游戏规则是:如果返回true,event被消化了,不再传递;如果返回false,event交给下一位继续。在button_onTouchEvent中返回了true,事件传递就到此为止,其中button_doClick是在button_onTouchEvent中调用。
button_onTouchEvent修改为:
@Override public boolean onTouchEvent(MotionEvent event) { Log.i("TAG", "button_onTouchEvent=" + event.getAction()); //return super.onTouchEvent(event); return false; }
点击按钮:
02-16 03:02:38.213: I/TAG(2582): viewgroup_dispatchTouchEvent=0 02-16 03:02:38.213: I/TAG(2582): viewgroup_onInterceptTouchEvent 02-16 03:02:38.213: I/TAG(2582): button_dispatchTouchEvent=0 02-16 03:02:38.213: I/TAG(2582): button_onTouch=0 02-16 03:02:38.213: I/TAG(2582): button_onTouchEvent=0 02-16 03:02:38.213: I/TAG(2582): viewgroup_onTouchEvent=0 02-16 03:02:38.317: I/TAG(2582): viewgroup_dispatchTouchEvent=1 02-16 03:02:38.317: I/TAG(2582): viewgroup_onTouchEvent=1 02-16 03:02:38.317: I/TAG(2582): viewgroup_doClick
这回button_onTouchEvent放水了,使得event继续往下“掉”,button_doClick不再执行,现在执行的是viewgroup_doClick。另外,发现button上只走了一遍ACTION_DOWN,ACTION_UP没它什么事,因为event已经不在button手中了(这么说比较形象)。
还没完,继续,viewgroup_onTouchEvent修改为:
@Override public boolean onTouchEvent(MotionEvent event) { Log.i("TAG","viewgroup_onTouchEvent="+event.getAction()); //return super.onTouchEvent(event); return false; }
现在由viewgroup_onTouchEvent接着放水,点击按钮运行下结果:
02-16 03:18:56.737: I/TAG(2631): viewgroup_dispatchTouchEvent=0 02-16 03:18:56.737: I/TAG(2631): viewgroup_onInterceptTouchEvent 02-16 03:18:56.737: I/TAG(2631): button_dispatchTouchEvent=0 02-16 03:18:56.737: I/TAG(2631): button_onTouch=0 02-16 03:18:56.737: I/TAG(2631): button_onTouchEvent=0 02-16 03:18:56.737: I/TAG(2631): viewgroup_onTouchEvent=0 02-16 03:18:56.737: I/TAG(2631): Activity_onTouchEvent=0 02-16 03:18:56.841: I/TAG(2631): Activity_onTouchEvent=1
现在终于轮到躺地板的Activity接到event了,过程参考上面,应该也比较好理解。
以下内容在stackOveflow找到,用来总结再合适不过了
How the Activity handles touch:
Activity.dispatchTouchEvent()
- Always first to be called
- Sends event to root view attached to Window
onTouchEvent()
- Called if no views consume the event
- Always last to be called
How the View handles touch:
View.dispatchTouchEvent()
- Sends event to listener first, if exists
View.OnTouchListener.onTouch()
- If not consumed, processes the touch itself
View.onTouchEvent()
How a ViewGroup handles touch:
ViewGroup.dispatchTouchEvent()
onInterceptTouchEvent()
- Check if it should supersede children
- Passes
ACTION_CANCEL
to active child- Return true once, consumes all subsequent events
- For each child view, in reverse order they were added
- If touch is relevant (inside view),
child.dispatchTouchEvent()
- If not handled by previous, dispatch to next view
- If no children handle event, listener gets a chance
OnTouchListener.onTouch()
- If no listener, or not handled
onTouchEvent()
- Intercepted events jump over child step
相关推荐
之前笔者其实已经写过事件分发机制的文章:[快速理解android事件传递拦截机制概念](http://blog.csdn.net/double2hao/article/details/51541061) 但是,现在看来其实更像是一篇知识概括,多出可能未讲清楚,于是打算...
Android View 事件传递与消费,用于view事件传递的理解。
Android事件传递机制,TouchEvent详解
简单的android事件传递demo,对touch事件分发进行测试
Android TouchEvent事件传递机制
android Touch事件传递机制的实例
android事件传递测试
含图!含图!含图!重要的事说三遍!看图解析Android点击事件传递,一目了然!
android ViewGroup 事件传递处理流程代码
次demo演示了android下事件的传递机制,读者看后一目了然。
这是一个关于事件拦截以及事件分发很好的例子,通过点击A,B,C,D ,查看log,可以清楚的看到事件传递过程
Android事件传递机制测试代码,博文:http://blog.csdn.net/yanzi1225627
android触摸事件传递机制图文详解,自认为最简略最完善的流程图!
Android onTouch事件传递机制
事件传递机制Demo
Android Touch事件传递机制解析
以后会按标准一个个的写完测试DEMO,一是自我学习,二是方便同样在学习的其他同学这是,本系列代码均来自《Android高级进阶》,经过测试可以运行,这是 第一章 Android 触摸事件传递机制 View的事件传递机制
android view事件传递分析
JavaScript调用Android方法,向Android方法传递json数据。
事件传递机制详解dome,博客地址讲解 http://www.cnblogs.com/ldq2016/p/5216489.html