android view的事件传递机制学习笔记



1.view 中的dispatchTouchEvent方法返回值为 onTouchEvent(event);  

2.dispatchTouchEvent方法调用了ontouch方法。 ontouch方法在view 中是OntouchListener接口的抽象方法。

3.dispatchTouchEvent 中的ontouch方法要优先于onTouchEvent(event);  执行。onclick在onTouchEvent(event);  中执行只要控件注册了onclicklistener,就会执行onclick方法(在该方法当中)。

4.当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action,层级传递的。

   mOnTouchListener.onTouch(this, event)返回false 之后会调用onTouchEvent(event)方法,但onTouchEvent(event)方法可能会返回true(如何控件是enable的 则会返回为true而使整个方法返回ture如button, 反之亦然如textview)

疑问:哪些控件默认是enable的?哪些不是默认enable的?

5.注册了点击事件,该控件就是enable的了。所以textview注册了点击事件后,即时dispatchtouch方法返回为false, 他的down, move, up也 都会执行。

 已知的: imageview不是, button是, textview不是。

 

public boolean dispatchTouchEvent(MotionEvent event) {
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}
条件1: 该view是否注册了点击事件, 注册了点击事件就为1
条件2: 该view是否是可点击的  enable = true;(疑问,注册了点击事件view就是enable的了吗?)
条件3: view的onTouch方法的返回值。
onTouchEvent(event);
该方法如果控件注册了点击事件的话,就会执行click方法。
guolin的传递源码分析:

http://blog.csdn.net/guolin_blog/article/details/9097463



如果我们设置了setOnTouchListener,并且return true,那么View自己的onTouchEvent就不会被执行了


1、整个View的事件转发流程是:

View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent

在dispatchTouchEvent中会进行OnTouchListener的判断,如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent。

2、onTouchEvent中的DOWN,MOVE,UP

DOWN时:

a、首先设置标志为PREPRESSED,设置mHasPerformedLongPress=false ;然后发出一个115ms后的mPendingCheckForTap;

b、如果115ms内没有触发UP,则将标志置为PRESSED,清除PREPRESSED标志,同时发出一个延时为500-115ms的,检测长按任务消息;

c、如果500ms内(从DOWN触发开始算),则会触发LongClickListener:

此时如果LongClickListener不为null,则会执行回调,同时如果LongClickListener.onClick返回true,才把mHasPerformedLongPress设置为true;否则mHasPerformedLongPress依然为false;

MOVE时:

主要就是检测用户是否划出控件,如果划出了:

115ms内,直接移除mPendingCheckForTap;

115ms后,则将标志中的PRESSED去除,同时移除长按的检查:removeLongPressCallback();

UP时:

a、如果115ms内,触发UP,此时标志为PREPRESSED,则执行UnsetPressedState,setPressed(false);会把setPress转发下去,可以在View中复写dispatchSetPressed方法接收;

b、如果是115ms-500ms间,即长按还未发生,则首先移除长按检测,执行onClick回调;

c、如果是500ms以后,那么有两种情况:

i.设置了onLongClickListener,且onLongClickListener.onClick返回true,则点击事件OnClick事件无法触发;

ii.没有设置onLongClickListener或者 onLongClickListener.onClick 返回false,点击事件OnClick事件依然可以触发;

d、最后执行mUnsetPressedState.run(),将setPressed传递下去,然后将PRESSED标识去除;


最后问个问题,然后再运行个例子结束:

1、setOnLongClickListener和setOnClickListener是否只能执行一个

不是的,只要setOnLongClickListener中的onClick返回false,则两个都会执行;返回true则会屏幕setOnClickListener


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值