para - manual de programacion android pdf
¿Cómo intercambiar dos vistas de imágenes usando arrastrar y soltar en Android? (1)
He intentado implementar un simple arrastrar y soltar en Android, donde el elemento arrastrado intercambia posiciones con el elemento en el que se soltó.
Implementé con éxito los oyentes onLongClick y onDrag. Cuando arrastro y coloco un artículo, este reemplaza al elemento en el que se colocó, pero no puedo entender cómo hacer que el elemento reemplazado ocupe el lugar del elemento arrastrado.
Pasé un tiempo buscando respuestas, pero la mayoría de las respuestas solo vinculó implementaciones complejas de arrastrar y soltar que implican muchos archivos con muchos códigos, y no pude entenderlos lo suficiente como para aplicarlos a mi código.
Originalmente asumí que no obtenía una copia fiel de ImageView con
ImageView temp = (ImageView) event.getLocalState();
así que lo intenté
ImageView dragged = (ImageView) findViewById(temp.getId());
pero eso no hizo la diferencia.
Estoy casi seguro de que el problema está en ''OnDragListener'', en el ''caso DragEvent.ACTION_DROP:''. Aquí está mi código (de Main.java):
public class Main extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.ball1).setOnLongClickListener(listenClick);
findViewById(R.id.ball1).setOnDragListener(listenDrag);
findViewById(R.id.target1).setOnLongClickListener(listenClick);
findViewById(R.id.target1).setOnDragListener(listenDrag);
findViewById(R.id.target2).setOnDragListener(listenDrag);
findViewById(R.id.target2).setOnLongClickListener(listenClick);
findViewById(R.id.target3).setOnDragListener(listenDrag);
findViewById(R.id.target3).setOnLongClickListener(listenClick);
View.OnLongClickListener listenClick = new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View v)
{
ClipData data = ClipData.newPlainText("","");
DragShadow dragShadow = new DragShadow(v);
v.startDrag(data, dragShadow, v, 0);
return false;
}
};
private class DragShadow extends View.DragShadowBuilder
{
ColorDrawable greyBox;
public DragShadow(View view)
{
super(view);
greyBox = new ColorDrawable(Color.LTGRAY);
}
@Override
public void onDrawShadow(Canvas canvas)
{
greyBox.draw(canvas);
}
@Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint)
{
View v = getView();
int height = (int) v.getHeight();
int width = (int) v.getWidth();
greyBox.setBounds(0, 0, width, height);
shadowSize.set(width, height);
shadowTouchPoint.set((int)width/2, (int)height/2);
}
}
View.OnDragListener listenDrag = new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event)
{
int dragEvent = event.getAction();
switch (dragEvent)
{
case DragEvent.ACTION_DRAG_ENTERED:
Log.i("Drag Event", "Entered");
break;
case DragEvent.ACTION_DRAG_EXITED:
Log.i("Drag Event", "Exited");
break;
case DragEvent.ACTION_DROP:
ImageView target = (ImageView) v;
ImageView temp = (ImageView) event.getLocalState();
ImageView dragged = (ImageView) findViewById(temp.getId());
target.setId(dragged.getId());
target.setImageDrawable(dragged.getDrawable());
dragged.setId(temp.getId());
dragged.setImageDrawable(temp.getDrawable());
break;
}
return true;
}
};
Si alguien me puede decir por qué el setImageDrawable funciona en el objetivo, pero no en el arrastre, le estaré muy agradecido.
Una de las grandes alegrías de estar en Ciencias de la Computación es aprender humildad. Al menos el 90% de las veces, la respuesta a la búsqueda: "¿Por qué no funciona?" es que le dijiste a la computadora que hiciera algo incorrecto.
En "caso DragEvent.ACTION_DROP:" estaba obteniendo referencias a ambas vistas. Lo que no me estaba dando cuenta por alguna razón es que cuando lo hice
target.setImageDrawable(dragged.getDrawable());
También estaba cambiando el dibujable de temperatura, ya que la temperatura se refería a la vista real. Por eso cuando lo hice
dragged.setImageDrawable(temp.getDrawable());
De hecho, solo estaba configurando el dibujo arrastrado de lo que originalmente era. Aquí está el código corregido.
case DragEvent.ACTION_DROP:
ImageView target = (ImageView) v;
ImageView dragged = (ImageView) event.getLocalState();
Drawable target_draw = target.getDrawable();
Drawable dragged_draw = dragged.getDrawable();
dragged.setImageDrawable(target_draw);
target.setImageDrawable(dragged_draw);
break;