MotionEvent.ACTION_UP non appelé

Considérez le schéma ci-dessous (pour une meilleure compréhension de mon problème). entrer la description de l'image ici

Comme vous pouvez le voir, je considère une vue de liste entourée de remplissage. Maintenant, si un utilisateur appuie sur un élément de la liste, comme l’action, je lui ai fourni une couleur d’arrière-plan bleu clair. Maintenant, mon application traite avec onTouch Events elle-même pour déterminer des actions comme

  • Cliquez sur
  • Glisser de gauche à droite
  • Droit à gauche glisser

Voici mon code.

public boolean onTouch(View v, MotionEvent event) { if(v == null) { mSwipeDetected = Action.None; return false; } switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: { downX = event.getRawX(); downY = event.getRawY(); mSwipeDetected = Action.Start; // Find the child view that was touched (perform a hit test) Rect rect = new Rect(); int childCount = listView.getChildCount(); int[] listViewCoords = new int[2]; listView.getLocationOnScreen(listViewCoords); int x = (int) event.getRawX() - listViewCoords[0]; int y = (int) event.getRawY() - listViewCoords[1]; View child; for (int i = 0; i < childCount; i++) { child = listView.getChildAt(i); child.getHitRect(rect); if (rect.contains(x, y)) { mDownView = child; break; } } return false; // allow other events like Click to be processed } case MotionEvent.ACTION_MOVE: { upX = event.getRawX(); upY = event.getRawY(); float deltaX=0,deltaY=0; deltaX = downX - upX; deltaY = downY - upY; if(deltaY < VERTICAL_MIN_DISTANCE) { setTranslationX(mDownView, -(deltaX)); setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / listView.getWidth()))); return false; } else { forceBringBack(v); } return false; } case MotionEvent.ACTION_UP: { stopX = event.getX(); float stopValueY = event.getRawY() - downY; float stopValue = stopX - downX; if(!mDownView.isPressed()) { forceBringBack(mDownView); return false; } boolean dismiss = false; boolean dismissRight = false; if(Math.abs(stopValue) with/4" + (Math.abs(stopValue) > (listView.getWidth() /4))); Log.d(log, "Second Comparison " + (Math.abs(stopValueY) (listView.getWidth() /4))&&(Math.abs(stopValueY) 0; if(stopValue>0) { mSwipeDetected = Action.LR; } else mSwipeDetected = Action.RL; } Log.d(log, "Action Detected is " + mSwipeDetected + " with Stop Value after dissmiss" + stopValue); if(dismiss) { if(dismissRight) mSwipeDetected = Action.LR; else mSwipeDetected = Action.RL; animate(mDownView) .translationX(dismissRight ? listView.getWidth() : - listView.getWidth()) .alpha(0) .setDuration(mAnimationTime) .setListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { } }); } else { animate(mDownView) .translationX(0) .alpha(1) .setDuration(mAnimationTime) .setListener(null); } break; } } return false; } 

Comme vous pouvez le constater, je détermine l’action effectuée dans MotionEvent.ACTION_UP et définit la valeur de Enum Action en conséquence. Cette logique fonctionne comme un charme si l’utilisateur ne franchit pas les limites de la vue liste.

Maintenant, si l’utilisateur, tout en glissant (ou spécifiquement), déplace son doigt le long de la liste, passe du bleu à l’orange, MotionEvent.ACTION_UP ne sera pas donné à listview, ce qui empêchera mon code de prendre une décision et à translationX () et setAlpha (), car aucune action n’est jamais déterminée dans ce cas, cet élément de la liste est vide.

Le problème ne s’arrête pas là, car je ne gonfle pas la vue à chaque fois, la même ligne translateX () se gonfle à chaque fois, ce qui entraîne plusieurs occurrences d’un élément de liste vide / blanc.

Y a-t-il quelque chose de possible à faire pour que, même si je n’ai pas rencontré MotionEvent.ACTION_UP, je puisse encore faire des choix?

Merci.

Vous devriez return true; dans le case MotionEvent.ACTION_DOWN: MotionEvent.ACTION_UP le MotionEvent.ACTION_UP sera traité.


Comme expliqué sur View.OnTouchListener :

Retourne :

Vrai si l’auditeur a consommé l’événement, faux sinon.

MotionEvent.ACTION_UP Ne sera pas appelé tant que MotionEvent.ACTION_DOWN s’est MotionEvent.ACTION_DOWN produit, une explication logique est qu’il est impossible qu’un ACTION_UP se produise si un ACTION_DOWN ne s’est jamais produit avant.

Cette logique permet au développeur de bloquer d’autres événements après ACTION_DOWN .

Notez également que dans certaines circonstances (par exemple, les rotations d’écran), le geste peut être annulé, auquel cas un MotionEvent.ACTION_UP ne sera PAS envoyé. Au lieu de cela, MotionEvent.ACTION_CANCEL est envoyé à la place. Par conséquent, une instruction de changement d’action normale devrait ressembler à ceci:

 switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: // check if we want to handle touch events, return true // else don't handle further touch events, return false break; // ... handle other cases case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // finish handling touch events // note that these methods won't be called if 'false' was returned // from any previous events related to the gesture break; } 

Je ne pense pas que l’ajout de return true; au cas où MotionEvent.ACTION_DOWN: finirait par résoudre le problème. Cela compliquait simplement la situation où le return false aurait pu faire le travail comme un charme.

Ce qu’il faut noter est: MotionEvent.ACTION_DOWN: /*something*/ return true; bloquera tous les rappels Listener disponibles pour la vue, même surClickListenerm, alors que correctement return false dans MotionEvent.ACTION_UP: peut aider le MotionEvent à se propager à la bonne destination.

Référence à son code source: https://github.com/romannurik/android-swipetodismiss

Comme Danpe l’a expliqué dans sa réponse concise – j’ai dû append le code ACTION_DOWN pour que ACTION_UP soit reconnu.

  case MotionEvent.ACTION_DOWN: return true; case MotionEvent.ACTION_UP: XyPos xyPos = new XyPos(); xyPos.x = last_x; xyPos.y = last_y; handleViewElementPositionUpdate(xyPos); break; 

J’ai eu la méthode onTouch (..) entière de retour quand même, donc je ne sais pas pourquoi cela ne suffisait pas … mais bon d’avoir cette solution rapide .. (merci!)