GestureDetector fling dirección equivocada
Tengo una implementación de un BottomDrawer
que implementa GestureDetector
para determinar cuando el usuario lanza el cajón inferior. Tengo dos problemas con esto:
1) El onFling
no siempre se llama. Este es un problema relativamente menor.
- GestureDetector y GestureDetectorCompat
- OnSingleTapUp de SimpleOnGestureListener nunca se llama
- Android - Añadir GestureDetector a la vista web
- NullPointerException en GestureDetector.onTouchEvent
- SimpleOnGestureListener nunca entra en el método onFling (...)
2) La velocidad que se pasa al onFling
es con frecuencia de la dirección equivocada. Este es un gran problema, ya que conduce al usuario que lanza el cajón para cerrar, y la apertura, o viceversa. ¿Es este un tema que alguien ha encontrado antes? ¿Como puede ésto ser resuelto? Pensé que tal vez ignorar los lanzamientos de menos de una cierta magnitud, pero las velocidades erróneas a veces puede ser de una magnitud bastante grande, por lo que no ayuda.
Aquí está el código de mi clase BottomDrawer
, también puedo subir un proyecto de demostración a GitHub si eso sería útil:
package com.cbendeb.bottomdrawer.view; import android.animation.Animator.AnimatorListener; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.LinearLayout; /** * A bottom extensible drawer. Displays two views, one as the handle and one as the content. * * @author catherine */ public final class BottomDrawer extends LinearLayout implements GestureDetector.OnGestureListener { private static final String TAG = BottomDrawer.class.getSimpleName(); private static final int ANIMATE_DURATION = 500; private float lastTouchY; // so we don't have to recalculate this stuff all the time private float openY; private float closedY; private float currentY = -1; // listeners for the end of the open and close animations private AnimatorListener closeListener; private AnimatorListener openListener; // gestures private GestureDetector gestureDetector; private boolean flung = false; public BottomDrawer(Context context) { super(context); init(context); } public BottomDrawer(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public BottomDrawer(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { setOrientation(LinearLayout.VERTICAL); gestureDetector = new GestureDetector(context, this); } /** * @return true if the drawer is expanded */ public boolean isOpen() { return currentY != closedY; } /** * Opens the drawer. */ public void open() { animate() .translationY(0) .setDuration( Math.max(0, (int) (ANIMATE_DURATION * (getY() - openY) / (closedY - openY)))) .setListener(openListener).start(); } /** * Closes the drawer. */ public void close() { animate() .translationY(getChildAt(1).getHeight()) .setDuration( Math.max(0, (int) (ANIMATE_DURATION * (closedY - getY()) / (closedY - openY)))) .setListener(closeListener).start(); } @Override public boolean onTouchEvent(MotionEvent ev) { final int action = ev.getActionMasked(); final float y = ev.getRawY(); gestureDetector.onTouchEvent(ev); switch (action) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: // Calculate the distance moved final float dy = y - lastTouchY; if (getY() + dy < closedY && getY() + dy > openY) { setY(getY() + dy); invalidate(); } break; case MotionEvent.ACTION_CANCEL: flung = false; break; case MotionEvent.ACTION_UP: Log.d(TAG, "flung: " + flung); if (!flung) { if (getY() >= (openY + closedY) / 2) { Log.d(TAG, "closing"); close(); } else { Log.d(TAG, "opening"); open(); } } flung = false; break; case MotionEvent.ACTION_POINTER_UP: break; } lastTouchY = y; return true; } @Override public void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); openY = getBottom() - getChildAt(0).getHeight() - getChildAt(1).getHeight(); closedY = getBottom() - getChildAt(0).getHeight(); if (currentY == -1) { currentY = closedY; } if (changed && isOpen()) { setY(openY); } else if (changed && !isOpen()) { setY(closedY); } } @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { Log.d(TAG, "onFling velocityY: " + velocityY + " currentY " + currentY); final float y = getY(); if (velocityY < 0 && y > openY && y < closedY) { // moving upwards Log.d(TAG, "onFling opening"); open(); } else if (velocityY > 0 && y > openY && y < closedY) { // moving downwards Log.d(TAG, "onFling closing"); close(); } flung = true; return true; } @Override public void onLongPress(MotionEvent e) { // Do nothing } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onShowPress(MotionEvent e) { // Do nothing } @Override public boolean onSingleTapUp(MotionEvent e) { // Do nothing return false; } }
Estoy buscando en la implementación GestureDetector en GrepCode … pero sería bueno si había una manera más fácil de resolver esto.
- OnGestureListener # onScroll no se llama desde GestureDetector en Samsung Galaxy Nota 10.1
- ¿Cómo puedo detectar el toque en la pantalla?
- GestureDetector no puede ser resuelto a un tipo
- ¿Cómo habilitar Scale en Android ScrollView de una manera que no impide que se desplace y haga clic en sus elementos secundarios?
- El método ScaleGestureDetector.OnScaleGestureListener.onScaleEnd () no está siendo alcanzado
- Android ListView con OnItemClickListener Y GestureDetector
- Problemas con la detección de gestos en ListView
- Evento OnUp en GestureDetector
- Usar el inicio de sesión de Facebook correctamente
- Cambiar nombre / Eliminar archivo deja el archivo vacío