Wednesday, April 4, 2012

Introduce Drag And Drop for Android 3.0+

Start from Android 3.0, API Level 11, Android support Drag and Drop natually. With the Android drag/drop framework, you can allow your users to move data from one View to another View in the current layout using a graphical drag and drop gesture. The framework includes a drag event class, drag listeners, and helper methods and classes.

It's a example show how to handle the basic operation of Drag And Drop. User can drag the button1~4 over buttonTarget. As a example, it do nothing except display the events in a TextView.

Introduce Drag And Drop for Android 3.0+

A common View.OnDragListener, MyDragEventListener, is implement for all view listen to the Darg and Drop operation.

When a view (button1~4) is onLongClick, it start the Drag And Drop by calling startDrag().

Then a event of ACTION_DRAG_STARTED will be passed to the OnDragListener of all view with setOnDragListener. In order to accept it, all view should return true; otherwise it will not receive any other event in current Drap And Drop operation.

When user Drop it on any involved view, event of ACTION_DROP will be passed to the landing view. And finally, ACTION_END will passed to all involved views.

package com.exercise.com;

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.widget.Button;
import android.widget.TextView;

public class AndroidDragAndDropActivity extends Activity {

Button button1, button2, button3, button4, buttonTarget;
Button dragSourceButton;
TextView comments;

String commentMsg;

MyDragEventListener myDragEventListener = new MyDragEventListener();

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1 = (Button)findViewById(R.id.button1);
button2 = (Button)findViewById(R.id.button2);
button3 = (Button)findViewById(R.id.button3);
button4 = (Button)findViewById(R.id.button4);
buttonTarget = (Button)findViewById(R.id.buttonTarget);
comments = (TextView)findViewById(R.id.comments);

// Create and set the tags for the Buttons
final String BUTTON1_TAG = "button1";
final String BUTTON2_TAG = "button2";
final String BUTTON3_TAG = "button3";
final String BUTTON4_TAG = "button4";
button1.setTag(BUTTON1_TAG);
button2.setTag(BUTTON2_TAG);
button3.setTag(BUTTON3_TAG);
button4.setTag(BUTTON4_TAG);

button1.setOnLongClickListener(sourceButtonsLongClickListener);
button2.setOnLongClickListener(sourceButtonsLongClickListener);
button3.setOnLongClickListener(sourceButtonsLongClickListener);
button4.setOnLongClickListener(sourceButtonsLongClickListener);

button1.setOnDragListener(myDragEventListener);
button2.setOnDragListener(myDragEventListener);
button3.setOnDragListener(myDragEventListener);
button4.setOnDragListener(myDragEventListener);
buttonTarget.setOnDragListener(myDragEventListener);
}

Button.OnLongClickListener sourceButtonsLongClickListener
= new Button.OnLongClickListener(){

@Override
public boolean onLongClick(View v) {
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] clipDescription = {ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData dragData = new ClipData((CharSequence)v.getTag(),
clipDescription,
item);
DragShadowBuilder myShadow = new MyDragShadowBuilder(v);

v.startDrag(dragData,
myShadow,
null,
0);

commentMsg = v.getTag() + " : onLongClick.\n";
comments.setText(commentMsg);

return true;
}};

private static class MyDragShadowBuilder extends View.DragShadowBuilder {
private static Drawable shadow;

public MyDragShadowBuilder(View v) {
super(v);
shadow = new ColorDrawable(Color.LTGRAY);
}

@Override
public void onProvideShadowMetrics (Point size, Point touch){
int width = getView().getWidth();
int height = getView().getHeight();

shadow.setBounds(0, 0, width, height);
size.set(width, height);
touch.set(width / 2, height / 2);
}

@Override
public void onDrawShadow(Canvas canvas) {
shadow.draw(canvas);
}

}

protected class MyDragEventListener implements View.OnDragListener {

@Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();

switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
//All involved view accept ACTION_DRAG_STARTED for MIMETYPE_TEXT_PLAIN
if (event.getClipDescription()
.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN))
{
commentMsg += ((Button)v).getText()
+ " : ACTION_DRAG_STARTED accepted.\n";
comments.setText(commentMsg);
return true; //Accept
}else{
commentMsg += ((Button)v).getText()
+ " : ACTION_DRAG_STARTED rejected.\n";
comments.setText(commentMsg);
return false; //reject
}
case DragEvent.ACTION_DRAG_ENTERED:
commentMsg += ((Button)v).getText() + " : ACTION_DRAG_ENTERED.\n";
comments.setText(commentMsg);
return true;
case DragEvent.ACTION_DRAG_LOCATION:
commentMsg += ((Button)v).getText() + " : ACTION_DRAG_LOCATION - "
+ event.getX() + " : " + event.getY() + "\n";
comments.setText(commentMsg);
return true;
case DragEvent.ACTION_DRAG_EXITED:
commentMsg += ((Button)v).getText() + " : ACTION_DRAG_EXITED.\n";
comments.setText(commentMsg);
return true;
case DragEvent.ACTION_DROP:
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0);

commentMsg += ((Button)v).getText() + " : ACTION_DROP"
+ " - from " + item.getText().toString() + "\n";
comments.setText(commentMsg);

return true;
case DragEvent.ACTION_DRAG_ENDED:
if (event.getResult()){
commentMsg += ((Button)v).getText() + " : ACTION_DRAG_ENDED - success.\n";
comments.setText(commentMsg);
} else {
commentMsg += ((Button)v).getText() + " : ACTION_DRAG_ENDED - fail.\n";
comments.setText(commentMsg);
};
return true;
default: //unknown case
commentMsg += ((Button)v).getText() + " : UNKNOWN !!!\n";
comments.setText(commentMsg);
return false;

}

}}

}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Drag Source" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#FF0000"
android:text="Red" />
<Button
android:id="@+id/button2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00FF00"
android:text="Green" />
<Button
android:id="@+id/button3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#0000FF"
android:text="Blue" />
<Button
android:id="@+id/button4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#A0A0A0"
android:text="Gray" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Drop Target"
android:layout_gravity="center" />
<Button
android:id="@+id/buttonTarget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#404040"
android:text="Dark Gray" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/comments"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>


Download the files.

Next:
- Passing object in Drap And Drop using myLocalState



2 comments:

tanu said...

its not working...and the download file doesn't work

Anonymous said...

Just copied the code into Eclipse.

It works perfectly.

Tanu is an incompetent moron.