Android事件传递机制(三)deprecated

main.xml如下:

<!-- 自定义布局中,放置一个自定义控件 -->
<cn.c.MyFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <cn.c.MyLinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
		   <cn.c.MyButton
		     android:layout_width="200dip"
		     android:layout_height="200dip"
		     android:text="自定义Button"
		     android:textColor="@android:color/black"
		   />
    </cn.c.MyLinearLayout>
</cn.c.MyFrameLayout>

 

MainActivity如下:

package cn.c;
import android.os.Bundle;
import android.app.Activity;
import android.view.MotionEvent;
//Demo描述:
//分析Android事件分发和处理机制

//总结:
//1 ViewGroup继承自View
//  事件的传递方向为:从最外层(Activity)传递至最内层(某个View)
//  事件的消费方向为:从最内层(某个View)传递至最外层(Activity)
//  该两个方向是相反的
//2 ViewGroup中事件处理的流程是:
//  dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent
//  View中事件处理的流程是:
//  dispatchTouchEvent->onTouchEvent
//3 ViewGroup中onInterceptTouchEvent默认值是false
//  表示未拦截
//  ViewGroup中onTouchEvent默认值是false
//  表示未消费
//  View中onTouchEvent返回默认值是true
//  表示已消费

//测试方法:
//在Android事件传递机制(二)的基础上继续验证和实践中提到的原理

//测试步骤:
//将MyFrameLayout的dispatchTouchEvent返回false即不分发

//测试结果:
//05-13 10:42:32.749: I/System.out(19671): ===> MainActivity 中调用 onCreate()
//05-13 10:42:32.749: I/System.out(19671): --------------------------------------------------
//05-13 10:42:35.178: I/System.out(19671): ===> MainActivity 中调用 dispatchTouchEvent()
//05-13 10:42:35.178: I/System.out(19671): ===> super.dispatchTouchEvent()默认返回true
//05-13 10:42:35.178: I/System.out(19671): --------------------------------------------------
//05-13 10:42:35.178: I/System.out(19671): ===> MainActivity 中调用 onUserInteraction()
//05-13 10:42:35.178: I/System.out(19671): --------------------------------------------------
//05-13 10:42:35.178: I/System.out(19671): 外层MyFrameLayout 中调用  dispatchTouchEvent()
//05-13 10:42:35.178: I/System.out(19671): super.dispatchTouchEvent()默认返回true 表示继续分发
//05-13 10:42:35.178: I/System.out(19671): --------------------------------------------------
//05-13 10:42:35.178: I/System.out(19671): ===> MainActivity 中调用  onTouchEvent()--->ACTION_DOWN
//05-13 10:42:35.178: I/System.out(19671): super.onTouchEvent()默认返回false 表示未消费事件
//05-13 10:42:35.178: I/System.out(19671): --------------------------------------------------
//05-13 10:42:35.225: I/System.out(19671): ===> MainActivity 中调用 dispatchTouchEvent()
//05-13 10:42:35.225: I/System.out(19671): ===> super.dispatchTouchEvent()默认返回true
//05-13 10:42:35.225: I/System.out(19671): --------------------------------------------------
//05-13 10:42:35.225: I/System.out(19671): ===> MainActivity 中调用  onTouchEvent()--->ACTION_UP
//05-13 10:42:35.225: I/System.out(19671): super.onTouchEvent()默认返回false 表示未消费事件
//05-13 10:42:35.225: I/System.out(19671): --------------------------------------------------

//结果分析:
//在最外层的MyFrameLayout的dispatchTouchEvent中返回false即不分发,此时注意:
//并没有去执行MyFrameLayout的onInterceptTouchEvent!!!可以理解为:都不分发了
//就压根没有意义去看是否还要onInterceptTouchEvent拦截了.
//所以在资料3中的图是有一些欠缺的.没有注意到该问题
//在这个测试中每层里没有一个onTouchEvent()返回true.
//所以在后续事件分发的时的情况及原理同下面的测试一样

//测试步骤:
//将MyLinearLayout的onInterceptTouchEvent()返回值设置为true
//表示拦截.按照资料2的图四,此时事件的分发dispatchTouchEvent会结束
//不会继续往下传递,所以开始执行MyLinearLayout的onTouchEvent()开始执行
//且回溯.

