Иногда GestureDetector пропускает на Fling
У меня есть приложение, которое использует 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;
}
}
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);
}