Android View的事件分发机制.docx

上传人:b****5 文档编号:2844366 上传时间:2022-11-15 格式:DOCX 页数:14 大小:21.66KB
下载 相关 举报
Android View的事件分发机制.docx_第1页
第1页 / 共14页
Android View的事件分发机制.docx_第2页
第2页 / 共14页
Android View的事件分发机制.docx_第3页
第3页 / 共14页
Android View的事件分发机制.docx_第4页
第4页 / 共14页
Android View的事件分发机制.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

Android View的事件分发机制.docx

《Android View的事件分发机制.docx》由会员分享,可在线阅读,更多相关《Android View的事件分发机制.docx(14页珍藏版)》请在冰豆网上搜索。

Android View的事件分发机制.docx

AndroidView的事件分发机制

AndroidView的事件分发机制

一个应用的布局是丰富的,有TextView,ImageView,Button等,这些子View的外层还有ViewGroup,如RelativeLayout,LinearLayout。

作为一个开发者,我们会思考,当点击一个按钮,Android系统是怎样确定我点的就是按钮而不是TextView的?

然后还正确的响应了按钮的点击事件。

内部经过了一系列什么过程呢?

先铺垫一些知识能更加清晰的理解事件分发机制:

1.通过setContentView设置的View就是DecorView的子view,即DecorView是父容器。

2.点击屏幕时,在手指按下和抬起间,会产生很多事件,down…move…move…up,中间会有很多的move事件,这一系列的事件为一个事件序列

3.dispatchTouchEvent方法用于分发事件

4.onInterceptTouchEvent方法用于拦截事件

5.onTouchEvent方法用于处理事件

当一个点击事件(MotionEvent)产生后,事件最先传递给当前的界面(Activity),这点是很好理解的。

Activity再将事件传递给窗口(Window),然后Window将事件传递给顶级View(DecorView)。

此时,事件已经到达了View了。

之后顶级View就会按照事件分发机制去分发事件。

具体是这样的:

对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,这时它的dispatchTouchEvent方法就会被调用,如果这个ViewGroup的onInterceptTouchEvent方法返回true就表示它要拦截当前事件,接着事件就会交给这个ViewGroup处理,即它的onTouchEvent方法就会被调用。

如果这个ViewGroup的onInterceptTouchEvent方法返回false,就表示它不拦截当前事件,这时当前事件就会继续传递给它的子元素,接着子元素的dispatchTouchEvent方法就会被调用,如此反复直到事件被最终处理。

如果一个View的onTouchEvent方法返回false,那么它的父容器的onTouchEvent方法会被调用,如果它的父容器的onTouchEvent方法还是返回false,那就继续往上抛,当所有的元素都不处理这个事件,那么这个事件会最终传递给Activity处理,即Activity的onTouchEvent方法会被调用。

好了,现在已经铺垫了基础,那么接下来就从源码的角度来分析事件分发机制。

当然是从Activity的dispatchTouchEvent方法开始分析。

源码如下:

publicbooleandispatchTouchEvent(MotionEventev){

if(ev.getAction()==MotionEvent.ACTION_DOWN){

onUserInteraction();

}

if(getWindow().superDispatchTouchEvent(ev)){

returntrue;

}

returnonTouchEvent(ev);

}

如果当前事件是down的话,就调用onUserInteraction方法,onUserInteraction是一个空方法,我们可以暂时不搭理。

然后调用getWindow方法获取到当前Activity关联的Window,Window再调用superDispatchTouchEvent方法将事件传入进行分发。

如果superDispatchTouchEvent方法返回true的话,view已经处理了事件。

整个事件循环结束。

如果返回false,没有view处理这个事件。

事件往上抛,那就Activity自己处理了,即Activity的onTouchEvent方法会被调用。

因为想要知道事件的整个分发过程,现在关注的是Window的superDispatchTouchEvent方法,那么就跟进去看看:

publicabstractbooleansuperDispatchTouchEvent(MotionEventevent);