//测试结果:
//05-13 10:11:13.108: I/System.out(19000): ===> MainActivity 中调用 onCreate()
//05-13 10:11:13.108: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.213: I/System.out(19000): ===> MainActivity 中调用 dispatchTouchEvent()
//05-13 10:11:15.213: I/System.out(19000): ===> super.dispatchTouchEvent()默认返回true
//05-13 10:11:15.213: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.213: I/System.out(19000): ===> MainActivity 中调用 onUserInteraction()
//05-13 10:11:15.213: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.213: I/System.out(19000): 外层MyFrameLayout 中调用  dispatchTouchEvent()
//05-13 10:11:15.213: I/System.out(19000): super.dispatchTouchEvent()默认返回true 表示继续分发
//05-13 10:11:15.213: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.213: I/System.out(19000): 外层MyFrameLayout 中调用  onInterceptTouchEvent()
//05-13 10:11:15.213: I/System.out(19000): super.onInterceptTouchEvent()默认返回false 表示不拦截
//05-13 10:11:15.213: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.213: I/System.out(19000): 内层MyLinearLayout 中调用  dispatchTouchEvent()
//05-13 10:11:15.213: I/System.out(19000): super.dispatchTouchEvent()默认返回true 表示继续分发
//05-13 10:11:15.213: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.213: I/System.out(19000): 内层MyLinearLayout 中调用  onInterceptTouchEvent()
//05-13 10:11:15.213: I/System.out(19000): super.onInterceptTouchEvent()默认返回false 表示不拦截
//05-13 10:11:15.213: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.225: I/System.out(19000): 内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_DOWN
//05-13 10:11:15.225: I/System.out(19000): super.onTouchEvent()默认返回false 表示未消费事件
//05-13 10:11:15.225: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.225: I/System.out(19000): 外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_DOWN
//05-13 10:11:15.225: I/System.out(19000): super.onTouchEvent()默认返回false 表示未消费事件
//05-13 10:11:15.225: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.225: I/System.out(19000): ===> MainActivity 中调用  onTouchEvent()--->ACTION_DOWN
//05-13 10:11:15.225: I/System.out(19000): super.onTouchEvent()默认返回false 表示未消费事件
//05-13 10:11:15.225: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.241: I/System.out(19000): ===> MainActivity 中调用 dispatchTouchEvent()
//05-13 10:11:15.241: I/System.out(19000): ===> super.dispatchTouchEvent()默认返回true
//05-13 10:11:15.241: I/System.out(19000): --------------------------------------------------
//05-13 10:11:15.241: I/System.out(19000): ===> MainActivity 中调用  onTouchEvent()--->ACTION_UP
//05-13 10:11:15.241: I/System.out(19000): super.onTouchEvent()默认返回false 表示未消费事件
//05-13 10:11:15.241: I/System.out(19000): --------------------------------------------------

//结果分析:
//结果和我们预计的是一样的.可以看到在MyLinearLayout的onInterceptTouchEvent()中进行了
//拦截导致dispatchTouchEvent()的终端,并且MyLinearLayout开始执行onTouchEvent()且回溯.
//即MyLinearLayout的onTouchEvent()-->MyFrameLayout的onTouchEvent()-->MainActivity的onTouchEvent()
//注意:在处理up事件的时候还是这样的么?不是了!还是那个原因:从最上层(MainActvity)到最下层(MyButton)
//每一层的onTouchEvent()返回的均为false.系统会认为该事件没有被消费.所以后续事件分发的时候
//不会从MainActivity往下传递dispatchTouchEvent(),直接在MainActivity的onTouchEvent中处理.

