Как провести различие между броском и прикосновением? - PullRequest
4 голосов
/ 30 сентября 2010

У меня есть ListView внутри ViewFlipper, который я переворачиваю, когда пользователь проводит по экрану. Нажатие на ListView откроет браузер. Иногда, когда я смахиваю, он обнаруживается как касание в ListView и открывает браузер. Это может раздражать. Как я могу предотвратить это?

class MyGestureDetector extends SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            try {
                if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                    return false;
                // right to left swipe
                if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    viewFlipper.setInAnimation(slideLeftIn);
                    viewFlipper.setOutAnimation(slideLeftOut);
                    viewFlipper.showNext();
                } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                    viewFlipper.setInAnimation(slideRightIn);
                    viewFlipper.setOutAnimation(slideRightOut);
                    viewFlipper.showPrevious();
                }

                if (viewFlipper.getDisplayedChild() == 0) {
                    // TODO: light up left
                    flipperPosition = 0;
                } else if (viewFlipper.getDisplayedChild() == 1) {
                    // TODO: light up middle
                    flipperPosition = 1;
                } else if (viewFlipper.getDisplayedChild() == 2) {
                    // TODO: light up right
                    flipperPosition = 2;
                }
            } catch (Exception e) {
                System.out.println(e);
            }
            return false;
        }
    }

protected MotionEvent downStart = null;  

        public boolean onInterceptTouchEvent(MotionEvent event) {  

            switch(event.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                // keep track of the starting down-event  
                downStart = MotionEvent.obtain(event);  
                break;  
            case MotionEvent.ACTION_MOVE:  
                // if moved horizontally more than slop*2, capture the event for ourselves  
                float deltaX = event.getX() - downStart.getX();  
                if(Math.abs(deltaX) > ViewConfiguration.getTouchSlop() * 2)  
                    return true;  
                break;  
            }  

            // otherwise let the event slip through to children  
            return false;  
        }  

Ответы [ 2 ]

13 голосов
/ 01 октября 2010

Обычно это делается с помощью метода onInterceptTouchEvent родительского представления. onInterceptTouchEvent имеет шанс увидеть любое сенсорное событие, прежде чем его увидят дети. Если onInterceptTouchEvent возвращает true, то дочернее представление, которое ранее обрабатывало события касания, получает ACTION_CANCEL, и события с этого момента отправляются методу onTouchEvent родителя для обычной обработки. Он также может возвращать false и просто следить за событиями, когда они перемещаются по иерархии представления к своим обычным целям.

По сути, вы хотите сделать это в onInterceptTouchEvent в родительском представлении, где вы обнаруживаете броски:

  • На ACTION_DOWN запишите местоположение касания. Возврат false.
  • На ACTION_MOVE проверьте дельту между начальной позицией касания и текущей позицией. Если оно превышает пороговое значение (платформа использует ViewConfiguration#getScaledTouchSlop() или другие соответствующие значения из ViewConfiguration для подобных вещей), верните true.
  • Обнаружение и обработка броска как обычно на основе onTouchEvent.

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

Вот как такие вещи, как стандартный Android Launcher или News and Weather, выполняют параллельное перелистывание прокручиваемого / вставляемого контента.

1 голос
/ 30 сентября 2010

Вы пытались использовать SimpleOnGestureListener.onSingleTapConfirmed (MotionEvent) для события касания («щелчок»)?Это будет вызвано только после того, как детектор будет уверен, что первое нажатие пользователя действительно является нажатием, а не двойным нажатием (или, возможно, броском).

class MyGestureDetector extends SimpleOnGestureListener {
    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        // Code...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...