Android触摸事件简单分析

Android  2018年7月10日 am9:01发布6年前 (2018)更新 91es.com站长
86 0 0

这篇文章以前写的,后来博客清空重新开始了。最近看到,因此摘抄于此,以便查阅。

在开始分析之前,大家可以先记几个结论,这样便于理解。
  结论1:事件一定是先到达父控件上。
  结论2:事件简单来说可以分为三种:Down事件、Move事件、Up事件。

PS:

(1) 为了让读者看得更清晰,在代码中只打印了Down事件来分析,其他事件过滤,这样看起来简洁很多。
      (2) ViewGroup中才有事件的拦截,View中是没有的。

第一部分:代码片段

本不想附上代码,但如果没有,会让人理解有误,因此还是附上,仅供参考:

1、MainActivity.java


	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--MainActivity--------dispatchTouchEvent-------");
		}

		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--MainActivity--------onTouchEvent-------");
		}
		return super.onTouchEvent(event);
	}

2、ParentsView.java

public class ParentsView extends RelativeLayout {

	private String TAG = "touch";

	public ParentsView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public ParentsView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public ParentsView(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--ParentsView--------dispatchTouchEvent-------");
		}
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--ParentsView--------onInterceptTouchEvent-------");
		}
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--ParentsView--------onTouchEvent-------");
		}
		return super.onTouchEvent(event);
	}

}

3、SubView.java

public class SubView extends Button {

	private String TAG = "touch";

	public SubView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public SubView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public SubView(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--SubView--------dispatchTouchEvent-------");
		}
		return super.dispatchTouchEvent(event);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			Log.d(TAG, "--SubView--------onTouchEvent-------");
		}
		return super.onTouchEvent(event);
	}

}

4、layout.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" >

    <com.la.view.ParentsView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:background="@android:color/darker_gray" >

        <com.la.view.SubView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            android:background="@android:color/holo_blue_light"
            android:gravity="center"
            android:text="@string/hello_world" />
    </com.la.view.ParentsView>

</RelativeLayout>

上面代码中ParentsView和SubView分别继承RelativeLayout(间接继承ViewGroup)和Button(间接继承View),这个是为了简单点写,当然我们也可以直接继承ViewGroup或View的。

第二部分:触摸分发、拦截分析

情景一:ParentsView中不分发,也不处理时

就是在ParentsView的dispatchTouchEvent(MotionEvent ev)中返回 true。

就像[经理]直接把[老板]的话当屁放了。


touch   : --MainActivity--------dispatchTouchEvent------//老板 分发
touch   : --ParentsView--------dispatchTouchEvent-------//经理 不分发,也不处理了,直接抛弃事件

情景二:ParentsView中进行拦截,但不处理事件时

就是在ParentsView中的onInterceptTouchEvent(MotionEvent ev)返回true,但在onTouchEvent(MotionEvent event)中不处理事件,直接上报。

就像[经理]跟[老板]说[不处理!],不往下分配了,而是直接给[老板]自己处理。


touch   : --MainActivity--------dispatchTouchEvent------//老板 分发
touch   : --ParentsView--------dispatchTouchEvent-------//经理 分发
touch   : --ParentsView--------onInterceptTouchEvent----//经理 拦截
touch   : --ParentsView--------onTouchEvent-------------//经理 不处理(任务太简单了,不想处理,老板您自己处理吧)
touch   : --MainActivity--------onTouchEvent------------//老板 处理或不处理

情景三:ParentsView中进行拦截,但处理事件时

ParentsView中的 onInterceptTouchEvent(MotionEvent ev) 和 onTouchEvent(MotionEvent event)返回true,也就是拦截并处理了。

就像[经理]这次认怂了(老板的话还是要听听的),自己接下任务(很简单)自己处理了。


touch   : --MainActivity--------dispatchTouchEvent------//老板 分发
touch   : --ParentsView--------dispatchTouchEvent-------//经理 分发
touch   : --ParentsView--------onInterceptTouchEvent----//经理 拦截
touch   : --ParentsView--------onTouchEvent-------------//经理 自己处理掉

情景四:在SubView中不分发时

也就是在SubView中的dispatchTouchEvent(MotionEvent event)进行返回true。

[老板]和[经理]分配任务了,但是这任务可做可不做,[程序员]直接不安排时间(不分发).


touch   : --MainActivity--------dispatchTouchEvent------//老板   分发
touch   : --ParentsView--------dispatchTouchEvent-------//经理   分发
touch   : --ParentsView--------onInterceptTouchEvent----//经理   不拦截  让部下处理
touch   : --SubView--------dispatchTouchEvent-----------//程序员 不分发 觉得没必要处理

