问题:
View的onTouchEvent,OnLongClickListener,OnClickListener,OnTouchListener几者的执行顺序是怎样的?
回答:
这三者的响应顺序依此是diapatchTouchEvent > onTouchListener.onTouch > onTouchEvent > OnLongClickListener > onClickListener,其中任一环节处理事情后,事情则不持续向下分发,View内部的事情处理流程如下图:
可以看出不管OnTouchListener.onTouch,onTouchEvent仍是OnClickListener.onClick,三者任一回来true,即代表事情被当时View耗费,假如当时View不处理事情,则该事情会向上冒泡,终究被ViewRootImpl处理。
解析:
关于响应事情的View而言,在不考虑父布局拦截事情的前提下,事情流入View的dispatchTouchEvent,在View的onTouchEvent中进行处理。针对一个View而言,咱们需要自己处理触摸事情时,通常情况下有三种方式:
- 设置OnTouchListener
- 重写onTouchEvent
- 设置OnClickListener
那么这三者有什么区别呢?触发顺序是怎样的呢?
设置OnTouchListener
为View设置OnTouchListener
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
那么咱们来看下OnTouchListener.onTouch是在哪里调用的?
public void setOnTouchListener(OnTouchListener l) {
getListenerInfo().mOnTouchListener = l;
}
可以看出dispatchTouchEvent会判断是否设置了OnTouchListener,假如设置了的话,就把事情先转交给OnTouchListener处理,OnTouchListener.onTouch回来false再持续分发。
设置OnClickListener
为View设置OnClickListener的代码如下所示:
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
那么咱们来看下OnClickListener.onClick是在哪里调用的?
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
可以看到OnClickListener.onClick是在performClick中调用的,而performClick是在onTouchEvent的ACTION_UP中经过performClickInternal调用的,代码如下:
onTouchEvent
从dispatchTouchEvent中可以看到当不设置OnTouchListener或许OnTouchListener.onTouch回来false时,会将事情交给View的onTouchEvent处理,代码如下: