Tuesday, January 6, 2015

Android Drag and Drop example

This example show how to implement Drag and Drop on Android, to move ImageView between two LinearLayout.


To use Drag and Drop on Android, minSdkVersion in AndroidManifest.xml have to be 11 or higher.

Create /res/values/arrays.xml to define drawables in our ImageViews.
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <array name="resicon">
        <item>@android:drawable/ic_dialog_alert</item>
        <item>@android:drawable/ic_dialog_dialer</item>
        <item>@android:drawable/ic_dialog_email</item>
        <item>@android:drawable/ic_dialog_info</item>
        <item>@android:drawable/ic_dialog_map</item>
    </array>

</resources>

/res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="4dp"
    tools:context="com.example.androiddraganddrop.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:background="#202020"
            android:orientation="horizontal" >

            <LinearLayout
                android:id="@+id/area1"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:layout_margin="4dp"
                android:background="#404040"
                android:orientation="vertical" >
            </LinearLayout>

            <LinearLayout
                android:id="@+id/area2"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:layout_margin="4dp"
                android:background="#606060"
                android:orientation="vertical" >
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/prompt"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/black"
                android:textColor="@android:color/white"
                android:gravity="bottom" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

MainActivity.java
package com.example.androiddraganddrop;

import android.support.v7.app.ActionBarActivity;
import android.text.method.ScrollingMovementMethod;
import android.content.ClipData;
import android.content.res.TypedArray;
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.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

 LinearLayout area1, area2;
 TextView prompt;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  area1 = (LinearLayout) findViewById(R.id.area1);
  area2 = (LinearLayout) findViewById(R.id.area2);

  prompt = (TextView) findViewById(R.id.prompt);
  // make TextView scrollable
  prompt.setMovementMethod(new ScrollingMovementMethod());
  //clear prompt area if LongClick
  prompt.setOnLongClickListener(new OnLongClickListener(){

   @Override
   public boolean onLongClick(View v) {
    prompt.setText("");
    return true;
   }});

  TypedArray arrayResources = getResources().obtainTypedArray(
    R.array.resicon);

  for (int i = 0; i < arrayResources.length(); i++) {
   ImageView imageView = new ImageView(this);
   imageView.setImageDrawable(arrayResources.getDrawable(i));
   imageView.setOnLongClickListener(myOnLongClickListener);
   area1.addView(imageView);
  }

  arrayResources.recycle();
  
  area1.setOnDragListener(myOnDragListener);
  area2.setOnDragListener(myOnDragListener);
 }

 OnLongClickListener myOnLongClickListener = new OnLongClickListener() {

  @Override
  public boolean onLongClick(View v) {
   ClipData data = ClipData.newPlainText("", "");
   DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
   v.startDrag(data, shadowBuilder, v, 0);
   //v.setVisibility(View.INVISIBLE);
   return true;
  }

 };

 OnDragListener myOnDragListener = new OnDragListener() {
  
  @Override
  public boolean onDrag(View v, DragEvent event) {
   
   String area;
   if(v == area1){
    area = "area1";
   }else if(v == area2){
    area = "area2";
   }else{
    area = "unknown";
   }
   
   switch (event.getAction()) {
   case DragEvent.ACTION_DRAG_STARTED:
    prompt.append("ACTION_DRAG_STARTED: " + area  + "\n");
    break;
   case DragEvent.ACTION_DRAG_ENTERED:
    prompt.append("ACTION_DRAG_ENTERED: " + area  + "\n");
    break;
   case DragEvent.ACTION_DRAG_EXITED:
    prompt.append("ACTION_DRAG_EXITED: " + area  + "\n");
    break;
   case DragEvent.ACTION_DROP:
    prompt.append("ACTION_DROP: " + area  + "\n");
    View view = (View)event.getLocalState();
    LinearLayout oldParent = (LinearLayout)view.getParent();
    oldParent.removeView(view);
    LinearLayout newParent = (LinearLayout)v;
    newParent.addView(view);
    break;
   case DragEvent.ACTION_DRAG_ENDED:
    prompt.append("ACTION_DRAG_ENDED: " + area  + "\n");
   default:
    break;
   }
   return true;
  }

 };
}



download filesDownload the files.

More example of Drag and Drop
Drag and Drop items between ListView
- Improved Drag and Drop items between ListView
Drag and Drop items between ListView, with OnDragListener on ListView cells
Drag and Drop between ListView and GridView

5 comments:

Scott said...

Great example! I added a vibration of 75ms ((Vibrator) v.getContext().getSystemService(Context.VIBRATOR_SERVICE)).vibrate(75); and made the image GONE and then VISIBLE and it's a fantastic effect. Much easier than I imagined.

Makes me wonder now how to drop a view in the middle of a list instead of just into the parent view in general.

Andr.oid Eric said...

hello Scott,

thanks for your comment:)

Maybe my next example is to drap and drop between ListView too. But I also have no idea currently how to drop in middle of ListView.

民凯 said...

hi fren,

if i wan to do something like as below :
1) remain icon on left hand side layout when start drag.
2) can drag as many icon from left to right, after drop, show dialog box.
3) when open apps, remain the icon on right layout.

are u fren able to do this ? i still finding something like those three question.

thank you.

Μενελαος Πετουσης said...

Great Tutorial and very helpfull !!
I implemented this also for OnTouchListener instead of OnLongClickListener to be more quickly !!!

Keep going men !!!

Luciano Amarante said...

Hello.

I am Luciano, I found your example of DRAG and DROP on the internet and I'm trying to change to a new instance where I have 3 areas and the images begin in area 3 and can only go to the area 1 and can not go to area 2, and so you can accept one image in each area.
So I ask help to your code source for esto Will not succeeding to usalo.