情景五:在SubView中分发,但不处理时

就是在ParentsView和SubView都不拦截,也不处理,因此最后任务又回到MainActivity

就像[老板]给[经理]下达新任务,[经理]直接向下分发,[程序员]觉得”没必要处理“,任务就抛给[经理],[经理]把任务又抛给[老板],如果上面还有[大BOSS],那继续上报。

touch : --MainActivity--------dispatchTouchEvent------//老板   分发
touch : --ParentsView--------dispatchTouchEvent-------//经理   分发
touch : --ParentsView--------onInterceptTouchEvent----//经理   不拦截
touch : --SubView--------dispatchTouchEvent-----------//程序员 分发
touch : --SubView--------onTouchEvent-----------------//程序员 不处理
touch : --ParentsView--------onTouchEvent-------------//经理   不处理
touch : --MainActivity--------onTouchEvent------------//老板   处理或不处理,如果上面还有大BOSS,继续上报

情景六:在SubView中分发,但处理时

就是在SubView中的onTouchEvent(MotionEvent event)返回true,进行处理了。

就像[老板]和[经理]的任务来了,这次任务重大,[程序员]必须处理。


touch   : --MainActivity--------dispatchTouchEvent------//老板   分发
touch   : --ParentsView--------dispatchTouchEvent-------//经理   分发
touch   : --ParentsView--------onInterceptTouchEvent----//经理   不拦截
touch   : --SubView--------dispatchTouchEvent-----------//程序员 分发(安排日期处理)
touch   : --SubView--------onTouchEvent-----------------//程序员 处理并消耗

小结一下

从上面实验得知:

(1)事件一定是从先到父控件(老板、经理)上,然后分发到子控件(程序员)上。

(2)如果控件(比如经理)拦截了事件,就不会再分发给子控件(程序员)上了。

(3)如果控件(比如经理)拦截了事件,且不处理,那么事件会上报给父控件(老板),但不会给子控件(程序员)。

(4)如果控件(比如经理)拦截了事件,也处理了此事件,那么事件就被消耗了,不会上报给父控件(老板),也不会传递给子控件(程序员)。

 历史上的今天

  1. 2024: Android解析lrc文件代码片段(0条评论)
  2. 2024: FileProvider分享的Uri转成文件(0条评论)
  3. 2023: MediaScanner源码JNI介绍2(0条评论)
  4. 2021: 许立志:梦想(0条评论)
  5. 2020: [摘]Java垃圾回收机制(GC)详解(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

[代码片段]自定义TextImageView

前言记录一下TextImageView的自定义。ImageView是不支持显示text的,虽然ImageView+TextView组合可以解决,但有时候只想一个View解决,因此就自定义一下。正文隐藏内容!付费阅读后才能查看!¥2 ¥3多个隐藏块只需支付一次付费阅读参考文章《Andr...

FileProvider的使用

前言自Android 7.0开始,Android 框架开启了严格模式(StrictMode),禁止应用将file:///开头的Uri共享给其他的应用读写文件,否则会收到FileUriExposedException的异常。因此,Android提供了新的文件共享机制FileProvider。记录...

隐藏Settings中的Preference笔记

在Android项目开发中,客户要求精简Settings,也就是删除部分不需要或者无用的功能,因此需要影藏Preference等,下面是摘抄网友并自己加工整理的。隐藏 Preference 有两种方法:一、先在xml布局里面删,然后在java里面删掉调用的相关部分,但如果很多地方都有调...

Launcher根据包名启动应用

前言很多项目中Launcher是有可能自定义的,毕竟Android原生的Launcher比较庞大,有时候需要的需求很简单,自己重新写Launcher也比较容易维护。为啥要根据包名启动,因为一个应用可能存在多个Activity,当按Home键退出后,再次从Launcher界面点击需要回到之前展示...

萧红:饿

“列巴圈”挂在过道别人的门上,过道好象还没有天明,可是电灯已经熄了。夜间遗留下来睡朦朦的气息充塞在过道,茶房气喘着,抹着地板。我不愿醒得太早,可是已经醒了,同时再不能睡去。厕所房的电灯仍开着,和夜间一般昏黄,好象黎明还没有到来,可是“列巴圈”已经挂上别人家的门了!有的牛奶瓶也规规矩矩地等在别的房间...

WebStorm等软件不能输入中文

最近在Linux 上使用WebStorm和Android Studio时出现无法输入中文,因此在网上查询了一下。在《linux环境下wps及WebStorm等软件不能输入中文解决方案》找到了比较完美的解决方案,摘抄如下:找到WebStorm的解压目录, 然后 cd WebStorm-16...