//重要参考资料:
//1 http://www.eoeandroid.com/forum.php?mod=viewthread&tid=162460
//该资料中第二个图非常重要.
//2 http://www.dewen.org/q/2438
//该资料中亦有流程图
//3 http://blog.csdn.net/ponderforever/article/details/7082787
//在该资料的第四段提到:
//如果事件传递到某一层的子 view的onTouchEvent上了,这个方法返回了 false,
//那么这个事件会从这个view往上传递,都是其对应的onTouchEvent来接收.
//而如果传递到最上面的onTouchEvent也返回 false的话,这个事件就会"消失",而且接收不到下一次事件.
//(我说的一次事件指的是 down 到 up 之间的一系列事件)
//针对该段最后一句话:(我说的一次事件指的是 down 到 up 之间的一系列事件)
//的补充说明:比如在此Demo的MainActivity的onTouchEvent()中返回false(即默认值)并且
//MyButton的onTouchEvent()也返回false(默认的是true)那么外层的MyFrameLayoue
//和内层的LinearLayout只能获取到down事件而move和up事件是不能获取的
//这点非常的重要.
//4 http://blog.csdn.net/ddna/article/details/5473293
//5 http://blog.csdn.net/ddna/article/details/5451722
//6 http://www.sctarena.com/Article/Article.asp?nid=2802

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        System.out.println("===> MainActivity 中调用 onCreate()");
        System.out.println("--------------------------------------------------");
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    	System.out.println("===> MainActivity 中调用 dispatchTouchEvent()");
		System.out.println("===> super.dispatchTouchEvent()默认返回true");
		System.out.println("--------------------------------------------------");
    	return super.dispatchTouchEvent(ev);
    }

	@Override
	public void onUserInteraction() {
		System.out.println("===> MainActivity 中调用 onUserInteraction()");
		System.out.println("--------------------------------------------------");
		super.onUserInteraction();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			System.out.println("===> MainActivity 中调用  onTouchEvent()--->ACTION_DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			System.out.println("===> MainActivity 中调用  onTouchEvent()--->ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			System.out.println("===> MainActivity 中调用  onTouchEvent()--->ACTION_UP");
		default:
			break;
		}
		System.out.println("super.onTouchEvent()默认返回false 表示未消费事件");
		System.out.println("--------------------------------------------------");
		return super.onTouchEvent(event);
	}

}

MyFrameLayout如下:

package cn.c;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;

public class MyFrameLayout extends FrameLayout{
	public MyFrameLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		System.out.println("外层MyFrameLayout 中调用  dispatchTouchEvent()");
		System.out.println("super.dispatchTouchEvent()默认返回true 表示继续分发");
		System.out.println("--------------------------------------------------");
		return super.dispatchTouchEvent(ev);
		//return false;
	}

	//覆写自ViewGroup
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		System.out.println("外层MyFrameLayout 中调用  onInterceptTouchEvent()");
		System.out.println("super.onInterceptTouchEvent()默认返回false 表示不拦截");
		System.out.println("--------------------------------------------------");
		return super.onInterceptTouchEvent(ev);
		//return true;
	}
	//注意:
	//1 ViewGroup是View的子类
	//2 ViewGroup中onTouchEvent()方法默认返回的是false
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			System.out.println("外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			System.out.println("外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			System.out.println("外层MyFrameLayout 中调用  onTouchEvent()--->ACTION_UP");
		default:
			break;
		}
		System.out.println("super.onTouchEvent()默认返回false 表示未消费事件");
		System.out.println("--------------------------------------------------");
		return super.onTouchEvent(event);
	}

}

MyLinearLayout如下:

package cn.c;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class MyLinearLayout extends LinearLayout {
	public MyLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		System.out.println("内层MyLinearLayout 中调用  dispatchTouchEvent()");
		System.out.println("super.dispatchTouchEvent()默认返回true 表示继续分发");
		System.out.println("--------------------------------------------------");
		//return super.dispatchTouchEvent(ev);
		return false;
	}

	//覆写自ViewGroup
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		System.out.println("内层MyLinearLayout 中调用  onInterceptTouchEvent()");
		System.out.println("super.onInterceptTouchEvent()默认返回false 表示不拦截");
		System.out.println("--------------------------------------------------");
		return super.onInterceptTouchEvent(ev);

	}
	//注意:
	//1 ViewGroup是View的子类
	//2 ViewGroup中onTouchEvent()方法默认返回的是false
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			System.out.println("内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			System.out.println("内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			System.out.println("内层MyLinearLayout 中调用  onTouchEvent()--->ACTION_UP");
		default:
			break;
		}
		System.out.println("super.onTouchEvent()默认返回false 表示未消费事件");
		System.out.println("--------------------------------------------------");
		return super.onTouchEvent(event);
	}

}

