Переопределение onTouchEvent конкурирует с ScrollView - PullRequest
16 голосов
/ 01 июня 2011

Из упрощенного обзора у меня есть пользовательский вид, который содержит несколько растровых изображений, которые пользователь может перетаскивать и изменять их размер.

То, как я это делаю, довольно стандартно, так как я перезаписываю onTouchEvent в своем CustomView и проверяю, касается ли пользователь прикосновения к изображению и т. Д.

Моя проблема возникает, когда я хочу поместить этот CustomView в ScrollView. Это работает, но ScrollView и CustomView, кажется, конкурируют за MotionEvents, то есть, когда я пытаюсь перетащить изображение, оно либо медленно движется, либо вид прокручивается.

Я думаю, что мне, возможно, придется расширить ScrollView, чтобы я мог переопределить onInterceptTouchEvent и сообщить ему, находится ли пользователь в пределах изображения, чтобы не пытаться прокручивать. Но тогда, поскольку ScrollView находится выше в иерархии, как бы я получил доступ к текущему состоянию CustomView?

Есть ли лучший способ?

Ответы [ 3 ]

40 голосов
/ 01 июня 2011

Обычно Android использует длинное нажатие, чтобы начать перетаскивание в подобных случаях, поскольку это помогает устранить неоднозначность, когда пользователь намерен перетащить элемент против прокрутки контейнера элемента.Но если у вас есть однозначный сигнал, когда пользователь начинает перетаскивать элемент, попробуйте getParent().requestDisallowInterceptTouchEvent(true) из пользовательского представления, когда вы знаете, что пользователь начинает перетаскивание.(Документы для этого метода здесь .) Это не позволит ScrollView перехватывать события касания до конца текущего жеста.

8 голосов
/ 26 августа 2013

Ни одно из найденных решений не сработало для меня "из коробки", возможно, потому, что мое пользовательское представление расширяет Представление , а не ViewGroup , и, следовательно, я не могу реализовать onInterceptTouchEvent.

Также вызов getParent().requestDisallowInterceptTouchEvent(true) вызывал NPE или вообще ничего не делал.

Наконец, вот как я решил проблему:
Внутри вашего пользовательского onTouchEvent вызов requestDisallow... когда ваш взгляд позаботится о событии.Например:

@Override
public boolean onTouchEvent(MotionEvent event) {
    Point pt = new Point( (int)event.getX(), (int)event.getY() );
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        if (/*this is an interesting event my View will handle*/) {
            // here is the fix! now without NPE
            if (getParent() != null) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }

            clicked_on_image = true;
        }
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        if (clicked_on_image) {
            //do stuff, drag the image or whatever
        }
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        clicked_on_image = false;
    }
    return true;
}

Теперь мой пользовательский вид работает нормально, обрабатывая некоторые события и позволяя scrollView отлавливать те, которые нам не нужны.Нашел решение здесь: http://android -devblog.blogspot.com.es / 2011/01 / scrolling-inside-scrollview.html

Надеюсь, это поможет.

0 голосов
/ 08 июня 2016

Существует событие Android под названием MotionEvent.ACTION_CANCEL (значение = 3). Все, что я делаю, это перезаписываю метод onTouchEvent моего пользовательского элемента управления и фиксирую это значение. Если я обнаружу это состояние, я отвечу соответственно.

Вот код:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(isTouchable) {
        int maskedAction = event.getActionMasked();         
        if (maskedAction == MotionEvent.ACTION_DOWN) {
            this.setTextColor(resources.getColor(R.color.octane_orange));
            initialClick = event.getX();
        } else if (maskedAction == MotionEvent.ACTION_UP) {
            this.setTextColor(defaultTextColor);
            endingClick = event.getX();
            checkIfSwipeOrClick(initialClick, endingClick, range);
        } else if(maskedAction == MotionEvent.ACTION_CANCEL)
            this.setTextColor(defaultTextColor);
    }
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...