6

Ich habe einen onTouchListener zum Ziehen von Ansichten erstellt. Bilder ziehen reibungslos, wenn ich getRawX() und verwende. Das Problem dabei ist, dass das Bild zum zweiten Zeiger springt, wenn Sie einen zweiten Zeiger nach unten setzen und dann den ersten Zeiger anheben.Springen ImageView beim Ziehen. getX() und getY() Werte springen

Dieser onTouchListener versucht, dieses Problem zu beheben, indem er die pointerId verfolgt. Das Problem mit diesem onTouchListener ist beim Ziehen eines ImageViews, das ImageView springt ziemlich irre herum. Die Werte getX() und getY() springen umher.

Ich fühle mich wie ich das richtig mache. Ich möchte nicht eine benutzerdefinierte Ansicht dafür schreiben müssen, weil ich bereits einen scaleGestureDetector implementiert und einen benutzerdefinierten rotateGestureDetector geschrieben habe, der funktioniert. Alles funktioniert gut, aber ich muss das Problem beheben, das ich bekomme, wenn ich getRawX() und benutze.

Weiß jemand, was ich hier falsch mache?

Hier ist meine onTouchListener:

final View.OnTouchListener onTouchListener = new View.OnTouchListener() 
{ 
    @Override 
    public boolean onTouch(View v, MotionEvent event) 
    { 
     relativeLayoutParams = (RelativeLayout.LayoutParams) v.getLayoutParams(); 

     final int action = event.getAction(); 
     switch (action & MotionEvent.ACTION_MASK) 
     { 
      case MotionEvent.ACTION_DOWN: 
      { 
       final float x = event.getX(); 
       final float y = event.getY(); 

       // Where the user started the drag 
       lastX = x; 
       lastY = y; 
       activePointerId = event.getPointerId(0); 
       break; 
      } 
      case MotionEvent.ACTION_MOVE: 
      { 
       // Where the user's finger is during the drag 
       final int pointerIndex = event.findPointerIndex(activePointerId); 
       final float x = event.getX(pointerIndex); 
       final float y = event.getY(pointerIndex); 

       // Calculate change in x and change in y 
       final float dx = x - lastX; 
       final float dy = y - lastY; 

       // Update the margins to move the view 
       relativeLayoutParams.leftMargin += dx; 
       relativeLayoutParams.topMargin += dy; 
       v.setLayoutParams(relativeLayoutParams); 

       // Save where the user's finger was for the next ACTION_MOVE 
       lastX = x; 
       lastY = y; 

       v.invalidate(); 
       break; 
      } 
      case MotionEvent.ACTION_UP: 
      { 
       activePointerId = INVALID_POINTER_ID; 
       break; 
      } 
      case MotionEvent.ACTION_CANCEL: 
      { 
       activePointerId = INVALID_POINTER_ID; 
       break; 
      } 
      case MotionEvent.ACTION_POINTER_UP: 
      { 
       // Extract the index of the pointer that left the touch sensor 
       final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
       final int pointerId = event.getPointerId(pointerIndex); 

       if(pointerId == activePointerId) 
       { 
        // This was our active pointer going up. Choose a new 
        // active pointer and adjust accordingly 
        final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
        lastX = (int) event.getX(newPointerIndex); 
        lastY = (int) event.getY(newPointerIndex); 
        activePointerId = event.getPointerId(newPointerIndex); 
       } 
       break; 
      } 
     } 
     return true; 
    } 
}; 
image1.setOnTouchListener(onTouchListener); 
+0

Hat jemand eine Lösung? Scheint so, als wären andere auf dieses Problem gestoßen, aber ich habe noch keine Lösung gefunden. –

Antwort

10

Das Problem war einfach, aber unerwartet. getRawX/Y() gibt absolute Koordinaten zurück, während getX/Y() Koordinaten relativ zur Ansicht zurückgibt. Ich würde die Ansicht verschieben, lastX/Y zurücksetzen, und das Bild wäre nicht mehr an der gleichen Stelle, wenn ich also neue Werte erhalte, wären sie weg. In diesem Fall brauchte ich nur wo ich ursprünglich drückte das Bild (nicht der Fall bei der Verwendung von `getRawX/Y ').

So war die Lösung einfach entfernen Sie die folgenden Schritte aus:

// Save where the user's finger was for the next ACTION_MOVE 
lastX = x; 
lastY = y; 

Ich hoffe, das jemand in der Zukunft helfen wird, weil ich andere mit diesem Problem gesehen haben, und sie hatten mir einen ähnlichen Code (Zurücksetzen lastX/Y)

+0

Froh, dass ich das gefunden habe! Ich vermute, dass viele Leute Code zum Speichern der LastX/LastY haben, weil sie http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html gelesen haben. Offensichtlich unterscheidet sich die Situation beim Verschieben einer Ansicht von dem Beispiel in "Multitouch", wo eine Leinwand übersetzt wird. Der letzte Kommentar hier, http://stackoverflow.com/questions/16676097/android-getx-gety-interleaves-relate-absolute-coordinates?rq=1, stellt fest, dass, wenn er die Einstellung von view.setX() und auskommentierte view.setY(), das Interleaving von absoluten und relativen Koordinaten während onTouch() gestoppt. –

+0

@ T.Folsom Ich bin froh, dass ich helfen konnte! Ja, viele Leute modellieren ihren Code nach dem ersten Link, ich selbst eingeschlossen. Soweit ich weiß, geben 'getX()' und 'getY()' immer relative Koordinaten zurück. Seine Koordinaten springen aus dem gleichen Grund wie ich. Er verschiebt die Ansicht und erhält dann verschiedene relative Koordinaten, da sich die Ansicht verschoben hat. Ist das sinnvoll? –

+0

Ja, das hat mehr Menschen geholfen :) – Nate

0

Ich habe eine Spitze & denke, es wird sicher helfen.

invalidate() : does only redrawing a view,doesn't change view size/position. 

Was Sie verwenden sollten, ist requestLayout(): funktioniert die Mess- und Layout-Prozess. & Ich denke, requestLayout() wird aufgerufen, wenn Anruf setLayoutParams();

Versuchen Sie also von v.invalidate()

entfernen oder versuchen view.layout(left,top,right,bottom) Methode anstelle der Einstellung layoutParams verwenden.

+0

Ich habe versucht, 'v.invalidate()' in der Vergangenheit zu entfernen (versuchte es gerade jetzt, seit du es vorgeschlagen hast), da ich dachte, dass es in diesem Szenario nutzlos ist, hilft aber auch nicht. Ich habe versucht, es durch 'v.requestLayout()' zu ersetzen, und das änderte das Verhalten auch nicht:/Irgendwelche anderen Vorschläge? –

+0

keine Würfel mit 'forceLayout()' entweder –

+0

oder versuchen Sie mit View.layout (links, oben, rechts, unten) Methode anstelle von LayoutParams. – vakman

0

Nach viel Forschung, fand ich dies das Problem, getRawX ist absolut und getX ist relativ zu sehen. Verwenden Sie dies um einen zu einem anderen zu transformieren

//RawX = getX + View.getX 

event.getRawX == event.getX(event.findPointerIndex(ptrID1))+view.getX() 
Verwandte Themen