Android触摸事件简单分析

Android 4年前 (2018) 125la.com站长
124 1 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)如果控件(比如经理)拦截了事件,也处理了此事件,那么事件就被消耗了,不会上报给父控件(老板),也不会传递给子控件(程序员)。

广告也精彩
版权声明:125la.com站长 发表于 2018年7月10日 上午9:01。
转载请注明:Android触摸事件简单分析 | 125啦读书导航

相关文章

广告也精彩

1 条评论

  • 125啦读书导航

    写得还不错,不过用图来表示更清晰一些,比如这位大神写的《https://blog.csdn.net/chunqiuwei/article/details/41084921》

    回复