Window是一个抽象类,superDispatchTouchEvent是一个抽象的方法,那么我们必须要找到window的实现类才行,可是茫茫人海怎么找呢?

看到window类的说明就明白了

*

Theonlyexistingimplementationofthisabstractclassis

*android.view.PhoneWindow,whichyoushouldinstantiatewhenneedinga

*Window.

*/

publicabstractclassWindow

意思是Window存在唯一的实现是android.view.PhoneWindow

那么PhoneWindow里的superDispatchTouchEvent方法就是我们要找的信息,如下:

@Override

publicbooleansuperDispatchTouchEvent(MotionEventevent){

returnmDecor.superDispatchTouchEvent(event);

}

直接将事件传递给了DecorView。

这时事件已经是到达View了哦。

那么跟进DecorView的superDispatchTouchEvent方法看看,如下:

publicbooleansuperDispatchTouchEvent(MotionEventevent){

returnsuper.dispatchTouchEvent(event);

}

内部调用了父类的dispatchTouchEvent方法,那么DecorView的父类是什么呢?

DecorView肯定是View的,那么刚才开篇提到,我们通过setContentView设置的View,是DecorView的子View。

那么更加准确的说DecorView是一个ViewGroup。

privatefinalclassDecorViewextendsFrameLayoutimplementsRootViewSurfaceTaker

可以看到DecorView是继承自FrameLayout,FrameLayout是ViewGroup,也就是说DecorView是一个ViewGroup。

那么现在只需要关注ViewGroup的dispatchTouchEvent方法。

继续前进

ViewGroup的事件分发

ViewGroup的dispatchTouchEvent方法如下:

@Override

publicbooleandispatchTouchEvent(MotionEventev){

//代码省略

//Checkforinterception.

finalbooleanintercepted;

if(actionMasked==MotionEvent.ACTION_DOWN

||mFirstTouchTarget!

=null){

finalbooleandisallowIntercept=(mGroupFlags&FLAG_DISALLOW_INTERCEPT)!

=0;

if(!

disallowIntercept){

intercepted=onInterceptTouchEvent(ev);

ev.setAction(action);//restoreactionincaseitwaschanged

}else{

intercepted=false;

}

}else{

//Therearenotouchtargetsandthisactionisnotaninitialdown

//sothisviewgroupcontinuestointercepttouches.

intercepted=true;

}

//代码省略

if(!

canceled&&!

intercepted){

//代码省略

finalintchildrenCount=mChildrenCount;

if(newTouchTarget==null&&childrenCount!

=0){

finalfloatx=ev.getX(actionIndex);

finalfloaty=ev.getY(actionIndex);

//Findachildthatcanreceivetheevent.

//Scanchildrenfromfronttoback.

finalArrayListpreorderedList=buildOrderedChildList();

finalbooleancustomOrder=preorderedList==null

&&isChildrenDrawingOrderEnabled();

finalView[]children=mChildren;

for(inti=childrenCount-1;i>=0;i--){

finalintchildIndex=customOrder

?

getChildDrawingOrder(childrenCount,i):

i;

finalViewchild=(preorderedList==null)

?

children[childIndex]:

preorderedList.get(childIndex);

//Ifthereisaviewthathasaccessibilityfocuswewantit

//togettheeventfirstandifnothandledwewillperforma

//normaldispatch.Wemaydoadoubleiterationbutthisis

//safergiventhetimeframe.

if(childWithAccessibilityFocus!

=null){

if(childWithAccessibilityFocus!

=child){

continue;

}

childWithAccessibilityFocus=null;

i=childrenCount-1;

}

if(!

canViewReceivePointerEvents(child)

||!

isTransformedTouchPointInView(x,y,child,null)){

ev.setTargetAccessibilityFocus(false);

continue;

}

newTouchTarget=getTouchTarget(child);

if(newTouchTarget!

=null){

//Childisalreadyreceivingtouchwithinitsbounds.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 金融投资

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1