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