OnInterceptTouchEvent получает только ACTION_DOWN

Почему ViewGroup получает только ACTION_DOWN в onInterceptTouchEvent? Согласно документам, до тех пор, пока возвращается false, он должен получать все типы событий. http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent%28android.view.MotionEvent%29 Точка № 3.

Образец кода:

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new Container(this));
    }

    private class Container extends LinearLayout {

        public Container(Context context) {
            super(context);
            setBackgroundColor(0xFF0000FF);
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            Log.i(TAG, "onInterceptTouchEvent");
            int action = ev.getActionMasked();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                Log.i(TAG, "onInterceptTouchEvent.ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i(TAG, "onInterceptTouchEvent.ACTION_MOVE");
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                Log.i(TAG, "onInterceptTouchEvent.ACTION_UP");
                break;
            }
            return super.onInterceptTouchEvent(ev);
        }
    }
}

Ответ 1

Я отвечу на свой вопрос: onInterceptTouchEvent только вызывается, если у родителя есть дочернее представление, которое возвращает "true" из onTouchEvent. Когда дочерний объект возвращает true, родитель теперь имеет возможность перехватить это событие.

enter image description here

Ответ 2

У меня та же проблема. Я прочитал много постов об этом:
onInterceptTouchEvent получает только ACTION_DOWN
ACTION_UP и ACTION_MOVE onInterceptTouchEvent никогда не вызывается
onInterceptTouchEvent, onTouchEvent видят только ACTION_DOWN
onInterceptTouchEvent никогда не получает action_move

Я также читал документацию для Android:
http://developer.android.com/training/gestures/viewgroup.html
http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)

Все ответы одинаковы. Я пытался много раз, всегда не получить onInterceptTouchEvent(), если не событие.

Я читаю исходный код, думаю, что-то изменилось:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
    }

    boolean handled = false;
    if (onFilterTouchEventForSecurity(ev)) {
        final int action = ev.getAction();
        final int actionMasked = action & MotionEvent.ACTION_MASK;

        // Handle an initial down.
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // Throw away all previous state when starting a new touch gesture.
            // The framework may have dropped the up or cancel event for the previous gesture
            // due to an app switch, ANR, or some other state change.
            cancelAndClearTouchTargets(ev);
            resetTouchState();
        }

        // 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(ev) вызывается только тогда, когда MotionEvent.ACTION_DOWN, это то, что мы пытались и нашли. Итак, я думаю, что код изменился, но нет.

Если вы хотите, чтобы шпион или отслеживал все события, включая те, которые были отправлены в дочерние представления, вы можете переопределить dispatchTouchEvent() следующим образом:

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    MyLog.d(MyLog.DEBUG, "dispatchTouchEvent(): "+event.getAction());
    if (isEnabled()) {
        MyLog.d(MyLog.DEBUG, "dispatchTouchEvent()2: "+event.getAction());

        processEvent(event);//here you get all events include move & up

        super.dispatchTouchEvent(event);

        return true; //to keep receive event that follow down event
    }
    return super.dispatchTouchEvent(event);
}

У меня есть исполняемый код по адресу: https://github.com/maxyou/gesturebutton/blob/master/src/com/maxproj/gesturebutton/GestureButtonLayout.java

Ответ 3

Еще одна иллюстрация потока OnTouch

enter image description here

Activity.dispatchTouchEvent(MotionEvent) - это позволяет вашей активности перехватывать все сенсорные события, прежде чем они будут отправлены в окно.

ViewGroup.onInterceptTouchEvent(MotionEvent) - Это позволяет ViewGroup наблюдать за событиями, когда они отправляются дочерним представлениям. Это рекурсивная функция (от родителя к родителю)

ViewParent.requestDisallowInterceptTouchEvent(boolean) - вызовите это для родительского просмотра, чтобы указать, что он не должен перехватывать события касания с помощью onInterceptTouchEvent (MotionEvent).

Полный SO ответ здесь here