我在使用MotionEvent处理的ListView中观察到一个非常奇怪的行为。 我已经将ListView子类化以添加日志。这是我的子类。
public class MyListView extends ListView{
public MyListView(Context context) {
this(context, null);
}
public MyListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
boolean retVal = super.dispatchTouchEvent(ev);
System.out.println("MyListview.dispatchTouchEvent :"+ev.getActionMasked()+" <<>> "+retVal);
return retVal;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean retVal = super.onInterceptTouchEvent(ev);
System.out.println("MyListview.onInterceptTouchEvent :"+ev.getActionMasked()+" <<>> "+retVal);
return retVal;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean retVal = super.onTouchEvent(ev);
System.out.println("MyListview.onTouchEvent :"+ev.getActionMasked()+" <<>> "+retVal);
return retVal;
}
}
并且,当我在这个列表上,我在logcat中获得以下日志。
12-26 12:38:32.347:I / System.out(20725): MyListview.onInterceptTouchEvent:0&lt;&lt;&gt;&gt;假12-26 12:38:32.348: I / System.out(20725):MyListview.onTouchEvent:0&lt;&lt;&gt;&gt;真12-26 12:38:32.348:I / System.out(20725):MyListview.dispatchTouchEvent:0 &LT;&LT;&GT;&GT;真12-26 12:38:32.388:I / System.out(20725): MyListview.onTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.388: I / System.out(20725):MyListview.dispatchTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.405:I / System.out(20725):MyListview.onTouchEvent:2&lt;&lt;&gt;&gt; 真12-26 12:38:32.405:I / System.out(20725): MyListview.dispatchTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.422: I / System.out(20725):MyListview.onTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.422:I / System.out(20725):MyListview.dispatchTouchEvent:2 &LT;&LT;&GT;&GT;真12-26 12:38:32.439:I / System.out(20725): MyListview.onTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.439: I / System.out(20725):MyListview.dispatchTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.455:I / System.out(20725):MyListview.onTouchEvent:2&lt;&lt;&gt;&gt; 真12-26 12:38:32.455:I / System.out(20725): MyListview.dispatchTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.473: I / System.out(20725):MyListview.onTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.473:I / System.out(20725):MyListview.dispatchTouchEvent:2 &LT;&LT;&GT;&GT;真12-26 12:38:32.484:I / System.out(20725): MyListview.onTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.484: I / System.out(20725):MyListview.dispatchTouchEvent:2&lt;&lt;&gt;&gt;真12-26 12:38:32.484:I / System.out(20725):MyListview.onTouchEvent:1&lt;&lt;&gt;&gt; 真12-26 12:38:32.484:I / System.out(20725): MyListview.dispatchTouchEvent:1&lt;&lt;&gt;&gt;真
我对以下观察感到困惑:
对于ACTION_DOWN(代码0),onInterceptTouchEvent
返回'false',即使对于ACTION_DOWN(代码0),仍会调用onTouchEvent
。只有当我从onTouchEvent
返回true时,才应该调用onInterceptTouchEvent
吗?
据我所知,只要onInterceptTouchEvent
返回false,我就应该继续在onInterceptTouchEvent
中获取事件,但事实并非如此! (我认为任何子视图都不会窃取事件,因为所有后续事件都是在MyListView's
onTouchEvent
本身传递的。)
有人能帮我理解为什么我会得到这样的日志吗?谢谢。
答案 0 :(得分:0)
1. ListView
onTouchEvent()
仅在其所有孩子都没有消耗触摸事件或自身拦截触摸事件时调用(make onInterceptTouchEvent()
返回true )。因此,ListView
没有任何孩子或其子女onTouchEvent()
返回false,因此请ListView
本身处理触摸事件。
2.如果您阅读了ViewGroup
&#39; dispatchTouchEvent()
的源代码,您会发现:
// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
这意味着触摸事件为onInterceptTouchEvent()
时始终会调用ACTION_DOWN
,但触摸事件不是ACTION_DOWN
且{{1}时不会被调用变量(保存可触及的子视图的链接列表)为null。
因此,当您只是触摸屏幕(mFirstTouchTarget
)时,您可以调用onInterceptTouchEvent()
一次,但是当触摸事件继续时,无法再调用该方法,因为ACTION_DOWN
为null 。这通常是因为mFirstTouchTarget
没有孩子或所有孩子ListView
都返回假,正如我在上面的回答中提到的那样。
如果您想了解有关触摸事件传递的更多信息,请阅读onTouchEvent()
及其子代的更多源代码。