Android事件分发传递回传机制详解


转载本专栏每一篇博客请注明转载出处地址,尊重原创。此博客转载链接地址:点击打开链接   http://blog.csdn.net/qq_32059827/article/details/52577017


如果想参与实际开发项目,若不理解事件分发回传机制的话,几乎等于“”摸黑抓鳅”,因为几乎每个项目都会出现滑动冲突问题;而要想解决滑动冲突问题,必须先了解甚至掌握事件分发传递机制。等到了解决滑动冲突时,至少没有一种“断层”的感觉。所以本专栏开篇先介绍事件机制,对安卓中的事件机制,做一个详细的介绍与分析。

首先,View的几个基本的继承关系:

Android事件分发传递回传机制详解_第1张图片


本博客案例的图层:

新建三个类(分别按照上边图解的方式,写出这几个有关事件的方法)。

这个很简单,就不罗列了。例如类似容器1的代码:

public class ViewGroupOne extends LinearLayout {

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

	public ViewGroupOne(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}


	/**
	 * 分发事件
	 */
	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+分发+dispatchTouchEvent");
		return super.dispatchTouchEvent(event);
	}
	
	/**
	 * 拦截事件
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+拦截+onInterceptTouchEvent");
		return super.onInterceptTouchEvent(event);
	}
	
	/**
	 * 处理事件
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+处理+onTouchEvent");
		return true;
	}

}
笔者是吧事件抽取成工具类了,当然,每个方法里都写都写一遍事件情况也无所谓,只不过重复了一些代码罢了。

接着写一个复合上边图解的布局:

<com.example.event.ViewGroupOne 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"
    android:background="#ff0000"
    android:orientation="vertical" >

    <com.example.event.ViewGroupTwo
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="#00ff00" >

        <com.example.event.MyTextView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#0000ff" >
        </com.example.event.MyTextView>
    </com.example.event.ViewGroupTwo>

</com.example.event.ViewGroupOne>
注意:记得写类的全称。

好了,废话不多说,直接运行程序说话。通多点击手机屏幕。对所有的可能情况全部罗列如下:

一、默认情况,对生成的事件方法返回值什么也不做。返回值都是默认情况:

事件1:点击红色位置。看log输出

可以看到,整个事件是Activity先得到事件,调用它的dispatchTouchEvent分发事件,传递给ViewGroupOne,调用ViewGroupOne的dispatchTouchEvent方法,此时这个返回值默认return super.dispatchTouchEvent(event);把事件传递给自己的onInterceptTouchEvent(MotionEvent event)拦截事件,它的返回值也是默return super.onInterceptTouchEvent(event);认,即没做拦截;自己的onTouchEvent(MotionEvent event)处理方法被调用,默认不处理,return super.onTouchEvent(event);。这样事件没有被消费,又返回给Activity的onTouchEvent(MotionEvent event) ,Activity也是默认返回值。事件销毁。由up事件log日志,也可以看到:最后松手时,已经与ViewGroupOne没有任何关系。

事件2:点击绿色区域l。看log输出:

Android事件分发传递回传机制详解_第2张图片

这里就会显而易见了。多了ViewGroupTwo,就多往下传递一层,最里面这层每做处理,最后还是回传回来。到activity事件全部消失

事件3:点击蓝色区域:

这个肯定在意料之中,不用解释也很清楚为何打印此log了。

二、增加处理:

处理1:蓝色区域,MyTextView修改如下代码:

@Override
	public boolean onTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "MyTextView+处理+onTouchEvent");

		return true;//事件消费,不回传
	}
此时要重新运行程序了再点击蓝色区域,看log:

Android事件分发传递回传机制详解_第3张图片

MyTextView的onTouchEvent(MotionEvent event)返回true的意思是,事件由我来处理。它处理了事件,就不可能出现回传了,出现这种log也是顺理成章了。再看UP事件与分发拦截是一致的。最后在MyTextView中消失。这个时候可以对比一了,一都是默认,可以称之为狭义的回传机制,而二的处理1:我们可以称之为狭义的拦截机制,每一次的往下分发,有可称为狭义的传递机制(称之为狭义,可能逼格略高些,是因为不能代表全部,却也不失一般性;最起码拦截与回传分发大致是什么很清楚了)。那接着就细致开来,从狭义走到广义。

处理2:蓝色区域,MyTextView修改如下代码:

@Override
	public boolean onTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "MyTextView+处理+onTouchEvent");

		return false;//和默认效果一样,回传机制
	}
再运行,打印看log:

和默认效果是一样的。回看默认解析。

第一次总结:

TextView(没有子组件类型)
    onTouchEvent()
            return true; //事件消费不回传,自己消费掉事件
            return false;或者 return super.onTouchEvent() ;//事件回传给父组件

处理3:ViewGroupOne的dispatchTouchEvent方法做如下修改:

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+分发+dispatchTouchEvent");
		return true;
	}
运行程序,点击蓝色位置看log:

其实你会发现。不管点击屏幕哪个位置,都打印这样的log

这是因为,ViewGroupOne的dispatchTouchEvent返回true了,相当于在ViewGroupOne的分发事件地方就拦截了事件(称之为拦截,也因为没有回传,从UP日志里也可以看出没有回传)。事件消失。

处理4:ViewGroupOne的dispatchTouchEvent方法做如下修改:

@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+分发+dispatchTouchEvent");

		return false;
	}

Android事件分发传递回传机制详解_第4张图片

返回false,表示自己的dispatchTouchEvent不做处理,即不做分发。就回传,回传给activity的onTouchEvent处理,最后事件消失

注意:ViewGroupOne的dispatchTouchEvent方法默认返回super.dispatchTouchEvent(event);的时候是要传递给自己的onTouchEvent方法的,问这个方式是否做拦截。上边其实已经不知不觉介绍了这个情况。此时可以总结,只有在ViewGroupOne的dispatchTouchEvent方法默认返回super.dispatchTouchEvent(event);的时候才会去调用自己的onInterceptTouchEvent(MotionEvent event) 拦截事件,是否拦截。其他都是回传

处理5:ViewGroupOne的onInterceptTouchEvent方法做如下修改:

@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+拦截+onInterceptTouchEvent");
		return true;
	}
log情况

Android事件分发传递回传机制详解_第5张图片

自己的onInterceptTouchEvent(MotionEvent event)拦截事件返回为true,表名自己要拦截,不向下传递。调用自己的onTouchEvent(MotionEvent event)是否处理。由于默认不处理,又回传到activity事件消失。

处理6:ViewGroupOne的onInterceptTouchEvent(MotionEvent event)拦截事件返回false

@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+拦截+onInterceptTouchEvent");
		return false;
	}

又是默认的机制。

处理7:ViewGroupOne的onTouchEvent做如下处理:

注意:这个方法想要执行,前提是在ViewGroupOne的onInterceptTouchEvent方法返回true的时候

@Override
	public boolean onTouchEvent(MotionEvent event) {
		ActionUtiles.processEvent(event, "ViewGroupOne+处理+onTouchEvent");
		return super.onTouchEvent(event);
	}


返回true,自己处理事件,也就没了回传机制。事件消失

处理8:ViewGroupOne的onTouchEvent返回为false。不用打印也可以清楚,与默认效果是一样的。

第二次总结:

2,ViewGroup
      dispatchTouchEvent
            return true;//自己消费,不往下(子组件)往上传递(不回传)
            return false;//自己不处理,回传给父组件onTouchEvent方法处理
            return super.dis.....;//问自己onInterceptTouchEvent是否拦截
                   问自己  >onInterceptTouchEvent
                                true: 自己消费,调用自己onTouchEvent();不往下传递
                                false 或  super: 默认往下传递
                              
                                   >onTouchEvent()
                                          true: 自己消费(不回传)
                                          false 或 super: 继续回传

对于ViewGroupTwo和One是一摸一样的。就不再多赘述。最后,再用一张草图做一个收尾::


此草图花费接近一小时时间。。。虽然潦草,但是最能说明问题,包含了所有可能的情况。。


对于拦截机制详细介绍就完毕了,但是除了上边这些情况外,还有许许多多的分支情况;但是大同小异,仔细分析一下,就能得出正确的结论。以后此专栏可能还会再次探讨类似问题。若有问题或建议请留言更正、补充。

笔者花费几个小时,您或许只需要10分钟。欢迎点赞或关注本专栏,Android进阶知识不定期会更新哦。也可关注Android简易实战教程专栏,花5分钟“欣赏”有趣的小案例。

关注本博客,地址:点击打开链接   http://blog.csdn.net/qq_32059827

你可能感兴趣的:(事件分发机制,事件拦截机制,事件回传机制)