Drag and Drop in Android
This tutorial describes how to use drag and drop in Android. It is based on Eclipse 4.2 (Indigo), Java 1.6 and Android 4.2.
Table of Contents
As of Android 4.0 Drag and Drop of
Views
is supported. You register a listener on the View
and you define otherViews
as possible drop targets, e.g. drop zones.
To use this you register a listener on the
View
, e.g. a OnTouchListener
or a LongClickListener
.
In this method you construct an object of type
ClipData
. This object can be used to contain data which can be passed to the Views
which are defined as drop zones.
The
DragShadowBuilder
allow you specify the look of the dragging operation. Typically you pass in the View
directly, which will be shown for the drag operation.// 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; } } }
A
View
which are used as a drop zone, gets a OnDragListener
assigned via the setOnDragListener()
method. In this OnDragListener
you can evaluate the events and react accordingly.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; } }
Create a new Android project called de.vogella.android.draganddrop with an activity called DragActivity.
We are going to use XML drawables in this example.
Create the
drawable
folder in your res
directory. Create the following shape.xml
file in this folder.<?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>
Create the
shape_droptarget.xml
file in the drawable
folder.<?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>
Change the layout of your activity to the following code.
<?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>
Change your activity class to the following code.
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; } } }
If you start this activity you should be able to drag the
ImageViews
to another container.
0 comments:
Post a Comment