您的位置:首页 > 其它

View的事件分发

2016-07-21 15:18 288 查看

1.事件分发常用的三个函数

public boolean dispathTouchEvent(MotionEvent ev);

用来进行事件分发,如果事件能够传递给当前view,那么此方法一定会调用,返回结果受当前View的onTouchEvent和下级View的dispathTouchEvent方法的影响,表示是否消耗当前事件。

public boolean onInterceptTouchEvent(MotionEvent ev);

在上面方法的内部调用,用来表示是够拦截某个事件,如果当前view拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件,viewgroup中才有此事件,view中默认将事件传递给view的onTouchEvent。

public boolean onTouchEvent(MotionEvent ev);

在dispathTouchEvent中调用,用来处理点击事件。返回结果表示是否消耗当前点击事件,如果不消耗,则在同一个事件序列中,当前view无法接收该类事件。

上面所述的三个函数用伪代码表示,理一理他们的执行之间的关系:

public boolean dispathTouchEvent(MotionEvetn ev)
{
boolean consume=false;
if(onInterceptTouchEvent(ev))
{
consume=onTouchEvent(ev);
}else
{
consume=child.dispathTouchEvent(ev);
}
return consume;
}


2.点击事件的传递规则

俗话说文不如图,所以我就给大家画了这幅图,还是很直观的。




我们就按照上面的图解释一下事件传递的流程。大致上:Activity->ViewGroup->View这样的事件分发机制,dispatchTouchEvent按照这条线走,View->ViewGroup->Activity这样的事件处理顺序,onTouchEvent按照这条线走。

2.1 Activity的传递过程

传递规则:当一个点击操作发生了,事件最先传递给的肯定是Activity,所以Acticity的dispatchTouchEvent就会开始进行事件分发。具体的工作由Activity内部的Window来完成。Window会将事件传递给Decorview,Decorview一般就是当前界面的底层容器(即setContentView所设置的View的父容器)。通过Activity.getWindow.getDecorView()就可以获得。我们来看一下具体的源码,当然了我们只是看一点点皮毛,毕竟源码这个小妖精还是很折磨人的。

Activity.dispatchTouchEvent();

public boolean dispatchTouchEvent(MotionEvent ev)
{
if(getWindow.superdispatchTouchEvent())
{
return true;
}
return onTouchEvent(ev);
}


通过分析上面的代码和图,我们不难发现当Activity分发的事件,下层的viewgroup和view都没有处理时,那么他将亲自出马,这个还是很形象的。在生活中也很常见。比如一个公司的老板有了一个任务,他就交给下面的经理和员工去干,但是很不幸他们都解决不了,那么老板只能说一句:“要你们何用?”,自己去干这个活了。想想真的是代码源自于生活啊。

接下来来看window是如何将事件传递给ViewGroup的。通过源码我们知道,Window是一个抽象类,而window的superdispatchTouchEvent也是一个抽象方法,因此我们必须要找到Window的实现类才行。

由于Window的唯一实现的是PhoneWindow,因此接下来看一下PhotoWindow是如何看处理点击事件。

public boolean superDispatchTouchEvent(MotionEvent ev)
{
return mDecor.superDispatchTouchEvent(event);
}


到这里逻辑就很清晰了,PhoneWindow将事件传递给了Decorview,到了这一层差不多就到了我们的viewgroup了,Decorview的讲解可以看View的基础知识那一节。

2.2 ViewGroup的传递规则

当点击事件到达顶级的view即viewgroup,会调用viewgroup的dispatchTouchEvent的进行事件分发,如果onInterceptTouchEvent返回true,那么事件就不在向viewgroup的下层分发,把点击事件交给viewgroup的onTouchEvent处理。如果onTouchEvent返回true,那么点击事件结束,如果返回false,那么把点击事件交给Activity的onTouchEvent处理。

如果onInterceptTouchEvent返回false,那么viewgroup就会将这个事件分发给他的子view。首先遍历

viewgroup的所有子元素,然后判断子元素是够能够接收点击事件:主要通过下面两个条件来衡量:

1.子元素是否在播动画

2.点击事件的坐标是否在子元素的区域内

注意点:执行ViewGroup的onTouchEvent之前,我们还要看一下mOnTouchListener是否被设置,如果没设置,先要执行onTouchListener中的ontouch方法,ontouch的返回值还决定了后面的onTouchEvent能不能执行,假如return true,那么不能执行。

2.3 View的传递规则

view对点击事件的处理过程稍微简单一点,注意这里的view是不包含viewGroup的,假如是viewgroup那么遵循上面的传递规则,因为view是一个单独的元素,它没有子元素因此不需要向下传递事件,所以它只能自己处理事件,首先判断有没有设置onTouchListener,如果OnTouchListener中的onTouch方法返回true,那么onTouchEvent就不会被调用,可见onTouch的优先级是高于onTouchEvent的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: