Problemas con la detección de gestos en ListView

Tengo una actividad que contiene un ViewFlipper. El ViewFlipper incluye 2 diseños, ambos de los cuales son esencialmente ListViews.

Así que la idea aquí es que tengo dos listas y para navegar de una a la otra yo usaría un golpe horizontal.

Tengo que trabajar. Sin embargo, en cualquier elemento de la lista en que se encuentre el dedo cuando se comience a ejecutar el golpe, ese elemento también se hace clic largo.

Aquí está el código relevante que tengo:

public class MyActivity extends Activity implements OnItemClickListener, OnClickListener { private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private GestureDetector mGestureDetector; View.OnTouchListener mGestureListener; class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // right to left swipe if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { if (mCurrentScreen != SCREEN_SECONDLIST) { mCurrentScreen = SCREEN_SECONDLIST; mFlipper.setInAnimation(inFromRightAnimation()); mFlipper.setOutAnimation(outToLeftAnimation()); mFlipper.showNext(); updateNavigationBar(); } } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { if (mCurrentScreen != SCREEN_FIRSTLIST) { mCurrentScreen = SCREEN_FIRSTLIST; mFlipper.setInAnimation(inFromLeftAnimation()); mFlipper.setOutAnimation(outToRightAnimation()); mFlipper.showPrevious(); updateNavigationBar(); } } } catch (Exception e) { // nothing } return true; } } @Override public boolean onTouchEvent(MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) return true; else return false; } ViewFlipper mFlipper; private int mCurrentScreen = SCREEN_FIRSTLIST; private ListView mList1; private ListView mList2; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.layout_flipper); mFlipper = (ViewFlipper) findViewById(R.id.flipper); mGestureDetector = new GestureDetector(new MyGestureDetector()); mGestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } return false; } }; // set up List1 screen mList1List = (ListView)findViewById(R.id.list1); mList1List.setOnItemClickListener(this); mList1List.setOnTouchListener(mGestureListener); // set up List2 screen mList2List = (ListView)findViewById(R.id.list2); mList2List.setOnItemClickListener(this); mList2List.setOnTouchListener(mGestureListener); } … } 

Si cambio el "return true"; Declaración del GestureDetector para "devolver false;", no obtengo clics largos. Lamentablemente, obtengo clics regulares.

¿Alguien sabe cómo puedo evitar esto?

Sólo para dar una respuesta completamente diferente con un enfoque completamente diferente …

He hecho una vista personalizada llamada SwipeView, es de código abierto, etc etc bla bla bla. Debe dejarle hacer lo que usted quiere hacer tan simplemente como ir:

 mSwipeView.addChild(myList1); mSwipeView.addChild(myList2); 

Usted no tendrá que meterse con los detectores de gestos o cualquier cosa, y el golpe debe seguir su dedo como lo haces …

(Esto se lee como un terrible terrible anuncio, por favor, perdón. Ha sido un día largo;)

Tener algunos enlaces maravillosos:

http://jasonfry.co.uk/?id=23

http://jasonfry.co.uk/?id=24

http://jasonfry.co.uk/?id=28

Como usas un GestureDetector , lo que SimpleGestureDetector.onLongPress(MotionEvent e) hacer es implementar SimpleGestureDetector.onLongPress(MotionEvent e) para manejar clics largos. Sin embargo, no se puede conocer el listitem que ha sido presionado desde allí, por lo que necesita recordarlo de la normal onItemLongClick() .

 class MyGestureDetector extends SimpleOnGestureListener { ... @Override public void onLongPress(MotionEvent e) { if (longClickedItem != -1) { Toast.makeText(MainActivity.this, "Long click!", Toast.LENGTH_LONG).show(); } } } int longClickedItem = -1; @Override public boolean onItemLongClick(AdapterView<?> list, View view, int position, long id) { longClickedItem = position; return true; } @Override public boolean onTouchEvent(MotionEvent event) { // Reset longclick item if new touch is starting if (event.getAction()==MotionEvent.ACTION_DOWN) { longClickedItem = -1; } if (mGestureDetector.onTouchEvent(event)) return true; else return false; } 

He probado esto y parece que funciona bien.

Vaya a su gestoDetector y fije

  mGestureDetector.setIsLongpressEnabled(false); 

Esto evitará que se detecten eventos de prensa largos.

[EDIT] Rasca eso, totalmente mal.

Creo que tendrías que actualizar esta parte, y detectar si te desplazabas a la izquierda o derecha, y devuelve true si estuvieras en un estado de swiping. O al menos eso es donde yo buscaría primero.

  mGestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } return false; } }; 

Continuando con mi pobre ejemplo, lo siento.

Dentro de la onTouch creo que puede probar el event.getAction () y determinar si se ha producido un clic largo. Si lo ha hecho, y su en un movimiento de lanzamiento, a continuación, devuelve verdadero como para capturar el clic largo.

Temo que esto sea más una sugerencia que una respuesta definitiva.

También tiene que comprobar el otro en [métodos] que puede anular desde el SimpleOnGestureListener. Acaba de revisar y

 @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub super.onLongPress(e); } 

Podría ser algo con lo que podrías experimentar.

Desarrollé un componente personalizado derivado de horizontalScrollView que hace esto. Tengo listViews como las vistas de niño y deslizar sin presiones largas. Es respaldado por un listAdapter, que podría ser cualquier cosa que quieras (ArrayAdapter, CursorAdapter …). Carga hasta tres puntos de vista de niño y luego en mover de un tirón, sólo intercambia a ambos lados. La mayor parte de esto es kanged de ListView y necesita ser refactorizado. Es demasiado tiempo para publicar aquí directamente.

http://pastie.org/1480091

Quite su getListView().setOnItemLongClickListener

Agregue en su clase MyGestureDetector :

 public void onLongPress(MotionEvent e) { final int position = getListView().pointToPosition((int) e.getX(), (int) e.getY()); // what you want do super.onLongPress(e); } 
  • ¿Cómo habilitar Scale en Android ScrollView de una manera que no impide que se desplace y haga clic en sus elementos secundarios?
  • GestureDetector y GestureDetectorCompat
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.