android - soltar - Saltando ImageView mientras arrastra. Los valores getX() y getY() están saltando
drag and drop android studio example (3)
Creé un onTouchListener para arrastrar vistas. Las imágenes se arrastran suavemente si uso getRawX()
y getRawY()
. El problema con eso es que la imagen saltará al segundo puntero cuando coloque un segundo puntero hacia abajo y luego levante el primer puntero.
Este onTouchListener intenta solucionar ese problema haciendo un seguimiento del pointerId
. El problema con esto en TouchListener es al arrastrar un ImageView, el ImageView salta bastante locamente. Los getX()
y getY()
brincan.
Siento que estoy haciendo esto correctamente. No quiero tener que escribir una vista personalizada para esto porque ya he implementado un scaleGestureDetector y escribí un rotateGestureDetector personalizado que funciona. Todo funciona bien, pero necesito solucionar el problema que tengo cuando uso 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);
Tengo un consejo y creo que ayudará.
invalidate() : does only redrawing a view,doesn''t change view size/position.
Lo que debe usar es requestLayout()
: el proceso de medición y diseño. y creo que requestLayout()
se llamará cuando call setLayoutParams()
;
Por lo tanto, intente eliminar v.invalidate()
o intente utilizar el view.layout(left,top,right,bottom)
lugar de establecer layoutParams.
El problema fue simple, pero inesperado. getRawX/Y()
devuelve coordenadas absolutas, mientras que getX/Y()
devuelve coordenadas relativas a la vista. lastX/Y
la vista, restablecería la lastX/Y
, y la imagen ya no estaría en el mismo lugar, así que cuando obtenga nuevos valores estarían desconectados. En este caso, solo necesité el lugar donde originalmente presioné la imagen (no es el caso cuando uso `getRawX / Y '').
Entonces, la solución fue 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 a mí (restableciendo la lastX/Y
)
Después de mucha investigación, descubrí que este es el problema, getRawX es absoluto y getX es relativo a la vista. por lo tanto, use esto para transformar uno a otro
//RawX = getX + View.getX
event.getRawX == event.getX(event.findPointerIndex(ptrID1))+view.getX()