Android - listview

时间:2015-12-26 07:36:08

标签: android listview

我在使用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;真

我对以下观察感到困惑:

  1. 对于ACTION_DOWN(代码0),onInterceptTouchEvent返回'false',即使对于ACTION_DOWN(代码0),仍会调用onTouchEvent。只有当我从onTouchEvent返回true时,才应该调用onInterceptTouchEvent吗?

  2. 据我所知,只要onInterceptTouchEvent返回false,我就应该继续在onInterceptTouchEvent中获取事件,但事实并非如此! (我认为任何子视图都不会窃取事件,因为所有后续事件都是在MyListView's onTouchEvent本身传递的。)

  3. 有人能帮我理解为什么我会得到这样的日志吗?谢谢。

1 个答案:

答案 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()及其子代的更多源代码。