最近学习 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事件传递机制demo代码”着重于ViewGroup的事件处理流程,通过`testTouchEvent`这个文件,我们可以深入理解Android中的触摸事件(TouchEvent)如何在组件层次间传递。 Android事件传递主要分为三...
首先,我们要理解Android事件的产生过程。当用户与设备交互,如点击屏幕或按下物理按键时,硬件会生成相应的事件,这些事件由Android系统的输入系统捕获,并转化为软件可处理的Event对象。Event对象包含了事件类型、...
在Android开发中,事件传递和处理机制是相当关键的一个部分,尤其对于用户界面的交互有着决定性的影响。本文主要探讨了Android系统如何处理触摸事件,通过拟人化的比喻来解释事件传递的流程,并通过实际代码示例进行...
- 使用Log工具记录事件的传递路径和处理结果,有助于快速定位问题。 #### 五、总结 通过本篇文章的详细介绍,我们对Android事件分发机制有了更深刻的理解。掌握了事件分发的基本原理后,开发者可以根据实际需求...
通过这个Demo,开发者可以深入理解Android事件分发的细节,比如点击事件、滑动事件如何在View和ViewGroup之间传递,以及如何利用`onInterceptTouchEvent()`实现自定义的事件处理逻辑,如自定义滚动效果或触摸事件的...
首先,我们要理解Android事件分发的基本流程,它分为三个阶段:`dispatchTouchEvent()`, `onInterceptTouchEvent()`, 和 `onTouchEvent()`。这三者构成了一个自顶向下的事件传递链。 1. **dispatchTouchEvent()**:...
总结,Android事件处理机制是构建用户友好、响应迅速的应用程序的基础。理解和熟练掌握事件冒泡、监听器以及消息队列的使用,能帮助开发者更好地设计和实现应用程序的交互逻辑。在实际开发中,灵活运用这些机制,...
可能的动作包括将事件分发到对应的输入事件处理器,比如触摸事件会传递给触摸事件处理器,按键事件会传递给键盘事件处理器。处理完事件后,可能会触发UI的更新或应用程序的相应动作。 总的来说,Android的事件驱动...
总的来说,理解Android中的View事件传递、事件消费以及触摸事件和点击事件的处理是优化用户体验和编写高效UI代码的关键。开发者需要根据应用的需求,灵活运用这些机制来实现各种交互效果。在实际编码过程中,不断...
在Android开发中,事件响应是用户与应用交互的关键部分,理解和掌握不同的事件处理方式对于创建高效、用户体验良好的应用至关重要。本教程"008_android 之 常见事件响应的实现方式对比"深入探讨了Android中几种常见...
Parcelable是Android特有的序列化方式,比Serializable更高效,适用于频繁的数据交换和需要快速序列化的场景。实现Parcelable接口需要编写更多的代码,但它能提供更高的性能。以下是使用Parcelable的例子: ```java...
总结起来,Android事件响应机制是构建用户交互界面的关键,理解并掌握这一机制能够帮助开发者设计出更加灵活和响应迅速的用户界面。通过合理地利用事件分发、拦截以及消费,可以实现丰富的交互功能,提升用户体验。...
在Android开发中,触屏事件处理是用户交互的核心部分,涉及到Activity、View和ViewGroup这三个关键组件。本文将深入探讨这些组件在触屏...通过熟练掌握这些知识,开发者能够创建出更加直观、响应迅速的Android应用。
在Android开发中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与其他语言(如C/C++)编写的代码...理解并熟练掌握JNI的使用,能够帮助开发者充分利用Android系统的底层能力,提升应用的性能和功能。
- **ACTION_CANCEL**:当用户的手指离开屏幕但事件未结束时(例如,快速滑动导致Scroller滚动),系统会发送ACTION_CANCEL事件,通知当前处理事件的View事件已取消。 了解并熟练运用Android事件分发机制,可以帮助...
源码分析是理解Android消息传递机制的关键。通过查看这些组件的源代码,我们可以了解到它们的工作原理和内部实现细节。例如,Looper的`loop()`方法是如何不断检查MessageQueue并调用Handler的,以及Message是如何被...
理解并熟练掌握Android的事件分发机制对于开发高效、响应迅速的应用至关重要,因为它决定了用户界面的交互体验。在设计复杂的布局和处理多视图交互时,合理利用事件分发机制能够帮助开发者解决很多问题,如滚动冲突...
《深入理解Android Wi-Fi、NFC和GPS卷》是由邓凡平编著的一本专业书籍,专注于探讨Android操作系统中三个核心的无线通信技术:Wi-Fi、NFC(近场通信)和GPS(全球定位系统)。这本书是中文版,旨在帮助读者深入理解...
首先,理解Android事件处理机制是必要的。在Android中,用户对UI的操作(如点击按钮)会触发一系列的事件,这些事件会通过事件传递链(Event Dispatching Chain)从视图树(View Hierarchy)顶部向下传递。默认情况...