example - swipe listview android
Gesture Listener onFling Not Acting Constante (5)
Cambie el onTouch de esta manera:
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
boolean consumed = gestureDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_MOVE) {
return false;
}
return consumed;
}
Actualización: ver bounty para ampliar la pregunta.
Tengo una configuración GestureDetector
en un ListView
. ListView es un fragmento completo que proviene del lado de la ventana y superpone parcialmente otro fragmento. Quiero darle al usuario la capacidad de acercarlo (es decir, Wunderlist es un gran ejemplo de esta función en el lado derecho).
He aquí mi arreglo:
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
listView.setOnTouchListener(gestureListener);
El oyente mismo:
public class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 180;
private static final int SWIPE_THRESHOLD_VELOCITY = 50;
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
try {
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
FragmentManager fma = getActivity()
.getSupportFragmentManager();
FragmentManager fm = getFragmentManager();
FragmentTransaction t = fm.beginTransaction();
SherlockListFragment mFrag = new RateReviewFragment();
t.add(R.id.main_frag, mFrag);
t.setCustomAnimations(R.anim.animation_enter,
R.anim.animation_leave);
t.remove(mFrag);
t.commit();
}
return false;
} catch (Exception e) {
}
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// edited out; this opens up a context menu
}
}
A veces, cuando ListView
desplaza hacia abajo (o el desplazamiento de la lista se interrumpe con clics en una fila de la lista), GestureListener
simplemente se detiene ... escuchando. Deslizar no funcionará. Tienes que desplazarte hacia atrás para hacer que funcione nuevamente.
Si alguien puede ayudarme a aislar estos problemas, ¡le estaría muy agradecido!
ACTUALIZACIÓN: solo queda un problema, "el oyente deja de escuchar"
ACTUALIZACIÓN DOS: Pude haber averiguado qué está CAUSANDO esto; simplemente no sé la solución:
He encontrado algo después de registrar mis acciones; Cuanto más bajo llego a la lista (y cuanto más interactúo con ella), las mediciones no son consistentes. Por ejemplo, si muevo el dedo un centímetro hacia la izquierda y la derecha, en la parte superior de la lista, dirá que me moví, por ejemplo, 200 píxeles. Pero cuando tengo el problema indicado anteriormente, es mucho más bajo, quizás 50, para la MISMA distancia de 1 centímetro. Entonces, la ventana no se cierra porque no cumple mis condiciones if
.
Sidenote : lo he declarado más de una vez, el problema es cuando "interactúas con la lista". Esto significa: si me desplazo rápidamente de arriba hacia abajo; sin problema; pero si poco a poco voy bajando, tal vez tocando en la pantalla, desplazándome y apagándome, haciendo clic en los botones de la listView
, algunos de los cuales abren una nueva actividad (y luego vuelven a la misma posición), esto es "interactuar" con " .
No estoy seguro de si esto ayudará, ya que Dios sabe lo que está pasando detrás de la escena con todos estos problemas de fragmentos, pero intenta esto:
Después de que se haya llamado a OnTouch , antes de devolver la comprobación falsa si gestorDetector todavía está vivo (no nulo), (enviando devolución de llamada o algo a la clase listview) si no crea una instancia nueva y vuelve a llamar
listView.setOnTouchListener(gestureListener);
Primero intente hacer OnTouchListener
así:
View.OnTouchListener gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return true;
}
};
Entonces, siempre devuelve false
en onFling()
. Devuelve true
en la cláusula try/catch
. Y trate de pasar los mismos datos al método onScroll
en la cláusula else en onFling
.
prueba esto,
gestureDetector = new GestureDetector(getActivity(),
new GestureListener());
View.OnTouchListener gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
listView.onTouchEvent(event);
gestureDetector.onTouchEvent(event);
return true;
}
};
listView.setOnTouchListener(gestureListener);
y hacer el siguiente cambio
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return true;
}
EDITAR: Vi la lista de wunder de la aplicación, si quieres simular esa funcionalidad prueba este enfoque,
Use onInterceptTouch para el diseño de la raíz (del cual listView es un elemento secundario), dentro de este método debe verificar si el usuario ha pasado o no lo siguiente,
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_MOVE) {
if(/* Check your condition here */) {
// User has swiped
return true;
}
}
return false; // return false so that the event will be passed to child views.
}
para más información Android onInterceptTouchEvent
primero
onDown
que en tu oyente de gestos vuelves a ser true
en onDown
. Si he entendido bien su pregunta, está dejando de tocar y deslizar verticalmente eventos para ListView
, por lo que solo le interesan los eventos de deslizamiento horizontal en su código.
¿Por qué no eliminar todas las funciones que no le interesan, dejando así todo lo que no le interesa a ListView
? Si tiene que tenerlos, al menos devuelva false
, que es el predeterminado (consulte aquí ).
Como un lado, el código para AbsListView
(el padre de ListView
) muestra un sistema de estado bastante complejo para manejar toques y toques, por lo que es mejor dejarlo tan asediado como sea posible en mi opinión
En segundo lugar
Dadas sus observaciones más recientes, tal vez la clave es considerar la relación entre el desplazamiento X e Y en lugar del tamaño absoluto del deslizamiento. Si bien no puedo explicar el cambio en el tamaño del deslizamiento informado, lo que realmente nos interesa es un movimiento que es predominantemente horizontal, es decir:
(change in X) >> (change in Y)
Esto se puede lograr de la siguiente manera:
if ((velocityY == 0.0f) || (Math.abs(velocityX/velocityY) > 3.0f) {
// The movement is predominantly horizontal
// Put other checks here (like direction and so on)
// Then do the stuff
}
Esto tiene la ventaja de no usar e1
o e2
, lo que nos lleva a ...
En tercer lugar
Como nota, el problema es cuando ha interactuado con la vista de lista. En este punto, puede haber múltiples punteros reportados en el Event
. No se garantiza que la información X e Y predeterminada devuelta se relacione con un evento de puntero en particular. Probablemente valga la pena comprobar que está comparando información del mismo evento de puntero si desea hacer cálculos que impliquen X e Y, usando algo como:
int numPointers = e1.getPointerCount();
for (int pointerIndex1 = 0; pointerIndex1 < numPointers; pointerIndex1++) {
int pointerId = e1.getPointerId(pointerIndex1);
// find index for pointerId in e2.
float deltaX = e2.getX(pointerIndex2) - e1.getX(pointerIndex1);
// and so on
}