¿Cómo implementar Arrastrar y Soltar en Android 2.2?

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"?>         

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.

  • rxwen-blog-cosas
  • android-drag-and-drop-basic

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 dropzones; private Map dropzonestates; private Map 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(); dropzonelisteners = new HashMap(); dropzonestates = new HashMap(); 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 listeners = new HashSet(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

             

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 callback 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; } } 

);