Utilisation du Drag and Drop avec Android

Lars Vogel

Traducteur

ram-0000

Cet article va vous montrer comment utiliser les opérations de Drag and Drop sous Android.

NDT La traduction française « glisser et déposer » du concept « Drag and Drop » en anglais n'a pas été utilisée dans cet article.

Les commentaires et les suggestions d'amélioration sont les bienvenus, alors, après votre lecture, n'hésitez pas. Commentez . ♪

- Titre : Utilisation du Drag and Drop avec Android

- Auteur : Lars Vogel

- Traducteur : ram-0000

- Parution : 22 août 2013

- Licence : Le contenu de cet article est rédigé par Lars Vogel et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 3.0 non transposé. Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright ® 2013 Developpez.com.

Sommaire

- I. Drag and Drop avec Android

- I-A. Comment faire ?

- I-B. Implémentation

- II. Exercice

- II-A. Création du projet

- II-B. Création des « drawable » XML

- II-C. L'activité et son aspect

- III. Quelques liens

- III-A. Code source

- III-B. Ressources Android

- IV. Remerciements

I - Drag and Drop avec Android

I-A - Comment faire ?

Depuis Android version 4.0, le drag and drop des vues est supporté. Vous enregistrez un écouteur (listener) sur la vue qui peut être source du drag et vous définissez les autres vues comme destinations potentielles (ou drop zones).

I-B - Implémentation

Pour faire cela, il faut enregistrer un écouteur sur la vue avec OnTouchListener ou OnLongClickListener.

Dans cette méthode, vous construisez un objet du type ClipData. Cet objet peut être utilisé pour contenir des données à passer aux vues définies comme drop zones.

L'objet DragShadowBuilder vous permet de spécifier le look de l'opération drag. En général, vous passez directement en paramètre la vue qui va être montrée pour l'opération drag.

// Assign the touch listener to your view which you want to move
findViewById(R.id.myimage1).setOnTouchListener(new MyTouchListener());

// This defines your touch listener
private final class MyTouchListener implements OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
}

Les vues qui sont utilisées comme une zone de drop possèdent un objet OnDragListener attribué par la méthode setOnDragListener. Dans l'objet OnDragListener, vous pouvez récupérer les événements et réagir en conséquence.

findViewById(R.id.bottomright).setOnDragListener(new MyDragListener());

class MyDragListener 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:
v.setBackgroundDrawable(enterShape);
break;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundDrawable(normalShape);
break;
case DragEvent.ACTION_DROP:
// Dropped, reassign View to ViewGroup
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) v;
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
v.setBackgroundDrawable(normalShape);
default:
break;
}
return true;
}
}

II - Exercice

II-A - Création du projet

Créez un nouveau projet nommé de.vogella.android.draganddrop avec une activité nommée DragActivity.

II-B - Création des « drawable » XML

Nous allons utiliser des objets XML « drawables » dans cet exemple.

Créez le répertoire « drawable » dans celui des ressources « res ». Créez le fichier « shape.xml » suivant dans ce répertoire :

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

<stroke
android:width="2dp"
android:color="#FFFFFFFF" />

<gradient
android:angle="225"
android:endColor="#DD2ECCFA"
android:startColor="#DD000000" />

<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />

</shape>

Créez le fichier « shape_droptarget.xml » dans le répertoire « drawable » :

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >

<stroke
android:width="2dp"
android:color="#FFFF0000" />

<gradient
android:angle="225"
android:endColor="#DD2ECCFA"
android:startColor="#DD000000" />

<corners
android:bottomLeftRadius="7dp"
android:bottomRightRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />

</shape>

II-C - L'activité et son aspect

Modifiez l'aspect de votre activité en utilisant le code suivant :

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="2"
android:columnWidth="300dp"
android:orientation="vertical"
android:rowCount="2"
android:stretchMode="columnWidth" >

<LinearLayout
android:id="@+id/topleft"
android:layout_width="160dp"
android:layout_height="200dp"
android:layout_column="0"
android:layout_row="0"
android:background="@drawable/shape" >

<ImageView
android:id="@+id/myimage1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_row="0"
android:src="@drawable/ic_launcher" />
</LinearLayout>

<LinearLayout
android:id="@+id/topright"
android:layout_width="160dp"
android:layout_height="200dp"
android:layout_column="1"
android:layout_row="0"
android:background="@drawable/shape" >

<ImageView
android:id="@+id/myimage2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_row="0"
android:src="@drawable/ic_launcher" />
</LinearLayout>

<LinearLayout
android:id="@+id/bottomleft"
android:layout_width="160dp"
android:layout_height="200dp"
android:layout_column="0"
android:layout_row="1"
android:background="@drawable/shape" >

<ImageView
android:id="@+id/myimage3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>

<LinearLayout
android:id="@+id/bottomright"
android:layout_width="160dp"
android:layout_height="200dp"
android:layout_column="1"
android:layout_row="1"
android:background="@drawable/shape" >

<ImageView
android:id="@+id/myimage4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_row="0"
android:src="@drawable/ic_launcher" />
</LinearLayout>

</GridLayout>

Modifiez le source de votre activité en utilisant le code suivant :

package de.vogella.android.draganddrop;

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 {

/** Called when the activity is first created. */

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.myimage1).setOnTouchListener(new MyTouchListener());
findViewById(R.id.myimage2).setOnTouchListener(new MyTouchListener());
findViewById(R.id.myimage3).setOnTouchListener(new MyTouchListener());
findViewById(R.id.myimage4).setOnTouchListener(new MyTouchListener());
findViewById(R.id.topleft).setOnDragListener(new MyDragListener());
findViewById(R.id.topright).setOnDragListener(new MyDragListener());
findViewById(R.id.bottomleft).setOnDragListener(new MyDragListener());
findViewById(R.id.bottomright).setOnDragListener(new MyDragListener());

}

private final class MyTouchListener implements OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
} else {
return false;
}
}
}

class MyDragListener 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:
v.setBackgroundDrawable(enterShape);
break;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundDrawable(normalShape);
break;
case DragEvent.ACTION_DROP:
// Dropped, reassign View to ViewGroup
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
LinearLayout container = (LinearLayout) v;
container.addView(view);
view.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
v.setBackgroundDrawable(normalShape);
default:
break;
}
return true;
}
}
}

Si vous lancez votre activité, vous devrez être capable de faire un drag des images vers un autre conteneur.

III - Quelques liens

III-A - Code source

- Codes source d'exemple

III-B - Ressources Android

- Android Dialogs standard documentation.

- Tutoriel sur le développement Android avec Android Studio et Eclipse

IV - Remerciements

Nous remercions l'auteur, Lars Vogel, de nous avoir aimablement autorisés à publier son article. Cet article est une traduction autorisée dont le texte original peut être trouvé sur vogella.com. Nous remercions aussi ram-0000 pour sa traduction, Feanorin pour sa relecture technique ainsi que milkoseck pour sa relecture orthographique.