Drag and Drop

Android Drag and Drop Example

The Android System provides Drag and Drop framework, which facilitates users especially to move data from one View to another within the current layout. It is good to mention that many apps take advantage of the graphical drag and drop gesture that the system procures. The framework contains the following three components, which support drag and drop functionality:

  • Drag event class
  • Drag listeners
  • Helper methods and classes

This example shows a simple drag and drop functionality, in which an item can be moved from one View to another, but not back to first View again.

For this tutorial, we will use the following tools in a Windows 64-bit platform:

  1. JDK 1.7
  2. Eclipse 4.2 Juno
  3. Android SDK 4.4

1. Create a New Android Application Project

Open Eclipse IDE and go to File → New → Project → Android Application Project.

Fill in the name of the application, the project and the package in the appropriate fields. Also, choose as “Minimum Required SDK” the API 17 or larger and then click Next button.

DnDproject1

In the next window, the “Create Activity” option should be checked. The new activity will be the main activity of your project. Then press Next.

DnDproject2

In “Configure Launcher Icon” window you should choose the icon you want to have in your app. In our occasion, we will use the default icon of android, so just press Next.

createProject3!

Select the “Blank Activity” option and then press the Next button.

createProject4!

Specify a name for the new Activity and a name for the layout description of your app. The .xml file for the layout will automatically be created in the res/layout folder. In our occasion, we will leave the default names for both files. Press Finish.

createProject5!

The final structure of the created project is shown in the image below.

DnD_strPrj

2. Create XML drawbles

We want to make some drawables in order to distinguish the different views in the layout, when we drag and drop an item.

To make the drawables, we have fist of all to create a drawable folder in the res directory of the project, that contains these drawables.

Right click on res folder → New → Folder. Put drawable as the name of the folder, as shown in the image below and press Finish.

DnD_drawbleFolder

To make the xml files, right click on res/drawable → New → Other. In the pop up window, extend the XML folder, choose XML File and press Next.

createXmlAndrFile

Then, spesify the name of the xml file and press Finish.

createDrawable1

Open res/drawable/normal_shape.xml and paste the following code. The normal_shape.xml file will show the normal shape of the Views, before and after the drop of the item.

normal_shape.xml:

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

In the same way, right click on res/drawable → New → Other. In the pop up window, extend the XML folder, choose XML File and press Next. In addition, specify the name of the xml file and lets name it target_shape.xml.

Open res/drawable/target_shape.xml and paste the code below. The target_shape.xml file will show the shape of each View, in which the item will be displayed when it is dragged.

target_shape.xml:

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

3. Create the layout of the Main Activity

In this application the main purpose is to find out how it works drag and drop within a layout. So, in the same GridLayout, we are going to define two different LinearLayouts. The first one will contain an ImageView, which the user will drag and drop it in the second one.

Open res/layout/activity_main.xml file and paste the following.

activity_main.xml:

<?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:orientation="vertical" >

    <LinearLayout
        android:id="@+id/toplinear"
        android:layout_width="fill_parent"
        android:layout_height="170dp"
        android:background="@drawable/normal_shape"
        android:layout_marginBottom="10dp" >

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

    </LinearLayout>

    <LinearLayout
        android:id="@+id/bottomlinear"
        android:layout_width="fill_parent"
        android:layout_height="170dp"
        android:background="@drawable/normal_shape" >

        <TextView
            android:id="@+id/text"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:text="Drag the image and drop it here..." />

    </LinearLayout>

</GridLayout> 

4. Code the Main Activity

A drag and drop event occurs when a user starts dragging data, so the application tells the system to start a drag by calling startDrag() method. After that, the system calls back the application, in order to take the drag shadow, and it sends a DragEvent. If we want every View object in the layout to respond to the sending drag event, we should register a listener (onDragListener or onTouchListener) for each one or setup a callback method (onDragEvent or onTouchEvent respectively) and define other Views as possible “drop targets”. If we use both listener and callback method for the View, the system calls the listener first and then the callback, as long as the listener still handles successfully the drag event.

In our example, we will use the setOnLongClickListener() event listener along with OnDragListener(), because there are used mostly in new versions of Android.

Open src/com.javacodegeeks.android.dragndroptest/MainActivity.java file and paste the following code.

MainActivity.java:

package com.javacodegeeks.android.dragndroptest;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.graphics.drawable.Drawable;
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.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
  
	private ImageView myImage;
	private static final String IMAGEVIEW_TAG = "The Android Logo";
	
