Drag and Drop en Android. Parte 2

David Galisteo Cantero

Finalizamos el drang and drop, en este caso vamos a examinar el código Java que hace posible la funcionalidad de la app.

Puedes ver la primera parte aquí

En primer lugar veremos el código del manifest.xml, se podría decir que es el archivo donde irá la configuración de nuestra app:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.dragdrop"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="18" />
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.dragdrop.DragActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>

Como vemos, el xml no tiene mucho que explicar, se entiende bastante bien, quizás una de las cosas que más habría que tener en cuenta sería la versión mínima de nuestro sdk, en este caso es la 16 debido a que algunas de las funciones utilizadas en el código están disponibles sólo a partir de esa versión.

Bien, ahora vamos a lo más interesante, el código Java, aunque tiene algunos comentarios en el código, explicaré algunas cosas:

package com.example.dragdrop;
import android.app.Activity;
import android.content.ClipData;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.LinearLayout;
 
public class DragActivity extends Activity {
 
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_drag);
    findViewById(R.id.imagen1).setOnTouchListener(new imgTouchListener());
    findViewById(R.id.imagen2).setOnTouchListener(new imgTouchListener());
    findViewById(R.id.left).setOnDragListener(new ContainerDragListener());
    findViewById(R.id.right).setOnDragListener(new ContainerDragListener());
  }
 
  private class imgTouchListener implements OnTouchListener {
    public boolean onTouch(View view, MotionEvent motionEvent) {
 
    	/*ACTION_DOWN -> A pressed gesture has started, the motion contains the initial position*/
      if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
        ClipData data = ClipData.newPlainText("", "");
        /*Creates an image that the system displays during the drag and drop operation. This is called a "drag shadow".*/
        DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
        view.startDrag(data, shadowBuilder, view, 0);
        /*while the img is moving, the view is invisible, if we comment this line, the view 'will move' when we drop it*/
        view.setVisibility(View.INVISIBLE);
        return true;
      } else {
        return false;
      }
    }
  }
 
 private class ContainerDragListener implements OnDragListener {
    Drawable enterShape = getResources().getDrawable(R.drawable.shape_droptarget);
    Drawable normalShape = getResources().getDrawable(R.drawable.shape);
 
    @Override
    public boolean onDrag(View v, DragEvent event) {
      int action = event.getAction();
      switch (event.getAction()) {
      case DragEvent.ACTION_DRAG_STARTED:
        // do nothing
        break;
      case DragEvent.ACTION_DRAG_ENTERED:
    	  /*change de background*/
    	  v.setBackground(enterShape);
        break;
      case DragEvent.ACTION_DRAG_EXITED:
        v.setBackground(normalShape);
        break;
      case DragEvent.ACTION_DROP:
        // Dropped, reassign View to ViewGroup
        View view = (View) event.getLocalState();
        LinearLayout oldContainer = (LinearLayout) view.getParent();
        oldContainer.removeView(view);
        LinearLayout newContainer = (LinearLayout) v;
        newContainer.addView(view);
        view.setVisibility(View.VISIBLE);
        break;
      case DragEvent.ACTION_DRAG_ENDED:
        v.setBackground(normalShape);
      default:
        break;
      }
      return true;
    }
  }
}

Para empezar, tenemos el método ‘onCreate’, que es llamado al crear la app, en él obtenemos los layouts y les añadimos un evento ‘onDragListener’, y obtenemos las imagenes, a las cuales les añadimos el evento ‘onTouchListener’. Sencillo.

A continuación tenemos la clase imgTouchListener, de la cual se creará una instancia para el evento añadido a la imagen, en ella, simplemente ‘escuchamos’ que la acción llevada a cabo es la de ‘pulsar’ la imagen, en ese caso llevamos a cabo el proceso de cambio de layout.

Por otra parte, la clase ‘ContainerDragListener’ es la encargada de cambiar el fondo de los layouts cuando arrastramos la imagen, en esta clase, el evento más importante sería ‘ACTION_DROP’, que se produce cuando soltamos la imagen en el nuevo layout, cuando se produzca ese evento, lo que haremos será eliminar la imagen (view) del antiguo layout y añadirla al nuevo.

Podemos ver una imagen de muestra, tomada mientras arrastramos una de las imágenes:
funcionamiento drag and drop

¿Qué os parece? A mi ya se me ocurre alguna app que implemente esto 🙂

Creo que quedó más o menos bien explicado, comenta si tienes alguna duda.

HackSaludos!

Publicado el 21-11-2013

Compartelo!

6 comentarios

Deja un comentario

Comentanos

*
Ir arriba de la pagina