写代码过程中遇到个问题,如果像下面这样写ListView会发生什么?
mListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
答案是:如果给ListView设置TouchListener,并返回true,该ListView将无法滑动,无法点击里面的Item。即无法回调OnScrollListener和OnItemClickListener方法。
由于之前没有想过这个问题,网上查找也不知道如何搜起,好吧,看源码!
发现setOnTouchListener是在View里面的,view里面有这个方法
public boolean dispatchTouchEvent(MotionEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}
即如果你给一个view设置了setOnTouchListener的方法,会执行你的OnTouchListener方法。但是问题来了我们知道touch事件的分发先执行 dispatchTouchEvent -> onInterceptTouchEvent -> onTouchEvent 那我给ListView设置的OnTouchListener方法在哪调用的呢?
首先说明,我们看源码其实很有意思。
首先说明View是没有onInterceptTouchEvent方法的,ListView属于ViewGroup,上面三个方法都有。
ViewGroup重写了View的dispatchTouchEvent方法,看ViewGroup里的dispatchTouchEvent方法源码你会发现在内部调用了onInterceptTouchEvent方法,然后再调用dispatchTransformedTouchEvent方法。在该方法里面会执行子View或者执行super的dispatchTouchEvent方法。super即是View的dispatchTouchEvent方法,在View的dispatchTouchEvent方法里面又调用了onTouchEvent方法。并且在view的dispatchTouchEvent方法里面也调用了刚才我们设置的OnTouchListener里的方法。
苦口婆心写了这么多,最终还是看源码比较方便。
最终结论就是如果给ListView设置OnTouchListener,并且返回true,则ListView的onTouchEvent方法就不会被调用,即也不会滚动不可以点击。原因就是上面一大段罗里吧嗦的话。