Иногда GestureDetector пропускает onFling

У меня есть приложение, которое использует GestureDetector, и я заменяю некоторые изображения onDown и onFling (он же onUp). Однако в некоторых случаях onFling не вызывается, и результат не очень хорош :)

Сталкивались ли вы с такой проблемой и нашли ли вы решение/обходной путь (кроме использования тайм-аута)?
Вот небольшой код:

    final GestureDetector gdt1 = new GestureDetector(getApplicationContext(), new MyGestureDetector(mGestDetector, R.id.weatherFrame1));
    FrameLayout weatherFrame1 = (FrameLayout)findViewById(R.id.weatherFrame1);
    if (weatherFrame1 != null)
    {
        weatherFrame1.setOnTouchListener(new View.OnTouchListener()
        {
            @Override
            public boolean onTouch(final View view, final MotionEvent event)
            {
                gdt1.onTouchEvent(event);
                return true;
            }
        });
    }

А вот часть MyGestureDetector.java

    public class MyGestureDetector implements GestureDetector.OnGestureListener{
    {
    ...
        @Override
        public boolean onDown(MotionEvent e)
        {
            int index = e.getActionIndex();
            int pointerId = e.getPointerId(index);

            if (startingPointerId == -1)
            {
                Log.i("MyGestureDetector", "Pointer is " + pointerId);

                if (pointerId == 0)
                {
                    startingPosX = e.getX(pointerId);
                    startingPosY = e.getY(pointerId);
                    startingPointerId = pointerId;
                    if (null != mGestureListener)
                    {
                        mGestureListener.onDown(mGestureOrigin);
                    }
                }
            }
            return true;
        }
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
        {
            startingPointerId = -1;
            if (null != mGestureListener)
            {
                mGestureListener.onUp(mGestureOrigin);
            }
            return true;
        }
    }

person dragi    schedule 27.05.2014    source источник
comment
опубликуйте код, над которым вы работали до сих пор.   -  person Vishnu Prabhu    schedule 27.05.2014
comment
Является ли просмотр с прослушивателем жестов и просмотр, который вы перетаскиваете, одним и тем же видом? Если да, просто создайте представление поверх перетаскиваемого представления и установите прослушиватель жестов в новом представлении наложения.   -  person resource8218    schedule 28.05.2014
comment
@ErvinMartirosyan На самом деле я использую onFling() для обнаружения события onUp(), потому что, согласно официальным документам onFling() Notified of a fling event when it occurs with the initial on down MotionEvent and the matching up MotionEvent., в моем случае не требуется перетаскивание, только события вниз и вверх.   -  person dragi    schedule 28.05.2014


Ответы (1)


Для обнаружения событий «вверх» и «вниз» я бы рекомендовал что-то простое:

@Override
public boolean onTouch(final View view, final MotionEvent event) {

   if (event.getAction() == MotionEvent.ACTION_UP) {
      // handle up event
   } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
      // handle down event
   }

}

Изменить: наиболее вероятная причина, по которой onFling не вызывается каждый раз, заключается в том, что это не просто способ обработки событий UP. Глядя на исходный код Android, onFling вызывается только тогда, когда скорость достигает минимальной скорости, необходимой для того, чтобы считаться «броском». Проверьте это:

 case MotionEvent.ACTION_UP:
        mStillDown = false;
        MotionEvent currentUpEvent = MotionEvent.obtain(ev);
        if (mIsDoubleTapping) {
            // Finally, give the up event of the double-tap
            handled |= mDoubleTapListener.onDoubleTapEvent(ev);
        } else if (mInLongPress) {
            mHandler.removeMessages(TAP);
            mInLongPress = false;
        } else if (mAlwaysInTapRegion) {
            handled = mListener.onSingleTapUp(ev);
        } else {

            // A fling must travel the minimum tap distance
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
            final float velocityY = velocityTracker.getYVelocity();
            final float velocityX = velocityTracker.getXVelocity();

            if ((Math.abs(velocityY) > mMinimumFlingVelocity)
                    || (Math.abs(velocityX) > mMinimumFlingVelocity)){
                handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY);
            }
        }

В частности:

 if ((Math.abs(velocityY) > mMinimumFlingVelocity)
          || (Math.abs(velocityX) > mMinimumFlingVelocity)){
      handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY);
 }

(Источник: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/view/GestureDetector.java)

person Brian    schedule 24.06.2014
comment
Я предполагаю, что это будет лучший подход, но все же это не дает ответа на мою проблему, когда onFling не вызывается. - person dragi; 24.06.2014
comment
Ознакомьтесь с дополнительной информацией, которую я добавил к ответу. onFling не обязательно вызывается для каждого события UP. - person Brian; 24.06.2014
comment
Несмотря на то, что я не уверен на 100%, что onFling не вызывается из-за слишком низкой скорости (мне нужно увидеть (отладить), чтобы поверить в это;)), это наиболее логичная причина моей проблемы. - person dragi; 24.06.2014