Android Drag and Drop Example

0

In this article, we will see an example of android’s drag and drop feature. Using drag and drop, we can move data from one View to another View. The framework mainly includes a DragEvent class, drag listeners of type OnDragListener and helper method startDrag.

Let’s start building a simple drag and drop feature using the -android provided framework classes.

Main Layout

Our example consists of two text items ‘Item1’ and ‘Item2’ which are in their own layouts. We want to drag the items from one layer and drop into another layer.

welcome.xml:

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="1"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/top_layout"
        android:layout_width="match_parent"
        android:layout_height="100sp"
        android:background="@drawable/normal_drawable"
        android:orientation="vertical"
        android:padding="20sp" >

        <TextView
            android:id="@+id/item1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/item1" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/bottom_layout"
        android:layout_width="match_parent"
        android:layout_height="100sp"
        android:background="@drawable/normal_drawable"
        android:orientation="vertical"
        android:padding="20sp" >

        <TextView
            android:id="@+id/item2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/item2" />
    </LinearLayout>

    <TextView
        android:id="@+id/drag_status"
        android:layout_column="0"
        android:layout_gravity="left|center_vertical"
        android:layout_row="1"
        android:text="@string/drag_status" />

</GridLayout>

Differentiate normal and drag state

We want to differentiate the views as we start dragging and dropping.

We want one kind of drawable for the normal case where we are not dragging or for the case when we had just left the layer. Likewise, we want another style of drawable for the view as we start dragging the item or when we have entered another layer.
To make the drawables, create normal_state.xml and drage_state.xml and add color element in each file representing different colors .

normal_state.xml:

<?xml version="1.0" encoding="UTF-8"?>
<color 
    xmlns:android="http://schemas.android.com/apk/res/android"
	android:color="#7B68EE" />

drag_state.xml:

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

Steps to build drag and drop feature

  1. Recognize a dragging gesture: User makes some gesture that you recognize as a signal to start dragging data. In our case, we will make the text items listen on OnLongClickListener to recognize the drag gesture.
  2. Let system know dragging started: Once we receive the signal, we start the drag process by calling startDragging
  3. Register drag event listeners: Components interested in the drag events must implement drag event listener class View.OnDragListener. You set the drag event listener object for a View with the View object’s setOnDragListener() method.
  4. Include the data you want to move: When you start a drag, you include both the data you are moving and metadata describing this data as part of the call to the system
  5. System sends DragEvents: As you drag, the system sends drag events to the drag event listeners
  6. Respond to each drag event: Respond to each drag event. DragEvent‘s action code represents the drag state.
  7. Respond to drop event: When we drop the item, DragEvent‘s action code will be ACTION_DROP In our case, the views registered for the drag events respond by removing the text from its parent view and adding it to the view being dropped at.

DragNDropExample:

package com.javarticles.dragndrop;

import com.jopc.sandbox.R;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

public class DragNDropExample extends Activity {
	private TextView dragStatus;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.welcome);
		TextView item1 = (TextView) findViewById(R.id.item1);
		TextView item2 = (TextView) findViewById(R.id.item2);
		dragStatus = (TextView) findViewById(R.id.drag_status);
		dragStatus.setLines(10);
		item1.setText("Item1 in Top Layer");
		item2.setText("Item2 in Bottom Layer");
		
		item1.setTag("Item1");
		item2.setTag("Item2");
		
		item1.setOnLongClickListener(new LongClickListener());
		item2.setOnLongClickListener(new LongClickListener());
		
		LinearLayout topLayer = (LinearLayout) findViewById(R.id.top_layout);
		LinearLayout bottomLayer = (LinearLayout) findViewById(R.id.bottom_layout);
		
		topLayer.setOnDragListener(new DragListener());
		bottomLayer.setOnDragListener(new DragListener());
		
		topLayer.setTag("Top Layer");
		bottomLayer.setTag("Bottom Layer");
	}
	
	private class LongClickListener implements OnLongClickListener {
		@Override
		public boolean onLongClick(View v) {
			ClipData.Item item = new ClipData.Item((String)v.getTag());
			String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN };
			ClipData data = new ClipData((String) v.getTag(), mimeTypes, item);
			DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
			v.startDrag(data, shadowBuilder, v, 0);
			i = 1;
			dragStatus.setText(i + ": " + v.getTag() + "'s Drag Started");
			return true;
		}		
	}
	
	private class DragListener implements OnDragListener {

		@Override
		public boolean onDrag(View v, DragEvent event) {
			switch(event.getAction()) {
			case DragEvent.ACTION_DRAG_ENTERED:
				v.setBackgroundResource(R.drawable.drag_state);				
				appendText("Drag Status: " + v.getTag() + "'s drag entered");
				break;
			case DragEvent.ACTION_DRAG_EXITED:
				v.setBackgroundResource(R.drawable.normal_state);
				appendText("Drag Status: " + v.getTag() + "'s drag exited");
				break;
			case DragEvent.ACTION_DRAG_ENDED:
				v.setBackgroundResource(R.drawable.normal_state);
				appendText("Drag Status: " + v.getTag() + "'s drag ended");
				break;
			case DragEvent.ACTION_DROP:
				TextView textDropped = (TextView) event.getLocalState();
				textDropped.setVisibility(View.VISIBLE);
				ViewGroup viewDroppedAt = (ViewGroup) v;
				((ViewGroup) textDropped.getParent()).removeView(textDropped);
				
				if (v.getId() == R.id.bottom_layout) {
					if (textDropped.getId() == R.id.item1) {
						textDropped.setText("Item1 in bottom layer");
					} else if (textDropped.getId() == R.id.item2) {
						textDropped.setText("Item2 in bottom layer");
					}					
				} else if (v.getId() == R.id.top_layout) {
					if (textDropped.getId() == R.id.item1) {
						textDropped.setText("Item1 in top layer");
					} else if (textDropped.getId() == R.id.item2) {
						textDropped.setText("Item2 in top layer");
					}
				}
				viewDroppedAt.addView(textDropped);
				appendText("Drag Status: " + textDropped.getTag() + " dropped");
			}
			return true;
		}		
	}
	
	private void appendText(String s) {
		i++;
		dragStatus.setText(dragStatus.getText() + "\n" + i + ": " + s);
	}
	
	private int i = 1;
}

Run the application

Our main page consists of two text fields in two different layers. The top most layer contains Item1 and the bottom layer contains Item2. Both the items are draggable. For example, we can drag Item1 and drop in the bottom layer. Likewise, we can drag Item2 and drop in the top layer.

Drag N Drop

Drag N Drop

We will now drag Item2. You can see the different events in the text field below the Item2.

Drag Item2

Drag Item2

Drop Item2 in Item1’s layout.

Drop Item2

Drop Item2

Download source code

This was an example about Android’s Drag and Drop feature. You can download the source code here: dragNDropExample.zip

Share.

Comments are closed.