ejemplo - ¿Cómo implementar Arrastrar y Soltar en Android 2.2?
drag and drop list android example (4)
Estoy tratando de desarrollar una aplicación para Android, donde el usuario debería ser capaz de arrastrar imágenes desde una celda de una grilla a otra. Para implementar esto, necesito la API de arrastrar y soltar que se introdujo en Android 3.0, pero mi aplicación debería ejecutarse en Android 2.2. Entonces, ¿hay alguna manera de implementar esto usando Touch events? En caso afirmativo, proporcione un fragmento de código o un enlace que lo describa brevemente.
TouchEvent: TouchDown -> LockItemOnTouchPoint
FollowTouchDirections -> UpdateItemPosition
TouchEvent: TouchUp -> LockItemPosition
Hola después de mucho tiempo a obtener el éxito de hacer la función de arrastrar y soltar en Android 2.2
aquí le doy mi código que le da el éxito. Mi clase principal está aquí
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;
}
}
Después de esto, crea una clase y extiende tu diseño principal como Relative Lay out
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);
}
}
Y el archivo Principal Mi Xml
<?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>
ahora estoy feliz de haber hecho mi trabajo y también feliz porque estoy satisfecho con mi trabajo espero que esto te ayude. y el enlace que me da el camino está a continuación.
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>
Tengo algo de inspiración de MobileAnarchyWidget pero mejoro algunas cosas.
Como puede ver, utilizo PopupWindow para crear una parte visual de dragEfect even i clone desde el objeto que se puede arrastrar. Además, no tengo que usar ninguna parte del diseño. Simple ponga DragDropManager.class en su proyecto. No se necesitan cambios Sin recursos adicionales. Se pueden atacar más zonas a la vez si una zona llena / cubre parcialmente otra. Puede arrastrar cualquier cosa que sea al menos vista. Cambio la devolución de llamada en la ventana de Actividad para que cuando arrastre algo, nada más tenga acceso a los eventos. En esta solución, nunca pierde el foco de Draggable y también cuando levanta el dedo de la pantalla, DragDrop terminará automáticamente (Control de recuperación de actividad para devoluciones de llamadas).
No tengo tiempo para mostrarte todas las combinaciones para usar. Pero como pueden ver, hay un solo DropZoneListener. Puede usar más, pero recuerde que se llama a todos los oyentes y todos los estados de arrastre cambiados se envían a cada oyente.
ejemplo: Dropzones D1, D2; Oyente L1, L2;
si D1 o D2 cambiaron L1 (Dx) y L2 (Dx)
si D1 y D2 cambiaron L1 (D1, D2) y L2 (D1, D2)
Pero es bueno porque sabes si se deja caer en otro lugar. Y me olvido de que DragItem es un Objeto, así que cuando se descarta, debe resolver el tipo de objeto. Pero esto también es bueno porque cuando usas fragmentos nunca sabes qué tipo de datos se pueden arrastrar.
En mi solución, verifico el nivel de tipo de objeto. Si objeto no es compatible con dragzone de lo que sabrá.
view.setOnTouchListener (new View.OnTouchListener () {
public boolean onTouch(View v, MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_MOVE) {
v.setX(me.getRawX() - (v.getWidth() / 2));
v.setY(me.getRawY() - (float)(v.getHeight()* 1.5 / 2));
}
return true;
}
}
);