`
pjwqq
  • 浏览: 80822 次
社区版块
存档分类
最新评论

迅速理解Android事件传递

阅读更多

    最近学习 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,onClickButton实现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

 

 

1
0
分享到:
评论

相关推荐

    完全理解android事件分发机制

    之前笔者其实已经写过事件分发机制的文章:[快速理解android事件传递拦截机制概念](http://blog.csdn.net/double2hao/article/details/51541061) 但是,现在看来其实更像是一篇知识概括,多出可能未讲清楚,于是打算...

    android事件传递机制demo代码

    本示例代码“android事件传递机制demo代码”着重于ViewGroup的事件处理流程,通过`testTouchEvent`这个文件,我们可以深入理解Android中的触摸事件(TouchEvent)如何在组件层次间传递。 Android事件传递主要分为三...

    android事件分发机制

    首先,我们要理解Android事件的产生过程。当用户与设备交互,如点击屏幕或按下物理按键时,硬件会生成相应的事件,这些事件由Android系统的输入系统捕获,并转化为软件可处理的Event对象。Event对象包含了事件类型、...

    老生常谈android中的事件传递和处理机制

    在Android开发中,事件传递和处理机制是相当关键的一个部分,尤其对于用户界面的交互有着决定性的影响。本文主要探讨了Android系统如何处理触摸事件,通过拟人化的比喻来解释事件传递的流程,并通过实际代码示例进行...

    Android 事件分发机制视频讲解

    - 使用Log工具记录事件的传递路径和处理结果,有助于快速定位问题。 #### 五、总结 通过本篇文章的详细介绍,我们对Android事件分发机制有了更深刻的理解。掌握了事件分发的基本原理后,开发者可以根据实际需求...

    Android事件分发测试Demo

    通过这个Demo,开发者可以深入理解Android事件分发的细节,比如点击事件、滑动事件如何在View和ViewGroup之间传递,以及如何利用`onInterceptTouchEvent()`实现自定义的事件处理逻辑,如自定义滚动效果或触摸事件的...

    Android事件分发机制演示demo

    首先,我们要理解Android事件分发的基本流程,它分为三个阶段:`dispatchTouchEvent()`, `onInterceptTouchEvent()`, 和 `onTouchEvent()`。这三者构成了一个自顶向下的事件传递链。 1. **dispatchTouchEvent()**:...

    Android 事件处理机制

    总结,Android事件处理机制是构建用户友好、响应迅速的应用程序的基础。理解和熟练掌握事件冒泡、监听器以及消息队列的使用,能帮助开发者更好地设计和实现应用程序的交互逻辑。在实际开发中,灵活运用这些机制,...

    Android 事件驱动流程

    可能的动作包括将事件分发到对应的输入事件处理器,比如触摸事件会传递给触摸事件处理器,按键事件会传递给键盘事件处理器。处理完事件后,可能会触发UI的更新或应用程序的相应动作。 总的来说,Android的事件驱动...

    Android 中触摸事件与点击事件分析

    总的来说,理解Android中的View事件传递、事件消费以及触摸事件和点击事件的处理是优化用户体验和编写高效UI代码的关键。开发者需要根据应用的需求,灵活运用这些机制来实现各种交互效果。在实际编码过程中,不断...

    008_android 之 常见事件响应的实现方式对比

    在Android开发中,事件响应是用户与应用交互的关键部分,理解和掌握不同的事件处理方式对于创建高效、用户体验良好的应用至关重要。本教程"008_android 之 常见事件响应的实现方式对比"深入探讨了Android中几种常见...

    Android Intent传递对象

    Parcelable是Android特有的序列化方式,比Serializable更高效,适用于频繁的数据交换和需要快速序列化的场景。实现Parcelable接口需要编写更多的代码,但它能提供更高的性能。以下是使用Parcelable的例子: ```java...

    028-Android事件响应机制

    总结起来,Android事件响应机制是构建用户交互界面的关键,理解并掌握这一机制能够帮助开发者设计出更加灵活和响应迅速的用户界面。通过合理地利用事件分发、拦截以及消费,可以实现丰富的交互功能,提升用户体验。...

    android触屏事件之activity,view,viewgroup

    在Android开发中,触屏事件处理是用户交互的核心部分,涉及到Activity、View和ViewGroup这三个关键组件。本文将深入探讨这些组件在触屏...通过熟练掌握这些知识,开发者能够创建出更加直观、响应迅速的Android应用。

    android事件分发

    - **ACTION_CANCEL**:当用户的手指离开屏幕但事件未结束时(例如,快速滑动导致Scroller滚动),系统会发送ACTION_CANCEL事件,通知当前处理事件的View事件已取消。 了解并熟练运用Android事件分发机制,可以帮助...

    〔原创〕Android消息传递机制(总结)

    源码分析是理解Android消息传递机制的关键。通过查看这些组件的源代码,我们可以了解到它们的工作原理和内部实现细节。例如,Looper的`loop()`方法是如何不断检查MessageQueue并调用Handler的,以及Message是如何被...

    Android 事件分发机制

    理解并熟练掌握Android的事件分发机制对于开发高效、响应迅速的应用至关重要,因为它决定了用户界面的交互体验。在设计复杂的布局和处理多视图交互时,合理利用事件分发机制能够帮助开发者解决很多问题,如滚动冲突...

    《深入理解Android Wi-Fi、NFC和GPS卷》(邓凡平)

    《深入理解Android Wi-Fi、NFC和GPS卷》是由邓凡平编著的一本专业书籍,专注于探讨Android操作系统中三个核心的无线通信技术:Wi-Fi、NFC(近场通信)和GPS(全球定位系统)。这本书是中文版,旨在帮助读者深入理解...

    Android-DBClickBlocker单击事件防止变成双击事件

    首先,理解Android事件处理机制是必要的。在Android中,用户对UI的操作(如点击按钮)会触发一系列的事件,这些事件会通过事件传递链(Event Dispatching Chain)从视图树(View Hierarchy)顶部向下传递。默认情况...

    android 事件的处理(2)

    在Android的输入框架中,事件首先由EventHub捕获,然后传递到InputReader进行处理。当事件被获取到后,InputReader会调用`processEventsLocked`方法来进一步处理这些事件。这个方法会根据事件类型进行区分,主要处理...

Global site tag (gtag.js) - Google Analytics