300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Anroid View事件响应机制和ViewGroup的事件响应分发机制

Anroid View事件响应机制和ViewGroup的事件响应分发机制

时间:2022-11-17 08:02:49

相关推荐

Anroid View事件响应机制和ViewGroup的事件响应分发机制

注:低版本的源码内容比高版本的源码简单,分析起来方便,但是高版本源码更为严密。

View的事件响应机制

涉及2个方法dispatchTouchEvent和onTouchEvent

1.View的dispatchTouchEvent方法(事件传递到View,View的这个方法就自动执行。)

dispatchTouchEvent返回true,响应事件;返回false,不响应事件。

----------------------------------------------------------------------------------------------------------------------

上述源码中的ListenerInfo是View类中的一个静态成员类,里面封装了各种事件类型的监听

者XxxListener的变量,包括privateOnTouchListenermOnTouchListener;

在View这个类中有ListenerInfomListenerInfo;这个类型的成员变量

而mListenerInfo是通过下面这个方法来返回的,从方法可以看出返回值肯定不为空。

ListenerInfogetListenerInfo(){

if(mListenerInfo!=null){

returnmListenerInfo;

}

mListenerInfo=newListenerInfo();

returnmListenerInfo;

}

结论1:所以View的dispatchTouchEvent方法中的if判断中li(也就是mListenerInfo)!=null

----------------------------------------------------------------------------------------------------------------------

再看View的setOnTouchListener这个方法,只要这个方法被调用了,参数不为空,那么

mListenerInfo.mOnTouchListener就不为空。

publicvoidsetOnTouchListener(OnTouchListenerl){

getListenerInfo().mOnTouchListener=l;

}

结论2:所以View的dispatchTouchEvent方法中的if判断中li.mOnTouchListener!=null

所以

这个条件组只是和li.mOnTouchListener.onTouch(this,event)这个回调方法有关

如果返回true的话,ImageView的dispatchTouchEvent方法也返回true。

如果返回false的话,会继续进行下面的一个if判断,也就是onTouchEvent方法的判断。

###############################################################################

所以对于dispatchTouchEvent()方法,如果直接继承自View的控件

1.没有调用setOnTouchListener()设置监听者,那么

li.mOnTouchListener==null,dispatchTouchEvent()方法默认就会返回false,这时

onTouchEvent方法和dispatchTouchEvent()方法就没有任何的关联了。

2.调用setOnTouchListener()设置监听者,那么li.mOnTouchListener!=null,

dispatchTouchEvent()方法就会判断li.mOnTouchListener.onTouch(this,event),即监听者

的onTouch回调方法(表明用户的意图)的返回值

***onTouch回调方法返回true,dispatchTouchEvent()方法就会返回true。

***onTouch回调方法返回false,dispatchTouchEvent()方法就会调用onTouchEvent处理

事件,即把事件转交给onTouchEvent方法进行处理

###############################################################################

2.View的onTouchEvent方法

publicbooleanonTouchEvent(MotionEventevent){

...

if(((viewFlags&CLICKABLE)==CLICKABLE||

(viewFlags&LONG_CLICKABLE)==LONG_CLICKABLE)){

...

switch(event.getAction()){

caseMotionEvent.ACTION_UP:

...

if(!post(mPerformClick)){

performClick();/*

底层实现:li.mOnClickListener.onClick(this);

View的点击事件真正是在UP事件之后执行的。

*/

}

...

returntrue;

}

returnfalse;

}

---------------------------------------------------------------------

View的onTouchEvent的返回值,取决于View是否可点击。

这就解释了为什么当ImageView和Button的监听事件的OnTouch事件都是返回false时,ImageView只能响应按下事件,而Button能响应所有事件的原因了:因为ImageView默认的clickable属性为false,而Button的clickable属性为true。

想让ImageView监听事件的onTouch返回false也能响应所有的事件,有2种方式

第1种:直接将ImageView的clickable属性设置为true。

第2种:为ImageView添加点击事件,通过查看下面的源码可以看出,点击事件会将View

的clickable属性设置为true。

publicvoidsetOnClickListener(OnClickListenerl){

if(!isClickable()){

setClickable(true);

}

getListenerInfo().mOnClickListener=l;}

假如Button添加了点击事件,如果去屏蔽它的点击事件呢?

n在添加点击事件的代码后面设置onclickable属性为false。

n在onTouchListener监听的onTouch方法里返回true。

原理:因为View的点击事件的本质是由onTouchEvent方法中的,performClick

这个方法所执行的,不让View执行onTouchEvent或clickable为false

即不会执行点击事件。

由此也可以看出onTouch事件和onClick事件不是一回事

ViewGroup的事件响应和传递机制(以2.3.3的源码来分析)

涉及3个方法dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent

ViewGroup的事件传递,是伴随着递归算法查找坐标落在那一个控件的范围,由父控件

向子控件,由外到内。

@Override

publicbooleandispatchTouchEvent(MotionEventev){

...

finalintaction=ev.getAction();

finalfloatxf=ev.getX();

finalfloatyf=ev.getY();

finalfloatscrolledXFloat=xf+mScrollX;

finalfloatscrolledYFloat=yf+mScrollY;

finalRectframe=mTempRect;//矩形类mTempRect=newRect();

booleandisallowIntercept=(mGroupFlags&FLAG_DISALLOW_INTERCEPT)!=0;

...

本文转自屠夫章哥 51CTO博客,原文链接:/4259297/1693953,如需转载请自行联系原作者

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。