MyButton如下:

package cn.c;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;

public class MyButton extends Button{
	public MyButton(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		System.out.println("自定义Button 中调用 dispatchTouchEvent()");
		System.out.println("super.dispatchTouchEvent默认返回true");
		System.out.println("--------------------------------------------------");
		return super.dispatchTouchEvent(event);
	}

	//注意:
	//在View的子类中onTouchEvent()方法默认返回的是true
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			System.out.println("自定义Button 中调用 onTouchEvent()--->ACTION_DOWN");
			break;
		case MotionEvent.ACTION_MOVE:
			System.out.println("自定义Button 中调用 onTouchEvent()--->ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			System.out.println("自定义Button 中调用 onTouchEvent()--->ACTION_UP");
			break;
		default:
			break;
		}
		System.out.println("super.onTouchEvent()默认返回true");
		System.out.println("--------------------------------------------------");
		return super.onTouchEvent(event);
	}

}

 

时间: 2024-08-04 03:30:41

Android事件传递机制(三)deprecated的相关文章

Android事件传递机制(二)deprecated

main.xml如下: <!-- 自定义布局中,放置一个自定义控件 --> <cn.c.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <cn.c.MyLinearLayout

Android事件传递机制(四)deprecated

main.xml如下: <!-- 自定义布局中,放置一个自定义控件 --> <cn.c.MyFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <cn.c.MyLinearLayout

Android事件传递机制(一)deprecated

main.xml如下: <RelativeLayout 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

Android事件传递机制(笔记)deprecated

总结: 1 事件的传递方向为:从最外层(Activity)传递至最内层(某个View)    事件的消费方向为:从最内层(某个View)传递至最外层(Activity)    该两个方向是相反的 2 ViewGroup中事件处理的流程是:    dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent    View中事件处理的流程是:    dispatchTouchEvent->onTouchEvent    只有当前者返回tru

Android事件传递机制_Android

实验环境 OS X 10.9 Eclipse(ADT) Android源码版本:API Level 19(Android 4.4) Android事件构成 在Android中,事件主要包括点按.长按.拖拽.滑动等,点按又包括单击和双击,另外还包括单指操作和多指操作.所有这些都构成了Android中的事件响应.总的来说,所有的事件都由如下三个部分作为基础: 按下(ACTION_DOWN) 移动(ACTION_MOVE) 抬起(ACTION_UP) 所有的操作事件首先必须执行的是按下操作(ACTIO

Android事件传递机制(零)

MainActivity如下: package com.cn; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; /** * Demo描述: * http://blog.csdn.net/lfdfhl/article/details/89

Android事件传递机制

实验环境 OS X 10.9 Eclipse(ADT) Android源码版本:API Level 19(Android 4.4) Android事件构成 在Android中,事件主要包括点按.长按.拖拽.滑动等,点按又包括单击和 双击,另外还包括单指操作和多指操作.所有这些都构成了Android中的事件响应 .总的来说,所有的事件都由如下三个部分作为基础: 按下(ACTION_DOWN) 移动(ACTION_MOVE) 抬起(ACTION_UP) 所有的操作事件首先必须执行的是按下操作(ACT

详细分析Android中onTouch事件传递机制_Android

onTach介绍 ontach是Android系统中整个事件机制的基础.Android中的其他事件,如onClick.onLongClick等都是以onTach为基础的. onTach包括从手指按下到离开手机屏幕的整个过程,在微观形式上,具体表现为action_down.action_move和action_up等过程. onTach两种主要定义形式如下: 1.在自定义控件中,常见的有重写onTouchEvent(MotionEvent ev)方法.如在开发中经常可以看到重写的onTouchEv

Android的View事件传递及传递问题 事件传递机制

Android的View 事件传递 1.基础知识 (1) 所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置.时间.历史记录以及第几个手指(多指触摸)等. (2) 事件类型分为 ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每个事件都是以 ACTION_DOWN 开始 ACTION_UP 结束. (3) 对事件的处理包括三