Este tutorial es bastante simple, consta de un RelativeLayout que hemos llamado 'marco' el cual ocupa toda la pantalla y un ImageView que es el objeto que arrastraremos con el dedo. El marco se podría hacer más pequeño y la imagen solo se arrastraría sobre esa superficie. También se podrían añadir las objetos y mover el deseado. En mi caso trabajo con un Samsung Galaxy S3 y podría mover hasta 5 objetos a la vez ya que reconoce 5 puntos táctiles a la vez. Sin embargo podríamos poner tantos objetos como quisiéramos aunque habría que mover los de uno en uno o en grupos pequeños.
Primerpo os presento como sería el código .XML como veis solo consta de un objeto, RelativeLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:id="@+id/marco"> </RelativeLayout>
Una vez tengamos este archivo listo vamos al código Java como siempre totalmente comentado. Si hubiera alguna duda, no olvidéis en preguntar en el apartado de Comentarios:
//Implementamos directamente el Listener a la clase public class MainActivity extends Activity implements View.OnTouchListener{ //Definimos el marco por el cual podemos arrastrar la imagen private ViewGroup marco; //Definimos la imagen que vasmo arrastrar private ImageView imagen; //Variables para centrar la imagen bajo el dedo private int xDelta; private int yDelta; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Relacionamos marco = (ViewGroup)findViewById(R.id.marco); //Creamos la imagen imagen = new ImageView(this); //Señalamos la imagen a mostrar imagen.setImageResource(R.drawable.ic_launcher); //Añadimos el Listener de la clase imagen.setOnTouchListener(this); //Añadimos la imagen al marco marco.addView(imagen); } //Al tocar la pantalla... public boolean onTouch(View view, MotionEvent event) { //Recogemos las coordenadas del dedo final int X = (int) event.getRawX(); final int Y = (int) event.getRawY(); //Dependiendo de la accion recogida.. switch (event.getAction() & MotionEvent.ACTION_MASK) { //Al tocar la pantalla case MotionEvent.ACTION_DOWN: //Recogemos los parametros de la imagen que hemo tocado RelativeLayout.LayoutParams Params = (RelativeLayout.LayoutParams) view.getLayoutParams(); xDelta = X - Params.leftMargin; yDelta = Y - Params.topMargin; break; case MotionEvent.ACTION_UP: //Al levantar el dedo simplemento mostramos un mensaje Toast.makeText(this, "Soltamos", Toast.LENGTH_LONG).show(); break; case MotionEvent.ACTION_POINTER_DOWN: //No hace falta utilizarlo break; case MotionEvent.ACTION_POINTER_UP: //No hace falta utilizarlo break; case MotionEvent.ACTION_MOVE: //Al mover el dedo vamos actualizando //los margenes de la imagen para //crear efecto de arrastrado RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); layoutParams.leftMargin = X - xDelta; layoutParams.topMargin = Y - yDelta; //Qutamos un poco de margen para //que la imagen no se deforme //al llegar al final de la pantalla y pueda ir más allá //probar también el codigo omitiendo estas dos líneas layoutParams.rightMargin = -50; layoutParams.bottomMargin = -50; //le añadimos los nuevos //parametros para mover la imagen view.setLayoutParams(layoutParams); break; } //Se podría decir que 'dibujamos' //la posición de la imagen en el marco. marco.invalidate(); return true; }}
Publico este vídeo para que podáis ver el resultado:
Muchas gracias por todo! no olvidéis comentar!
Buen blog, Victor,
ResponderEliminar¿tienes idea de como se podría hacer para mover todos los elementos del viewGroup simultaneamente? (Por ej. un par de TextView y un ImageView a la vez)
Saludos
No he probado, pero supongo que si metes todo lo que quieres mover a la vez en un layout y lo tratas como a la imagen de este tutorial lo haría.
EliminarNo sé si llego a tiempo, o qué... pero si haces esto funciona para mover varios objetos a la vez... además el LinearLayout se repite... por que así creas dos intancias, con lo que consigues mover (en este caso) dos objetos por un lado y otros dos por otro:
EliminarLinearLayout linear;
linear = new LinearLayout(this);
//linear.set
// Relacionamos
marco = (ViewGroup) findViewById(R.id.marco);
// Creamos la imagen
imagen = new ImageView(this);
// Señalamos la imagen a mostrar
imagen.setImageResource(R.drawable.ic_launcher);
linear.addView(imagen);
// Creamos la imagen
imagen = new ImageView(this);
// Señalamos la imagen a mostrar
imagen.setImageResource(R.drawable.bt_info);
linear.addView(imagen);
// Añadimos el Listener de la clase
linear.setOnTouchListener(this);
// Añadimos la imagen al marco
marco.addView(linear);
linear = new LinearLayout(this);
// Creamos la imagen
imagen = new ImageView(this);
// Señalamos la imagen a mostrar
imagen.setImageResource(R.drawable.ic_launcher);
linear.addView(imagen);
// Creamos la imagen
imagen = new ImageView(this);
// Señalamos la imagen a mostrar
imagen.setImageResource(R.drawable.bt_info);
linear.addView(imagen);
// Añadimos el Listener de la clase
linear.setOnTouchListener(this);
// Añadimos la imagen al marco
marco.addView(linear);
Hola, muy buen y simple tutorial.
ResponderEliminarMi duda es cómo saber en qué posición se ha soltado la imagen (trabajo con la API 8, por lo que no puedo utilizar view.getX() o view.getY()).
Gracias
Fenomeno. código muy comentado y simple. Gracias!
ResponderEliminarGracias!
EliminarEl código y tutorial, muy bien, pero me duelen los ojos desde que leí uviera en lugar de hubiera...
ResponderEliminargracias de todos modos
jajaja ya esta editado muchas gracias.
Eliminarcomo lo haces 2 o mas imagenes?
ResponderEliminarBuenisimo tutorial!!!!
ResponderEliminarUna pregunta... ¿como hago si tengo dos imagenes que cuando haga el ACTION_DOWN, la que seleccione quede siempre por encima de la otra cuando la mueva? Muchas gracias! Un saludo
Buenas. ¿como podria guardar la nueva posicion en un XML y que lo leyera correctamente la proxima vez que se ejecute?
ResponderEliminarHola,
ResponderEliminarMuy interesante el código y su explicación. Vereis estoy haciendo un ejercicio en el que tengo como imagen de fondo un semáforo, entonces me gustaría hacer que según pulses en una luz o en otra aparezca una pantalla con un mensaje o con otro, pero no sé cómo hacerlo, es decir ¿cómo puedo saber que estoy tocando la parte de la imagen referente a la luz roja?
Muchas, gracias.
Un saludo.
Muchas gracias :)
ResponderEliminarY si quiera poder ampliar y reducir la imagen como seria?
ResponderEliminarpor separado puedo hacerlo, es decir muevo bien y hago zoom con los dedos pero si junto todo no funciona.
Útil y fácil, gracias ;)
ResponderEliminarmuy buen tutorial..pero disculpa, soy principiante..me gustaría saber el codigo para arrastrar una imagen a un contenedor y una vez estando en contenedor arroje una imagen como respuesta..me podrias ayudar por favor.
ResponderEliminarpublic class MainActivity extends ActionBarActivity implements OnTouchListener {
ResponderEliminarTextView text;
ViewGroup marco;
ImageView imagen;
private int xDelta;
private int yDelta;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.coordenada);
marco = (ViewGroup) findViewById(R.id.container);
imagen = new ImageView(this);
imagen.setImageResource(R.drawable.ic_launcher);
imagen.setOnTouchListener(this);
marco.addView(imagen);
}
public boolean onTouch(View view, MotionEvent event){
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_UP:
Toast.makeText(this, "Soltamos", Toast.LENGTH_LONG).show();
break;
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams Params = (RelativeLayout.LayoutParams) view.getLayoutParams();
xDelta = X - Params.leftMargin;
yDelta = Y - Params.topMargin;
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - xDelta;
layoutParams.topMargin = Y - yDelta;
text.setText("X:"+(X - xDelta)+";Y:"+(Y - yDelta));
view.setLayoutParams(layoutParams);
break;
}
marco.invalidate();
return true;
}
public class MainActivity extends Activity implements OnTouchListener{
ResponderEliminar//Definimos el marco por el cual podemos arrastrar la imagen
private ViewGroup marco;
//Definimos la imagen que vasmo arrastrar
private ImageView imagen;
//Variables para centrar la imagen bajo el dedo
private int xDelta;
private int yDelta;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Relacionamos
marco = (ViewGroup)findViewById(R.id.marco);
tv = (TextView) findViewById(R.id.textView1);
//Creamos la imagen
imagen = new ImageView(this);
//Señalamos la imagen a mostrar
imagen.setImageResource(R.drawable.ic_launcher);
//Añadimos el Listener de la clase
imagen.setOnTouchListener(this);
//Añadimos la imagen al marco
marco.addView(imagen);
}
//Al tocar la pantalla...
public boolean onTouch(View view, MotionEvent event) {
//Recogemos las coordenadas del dedo
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
//Dependiendo de la accion recogida..
switch (event.getAction() & MotionEvent.ACTION_MASK) {
//Al tocar la pantalla
case MotionEvent.ACTION_DOWN:
//Recogemos los parametros de la imagen que hemo tocado
RelativeLayout.LayoutParams Params =
(RelativeLayout.LayoutParams) view.getLayoutParams();
xDelta = X - Params.leftMargin;
yDelta = Y - Params.topMargin;
break;
case MotionEvent.ACTION_UP:
//Al levantar el dedo simplemento mostramos un mensaje
Toast.makeText(this, "Soltamos", Toast.LENGTH_LONG).show();
break;
case MotionEvent.ACTION_POINTER_DOWN:
//No hace falta utilizarlo
break;
case MotionEvent.ACTION_POINTER_UP:
//No hace falta utilizarlo
break;
case MotionEvent.ACTION_MOVE:
//Al mover el dedo vamos actualizando
//los margenes de la imagen para
//crear efecto de arrastrado
RelativeLayout.LayoutParams layoutParams =
(RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - xDelta;
layoutParams.topMargin = Y - yDelta;
//Qutamos un poco de margen para
//que la imagen no se deforme
//al llegar al final de la pantalla y pueda ir más allá
//probar también el codigo omitiendo estas dos líneas
layoutParams.rightMargin = -50;
layoutParams.bottomMargin = -50;
//le añadimos los nuevos
//parametros para mover la imagen
view.setLayoutParams(layoutParams);
tv.setText("X:"+X+" Y:"+Y);
break;
}
//Se podría decir que 'dibujamos'
//la posición de la imagen en el marco.
marco.invalidate();
return true;
}}
Muy Buen tuto, explicas perfectamente en cada método lo que hace.
ResponderEliminarpero, ¿si quisiera moverla al tocar sobre la pantalla?, que si toco a la derecha de la imagen, se desplace a la derecha.
Muito Obrigado por ajudar!! Estava procurando por isso faz dias.
ResponderEliminarObrigado!
como hago para ajustar la imagen a mi imageView
ResponderEliminar