/** Called when the activity is first created. */

	@Override
  	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
    
	    setContentView(R.layout.activity_main);
	    myImage = (ImageView)findViewById(R.id.image);
	    // Sets the tag
	    myImage.setTag(IMAGEVIEW_TAG);
	    
	    // set the listener to the dragging data
	    myImage.setOnLongClickListener(new MyClickListener());
	   
	    findViewById(R.id.toplinear).setOnDragListener(new MyDragListener());
	    findViewById(R.id.bottomlinear).setOnDragListener(new MyDragListener());
	
	}

	private final class MyClickListener implements OnLongClickListener {

	    // called when the item is long-clicked
		@Override
		public boolean onLongClick(View view) {
		// TODO Auto-generated method stub
		
			// create it from the object's tag
			ClipData.Item item = new ClipData.Item((CharSequence)view.getTag());

	        String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN };
	        ClipData data = new ClipData(view.getTag().toString(), mimeTypes, item);
	        DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
	   
	        view.startDrag( data, //data to be dragged
	        				shadowBuilder, //drag shadow
	        				view, //local data about the drag and drop operation
	        				0   //no needed flags
	        			  );
	        
	        
	        view.setVisibility(View.INVISIBLE);
	        return true;
		}	
	}

	class MyDragListener implements OnDragListener {
		Drawable normalShape = getResources().getDrawable(R.drawable.normal_shape);
		Drawable targetShape = getResources().getDrawable(R.drawable.target_shape);

		@Override
		public boolean onDrag(View v, DragEvent event) {
	  
			// Handles each of the expected events
		    switch (event.getAction()) {
		    
		    //signal for the start of a drag and drop operation.
		    case DragEvent.ACTION_DRAG_STARTED:
		        // do nothing
		        break;
		        
		    //the drag point has entered the bounding box of the View
		    case DragEvent.ACTION_DRAG_ENTERED:
		        v.setBackground(targetShape);	//change the shape of the view
		        break;
		        
		    //the user has moved the drag shadow outside the bounding box of the View
		    case DragEvent.ACTION_DRAG_EXITED:
		        v.setBackground(normalShape);	//change the shape of the view back to normal
		        break;
		        
		    //drag shadow has been released,the drag point is within the bounding box of the View
		    case DragEvent.ACTION_DROP:
		        // if the view is the bottomlinear, we accept the drag item
		    	  if(v == findViewById(R.id.bottomlinear)) {
		    		  View view = (View) event.getLocalState();
		    		  ViewGroup viewgroup = (ViewGroup) view.getParent();
		    		  viewgroup.removeView(view);
		        
		    		  //change the text
		    		  TextView text = (TextView) v.findViewById(R.id.text);
		    		  text.setText("The item is dropped");
		           
		    		  LinearLayout containView = (LinearLayout) v;
		    		  containView.addView(view);
		    		  view.setVisibility(View.VISIBLE);
		    	  } else {
		    		  View view = (View) event.getLocalState();
		    		  view.setVisibility(View.VISIBLE);
		    		  Context context = getApplicationContext();
		    		  Toast.makeText(context, "You can't drop the image here", 
                                                 Toast.LENGTH_LONG).show();
		    		  break;
		    	   }
		    	  break;
		    	  
		    //the drag and drop operation has concluded.
		    case DragEvent.ACTION_DRAG_ENDED:
		        v.setBackground(normalShape);	//go back to normal shape
		    
		    default:
		        break;
		    }
		    return true;
		}
	}
}

As you can notice in the code above, for the dragging data you can use the ClipData or the ClipData.Item, which contains data that is dropped to the “target-drop” Views. The ClipData object includes ClipDescription, which stores important meta-data about the clip. In addition, DragShadowBuilder is used in order to display an image during the drag and drop operation.

As we mentioned above, in this application we want to drag and drop an item only in one View, but not back to the previous one. Also, we want to change the shape of each chosen “target drop” View, when the drag shadow gets in it’s bounding box. For these reasons, we added some code in the appropriate actions of the DragEvent, as you can see in the MainActivity.java file.

5. Run the application

To run our application, right click on our project → Run as → Android Application. The AVD will appear with the app loaded. The image below shows the screen of the application.

DND_AVD1

Now, left and right click to the image and drag it to the view with the text “Drag the image and drop it here…”. You will see how it’s shape is changing and that is happening because the ACTION_DRAG_ENTERED is called.

DND_AVD2

Then drop the image to that View. The ACTION_DROP is called in that situation. You can notice that the image is successfully been dropped into the View and the text changed.

DND_AVD3

If we try to drag and drop the image into the previous view, the message “You can’t drop the image here” will appear. Nevertheless the ACTION_DROP is called again, we decided to exclude this View of “drop-target” views, as we mentioned.

DND_AVD4

Download Eclipse Project

This was an example of Drag and Drop in Android. Download the Eclipse Project of this example: DragNDropTest.zip

Katerina Zamani

Katerina has graduated from the Department of Informatics and Telecommunications in National and Kapodistrian University of Athens (NKUA) and she attends MSc courses in Advanced Information Systems at the same department. Currently, her main academic interests focus on web applications, mobile development, software engineering, databases and telecommunications.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Luciano
Luciano
6 years ago

Doesnt work

Back to top button