How to implement Drag and Drop in Android 2.2?
I am trying to develop an Android application where the user needs to be able to drag and drop images from one grid cell to another. To implement this, I need the Drag and Drop API, which was introduced in Android 3.0, but my app needs to work in Android 2.2. So, is there a way to implement this using Touch events? If so, please provide me with a code snippet or any link that briefly describes it.
source to share
Hi after a long time, get success by doing drag and drop in android 2.2
here i give my code which gives you success. My main class is here
package info.tempDD;
import android.app.Activity;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class TempDDActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
private View selected_item = null;
private int offset_x = 0;
private int offset_y = 0;
Boolean touchFlag=false;
boolean dropFlag=false;
LayoutParams imageParams;
ImageView imageDrop,image1,image2;
int crashX,crashY;
Drawable dropDrawable,selectDrawable;
Rect dropRect,selectRect;
int topy,leftX,rightX,bottomY;
int dropArray[];
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
ViewGroup container = (ViewGroup) findViewById(R.id.container);
imageDrop=(ImageView) findViewById(R.id.ImgDrop);
image1=(ImageView) findViewById(R.id.img);
image2=(ImageView) findViewById(R.id.img2);
container.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
if(touchFlag==true)
{
System.err.println("Display If Part ::->"+touchFlag);
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN :
topy=imageDrop.getTop();
leftX=imageDrop.getLeft();
rightX=imageDrop.getRight();
bottomY=imageDrop.getBottom();
System.err.println("Display Top-->"+topy);
System.err.println("Display Left-->"+leftX);
System.err.println("Display Right-->"+rightX);
System.err.println("Display Bottom-->"+bottomY);
//opRect.
break;
case MotionEvent.ACTION_MOVE:
crashX=(int) event.getX();
crashY=(int) event.getY();
System.err.println("Display Here X Value-->"+crashX);
System.err.println("Display Here Y Value-->"+crashY);
int x = (int) event.getX() - offset_x;
int y = (int) event.getY() - offset_y;
//int w = getWindowManager().getDefaultDisplay().getWidth() - 100;
//int h = getWindowManager().getDefaultDisplay().getHeight() - 100;
int w = getWindowManager().getDefaultDisplay().getWidth() - 50;
int h = getWindowManager().getDefaultDisplay().getHeight() - 10;
if (x > w)
x = w;
if (y > h)
y = h;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(new ViewGroup.MarginLayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
lp.setMargins(x, y, 0, 0);
//Drop Image Here
if(crashX > leftX && crashX < rightX && crashY > topy && crashY < bottomY )
{
Drawable temp=selected_item.getBackground();
imageDrop.setBackgroundDrawable(temp);
imageDrop.bringToFront();
dropFlag=true;
selected_item.setVisibility(View.INVISIBLE);
}
//Drop Image Here
selected_item.setLayoutParams(lp);
break;
case MotionEvent.ACTION_UP:
//
touchFlag=false;
if(dropFlag==true)
{
dropFlag=false;
}
else
{
selected_item.setLayoutParams(imageParams);
}
break;
default:
break;
}
}else
{
System.err.println("Display Else Part ::->"+touchFlag);
}
return true;
}
});
image1.setOnTouchListener(this);
image2.setOnTouchListener(this);
}
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
touchFlag=true;
offset_x = (int) event.getX();
offset_y = (int) event.getY();
selected_item = v;
imageParams=v.getLayoutParams();
break;
case MotionEvent.ACTION_UP:
selected_item=null;
touchFlag=false;
break;
default:
break;
}
return false;
}
}
After that create one class and extend your main layout like RelativeLayout
package info.tempDD;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
public class TouchInterceptor extends RelativeLayout {
public TouchInterceptor(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
}
And the Main My Xml file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/ImgDrop"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:layout_marginTop="50dp"
android:background="#FFFFFF" >
</ImageView>
<ImageView
android:id="@+id/img"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:background="@drawable/ic_launcher" >
</ImageView>
<ImageView
android:id="@+id/img2"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@drawable/ic_launcher" >
</ImageView>
</RelativeLayout>
ok now i'm happy i did my job and also happy because i'm happy with my job. Hope this helps you. and the link that gives me the way is below.
source to share
DragDropManager.class
package com.example.dragdrop;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.PopupWindow;
public class DragDropManager
{
private static DragDropManager instance;
private Activity mActivity;
private List<View> dropzones;
private Map<View, Integer> dropzonestates;
private Map<View, DropZoneListener> dropzonelisteners;
private PopupWindow popoup;
private MotionEvent firstEvent;
private Rect rect;
private Object item;
public static DragDropManager getInstance()
{
if (instance == null) instance = new DragDropManager();
return instance;
}
private DragDropManager()
{
}
public void init(Activity a)
{
mActivity = a;
dropzones = new ArrayList<View>();
dropzonelisteners = new HashMap<View, DropZoneListener>();
dropzonestates = new HashMap<View, Integer>();
rect = new Rect();
}
public void addDropZone(View zone, DropZoneListener zonelistener)
{
dropzones.add(zone);
dropzonelisteners.put(zone, zonelistener);
dropzonestates.put(zone, 0);
}
public void clearZones()
{
dropzones.clear();
dropzonelisteners.clear();
dropzonestates.clear();
}
public void clearZone(View zone)
{
dropzones.remove(zone);
dropzonelisteners.remove(zone);
dropzonestates.remove(zone);
}
private void checkDropZones(MotionEvent event)
{
boolean isOver;
HashSet<DropZoneListener> listeners = new HashSet<DropZoneListener>(dropzonelisteners.values());
for (View zone : dropzones)
{
int[] location = new int[2];
zone.getLocationInWindow(location);
zone.getDrawingRect(rect);
rect.offset(location[0], location[1]);
isOver = rect.contains((int) event.getRawX(), (int) event.getRawY());
switch (dropzonestates.get(zone))
{
case 0:
if (isOver)
{
for(DropZoneListener listener:listeners)
{
listener.OnDragZoneEntered(zone, item);
}
dropzonestates.put(zone, 1);
}
break;
case 1:
if (!isOver)
{
for(DropZoneListener listener:listeners)
{
listener.OnDragZoneLeft(zone, item);
}
dropzonestates.put(zone, 0);
}
else if (isOver && event.getAction()==MotionEvent.ACTION_UP)
{
for(DropZoneListener listener:listeners)
{
listener.OnDropped(zone, item);
}
dropzonestates.put(zone, 0);
}
break;
}
}
}
public void startDragging(final View dragView, Object item)
{
this.item = item;
// Copy view Bitmap (Clone Object visual)
ImageView view = new ImageView(mActivity);
view.measure(dragView.getWidth(), dragView.getHeight());
Bitmap returnedBitmap = Bitmap.createBitmap(dragView.getWidth(), dragView.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
dragView.draw(canvas);
view.setBackgroundDrawable(new BitmapDrawable(dragView.getResources(), returnedBitmap));
// Set up Window
popoup = new PopupWindow(view, dragView.getWidth(), dragView.getHeight());
popoup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
// set window at position
int[] location = new int[2];
dragView.getLocationInWindow(location);
popoup.showAtLocation(mActivity.getWindow().getDecorView(), Gravity.NO_GRAVITY, location[0], location[1]);
// Switch call Backs
callbackDefault = mActivity.getWindow().getCallback();
mActivity.getWindow().setCallback(callback);
}
private android.view.Window.Callback callbackDefault;
private android.view.Window.Callback callback = new android.view.Window.Callback()
{
@Override
public boolean dispatchGenericMotionEvent(MotionEvent event)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
checkDropZones(event);
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
// popoup.update((int)event.getRawX(), (int)event.getRawY(), -1,
// -1);
}
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
if (firstEvent == null) firstEvent = MotionEvent.obtain(event);
// Log.v("EVENT","X:"+event.getRawX() + " _X:" + location[0] +
// " __X:" + firstEvent.getRawX());
// Log.v("EVENT","Y:"+event.getRawY() + " _Y:" + location[1] +
// " __Y:" + firstEvent.getRawY());
float pos_x = event.getRawX() + (-popoup.getWidth() / 2);
float pos_y = event.getRawY() + (-popoup.getHeight() / 2);
popoup.update((int) pos_x, (int) pos_y, -1, -1);
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
popoup.dismiss();
mActivity.getWindow().setCallback(callbackDefault);
}
return false;
}
@Override
public boolean dispatchTrackballEvent(MotionEvent event)
{
return false;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onActionModeFinished(ActionMode mode)
{
// TODO Auto-generated method stub
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onActionModeStarted(ActionMode mode)
{
// TODO Auto-generated method stub
}
@Override
public void onAttachedToWindow()
{
// TODO Auto-generated method stub
}
@Override
public void onContentChanged()
{
// TODO Auto-generated method stub
}
@Override
public boolean onCreatePanelMenu(int featureId, Menu menu)
{
// TODO Auto-generated method stub
return false;
}
@Override
public View onCreatePanelView(int featureId)
{
// TODO Auto-generated method stub
return null;
}
@Override
public void onDetachedFromWindow()
{
// TODO Auto-generated method stub
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onMenuOpened(int featureId, Menu menu)
{
// TODO Auto-generated method stub
return false;
}
@Override
public void onPanelClosed(int featureId, Menu menu)
{
// TODO Auto-generated method stub
}
@Override
public boolean onPreparePanel(int featureId, View view, Menu menu)
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onSearchRequested()
{
// TODO Auto-generated method stub
return false;
}
@Override
public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams attrs)
{
// TODO Auto-generated method stub
}
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
// TODO Auto-generated method stub
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public ActionMode onWindowStartingActionMode(Callback callback)
{
// TODO Auto-generated method stub
return null;
}
};
public interface DropZoneListener
{
void OnDragZoneEntered(View zone, Object item);
void OnDragZoneLeft(View zone, Object item);
void OnDropped(View zone, Object item);
}
}
MainActivity.class
package com.example.dragdrop;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.example.dragdrop.DragDropManager.DropZoneListener;
public class MainActivity extends Activity implements OnLongClickListener, OnTouchListener
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DragDropManager.getInstance().init(this);
Button b1 = (Button) findViewById(R.id.button1);
Button b2 = (Button) findViewById(R.id.button2);
Button b3 = (Button) findViewById(R.id.button3);
EditText et1 = (EditText) findViewById(R.id.editText1);
TextView tv1 = (TextView) findViewById(R.id.textView1);
Button b4 = (Button) findViewById(R.id.button4);
Button b5 = (Button) findViewById(R.id.button5);
Button b6 = (Button) findViewById(R.id.button6);
b1.setOnTouchListener(this);
b2.setOnLongClickListener(this);
b3.setOnTouchListener(this);
et1.setOnTouchListener(this);
tv1.setOnTouchListener(this);
DragDropManager.getInstance().addDropZone(b4, dropZoneListener1);
DragDropManager.getInstance().addDropZone(b5, dropZoneListener1);
DragDropManager.getInstance().addDropZone(b6, dropZoneListener1);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
DropZoneListener dropZoneListener1 = new DropZoneListener()
{
@Override
public void OnDropped(View zone, Object item)
{
Log.v("ddddd","drop time");
switch(zone.getId())
{
case R.id.button4:
if (item instanceof String)
((Button)zone).setText("DROP ITEM OK");
else
((Button)zone).setText("DROP ITEM ERR");
break;
case R.id.button5:
((Button)zone).setText("DROP");
break;
case R.id.button6:
if (item instanceof Integer)
((Button)zone).setText("DROP ITEM OK");
else
((Button)zone).setText("DROP ITEM ERR");
break;
}
}
@Override
public void OnDragZoneLeft(View zone, Object item)
{
switch(zone.getId())
{
case R.id.button4:
((Button)zone).setText("LEFT");
break;
case R.id.button5:
((Button)zone).setText("LEFT");
break;
case R.id.button6:
((Button)zone).setText("LEFT");
break;
}
}
@Override
public void OnDragZoneEntered(View zone, Object item)
{
switch(zone.getId())
{
case R.id.button4:
if (item instanceof String)
((Button)zone).setText("ENTER ITEM OK");
else
((Button)zone).setText("ENTER ITEM ERR");
break;
case R.id.button5:
((Button)zone).setText("ENTER");
break;
case R.id.button6:
if (item instanceof Integer)
((Button)zone).setText("ENTER ITEM OK");
else
((Button)zone).setText("ENTER ITEM ERR");
break;
}
}
};
@Override
public boolean onLongClick(View v)
{
DragDropManager.getInstance().startDragging(v, 0);
return false;
}
@Override
public boolean onTouch(View v, MotionEvent event)
{
DragDropManager.getInstance().startDragging(v, "String");
return false;
}
}
activity_main.xml
<RelativeLayout 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"
tools:context=".MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="14dp"
android:text="Click" />
<Button
android:id="@+id/button2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="29dp"
android:text="Long" />
<Button
android:id="@+id/button3"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignLeft="@+id/button2"
android:layout_below="@+id/button2"
android:layout_marginTop="16dp"
android:text="Click" />
<Button
android:id="@+id/button6"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_alignTop="@+id/button3"
android:layout_marginLeft="39dp"
android:layout_toRightOf="@+id/button3"
android:text="Drop3" />
<Button
android:id="@+id/button5"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignLeft="@+id/button4"
android:layout_centerVertical="true"
android:text="Drop2" />
<Button
android:id="@+id/button4"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_above="@+id/button5"
android:layout_alignParentRight="true"
android:layout_marginBottom="35dp"
android:layout_marginRight="20dp"
android:text="Drop1" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button3"
android:layout_below="@+id/button3"
android:layout_marginTop="17dp"
android:ems="10" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/button6"
android:layout_alignParentLeft="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
I have some inspiration from MobileAnarchyWidget, but I am improving some things.
As you can see, I am using PopupWindow to create dragEfect, even I am cloning the visual from the dragged object. Also I don't need to use any part of the layout. Easy transfer of DragDropManager.class to your project. No changes required. No additional resources required. In case one zone is filled / partially covered by another, you can press several zones at once. You can drag and drop anything, at least on the view. I am switching the callback to the Activity window, so when you drag and drop something, something else doesn't have access to events. In this solution, you never lost focus from Draggable, and also when you select UP finger from the screen, DragDrop exits automatically (Activity regains control for callbacks).
I don't have time to show you all the combinations. But as you can see there is one single DropZoneListener. You can use more, but remember that all listeners are called and all changed drag states are passed to each listener.
Example: Dropzones D1, D2; Listener L1, L2;
if D1 or D2 is changed L1 (Dx) and L2 (Dx)
if D1 and D2 are changed L1 (D1, D2) and L2 (D1, D2)
But that's good, because you know if it fell somewhere else. And I forgot that DragItem is an Object, so when casting you have to resolve to the type of the object. But it's also good, because when you use slices, you never know what data to drag and drop.
In my solution, I check the object type level. If the object is not supported by dragzone, you know.
source to share