面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序
问题:
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处理,代码如下:
转载自:https://juejin.cn/post/7223357165682245691