Saltar ImageView mientras arrastra. Los valores de getX () y getY () saltan

He creado un onTouchListener para arrastrar Vistas. Las imágenes se arrastran sin problemas si uso getRawX() y getRawY() . El problema es que la imagen salta al segundo puntero cuando coloca un segundo puntero hacia abajo y luego levanta el primer puntero.

Este onTouchListener intenta corregir ese problema siguiendo la pista del pointerId . El problema con este onTouchListener es mientras arrastra un ImageView, el ImageView salta alrededor bastante loco. Los getX() y getY() saltan alrededor.

Siento que estoy haciendo esto correctamente. No quiero tener que escribir una vista personalizada para esto porque ya he implementado un scaleGestureDetector y escribió un rotateGestureDetector personalizado que funciona. Todo funciona bien, pero necesito arreglar el problema que obtengo al usar getRawX() y getRawY() .

¿Alguien sabe lo que estoy haciendo mal aquí?

Aquí está mi 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); 

La cuestión era simple, pero inesperada. getRawX/Y() devuelve coordenadas absolutas, mientras que getX/Y() devuelve las coordenadas relativas a la vista. Me gustaría mover la vista, restablecer lastX/Y , y la imagen no estaría en el mismo lugar más así que cuando recibo nuevos valores que estaría fuera. En este caso sólo necesitaba donde originalmente presioné la imagen (no es el caso cuando se usa `getRawX / Y ').

Por lo tanto, la solución era simplemente eliminar lo siguiente:

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

Espero que esto ayude a alguien en el futuro, porque he visto a otros con este problema, y ​​tenían un código similar para mí (reiniciar lastX/Y )

Tengo una sugerencia y creo que va a ayudar.

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

Lo que debe usar es requestLayout() : hace el proceso de medición y diseño. & Pienso que requestLayout() será llamado cuando llamada setLayoutParams() ;

Por lo tanto, intente eliminar v.invalidate()

O intente usar el view.layout(left,top,right,bottom) lugar de configurar layoutParams.

Después de una gran cantidad de investigación, encontré que este era el problema, getRawX es absoluta y getX es relativa a la vista. Por lo tanto, utilizar esto para transformar uno a otro

 //RawX = getX + View.getX event.getRawX == event.getX(event.findPointerIndex(ptrID1))+view.getX() 
  • Disparar Evento táctil desde la vista DialogFragment a la vista de actividad principal
  • Gire la vista de disposición de androide sobre su centro usando el oyente táctil
  • Analog SetOnTouchListener o cómo se utiliza en xamarin, qué argumento debe ser
  • Arrastrar y soltar imágenes en android
  • EditText en ListView pierde foco cuando se presiona en Android 4.x
  • Imagen en lienzo con eventos táctiles
  • Android dragvable ImageVIew
  • Cómo implementar OnTouch Listener en XML
  • Reducir animadamente el tamaño del botón en la prensa y recuperar su tamaño en la versión
  • ¿Cómo puedo pasar Touch Listeners a la vista personalizada para arrastrar y soltar?
  • SwipeListView sólo un elemento abierto a la vez
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.