Android SimpleOnGestureListener.onFling obtener un objeto nulo MotionEvent
Estoy tratando de detectar un evento de fling en una simple aplicación de Android, pero el primer argumento de MotionEvent
siempre es nulo. ¿Por qué se llama al método onFling con un argumento nulo? La documentación de Android dice que se llama cuando se produce un evento de fling con la inicial en abajo MotionEvent y la coincidencia de MotionEvent.
class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // e1 always == null, return early a null reference exception if (e1 == null) { return false; } if (e1.getY() - e2.getY() > 120) { handleFlingEvent(); return true; } return false; } }
La actividad principal tiene este método onTouchEvent:
- ¿Cómo sé si un MotionEvent es relativo o absoluto?
- Android Touch Evento que determina la duración
- Cómo deshabilitar el evento táctil android
- No mostrar MotionEvent.ACTION_UP o MotionEvent.ACTION_CANCEL
- Android: mover una vista en touch move (ACTION_MOVE)
GestureDetector flingDetector = new GestureDetector(new MyGestureDetector()); @Override public boolean onTouchEvent(MotionEvent event) { if (flingDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); }
- Volver a dibujar durante MotionEvent.ACTION_MOVE en onTouchEvent ()
- Por qué siempre obtengo ACTION_DOWN de onTouchEvent
- Ocultar el botón y mostrar de nuevo en el tacto
- ¿Cómo deslizar la imagen con el toque de dedo en Android?
- Android: forma de botón personalizada
- Inyectar eventos de pantalla táctil, Android 5.0, dev / input / eventX
- ¿Qué se llama un toque de salto en la documentación de Android?
- Desplazamiento suave con inercia y resistencia de los bordes / snapback
Tengo el problema similar. Sucede cuando el método GestureDetector y el método onFling se encontraban en una clase de vista personalizada, que forma parte de la interfaz de usuario de la actividad. Después de una serie de pruebas encontré que sólo la actividad principal puede detectar el gesto de deslizamiento también. Así que solucionar el problema por sustituirlos en la actividad. Pero no encontré la causa raíz de este problema.
En primer lugar me encontré con este problema con Android 4.0 como mi código funciona bien en todas las versiones anteriores. Después de tomar una señal de las sugerencias aquí, he encontrado una solución fácil es sólo realizar un seguimiento del evento onDown y utilizarlo en lugar del primer parámetro de onFling en caso de que suceda a ser nulo.
public class MySimpleGestureListener extends SimpleOnGestureListener { protected MotionEvent mLastOnDownEvent = null; @Override public boolean onDown(MotionEvent e) { mLastOnDownEvent = e; return true;//super.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1==null) e1 = mLastOnDownEvent; if (e1==null || e2==null) return false; float dX = e2.getX()-e1.getX(); float dY = e2.getY()-e1.getY(); ...rest of code } ...rest of class }
Tengo el mismo problema con la vista personalizada y OnGestureListener onFling. Encontré esto:
Sea o no utilizar GestureDetector.SimpleOnGestureListener, siempre debe implementar un método onDown () que devuelve true.
Sourced de http://developer.android.com/training/custom-views/making-interactive.html
Tenía 3 botones en el diseño lineal horizontal y esta disposición a su vez rodeada por horizontalscrollview
.
Entonces simplegesturelistener
el simplegesturelistener
en el horizontalscrollview
y conseguí el mismo error que arriba. Entonces también simplegesturelistener
para todos los botones en el diseño y trabajó.
Creo que el evento onDown ha sido reanudado por el scrollview, por lo que no podemos obtener el evento en la actividad. Si personaliza un ScrollView y reemplaza el dispatchTouchEvent () y onTouchEvent (), el problema se resolverá.
Actividad:
public class TestActivity extends Activity { private MyScrollView scrollView; private TestActivity me; private GestureDetector detector; protected void onCreate(Bundle savedInstanceState) { this.me = this; MySimpleGestureListener gestureListener = new MySimpleGestureListener(); this.detector = new GestureDetector(gestureListener); this.scrollView.setOnTouchListener(onTouchListerner); this.scrollView.setDetector(detector); } private View.OnTouchListener onTouchListener = new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return me.detector.onTouchEvent(event); } }; }
MySimpleGestureListener:
public class MySimpleGestureListener extends SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return super.onScroll(e1, e2, distanceX, distanceY); } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onDown(MotionEvent e) { return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO do your onFling here } }
Por fin, MyScrollView
public class MyScrollView extends ScrollView { private GestureDetector detector; @Override public boolean dispatchTouchEvent(MotionEvent ev){ if (this.detector!= null) { detector.onTouchEvent(ev); super.dispatchTouchEvent(ev); return true; } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); // if (this.detector != null) { return this.detector.onTouchEvent(ev); } return false; } // here is the getter and setter }
Espero que esto ayude.
En la clase de grupo de vista personalizada, necesita los métodos override 2: onInterceptTouchEvent
y onTouchEvent
. Después de eso, debe llamar a GestureDetector.onTouchEvent()
en ambos métodos. El evento ACTION_DOWN
se pasa a onInterceptTouchEvent
solamente.
@Override public boolean onInterceptTouchEvent(MotionEvent event) { if(mDetector.onTouchEvent(event)) { return true; } return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { if(mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); }
- Reconocimiento de voz continua Android
- Arquitectura limpia: cómo reflejar los cambios de la capa de datos en la interfaz de usuario