No se puede arrastrar y soltar una imagen simple en el estudio android

Estoy tratando de crear una simple arrastrar y soltar la imagen en el estudio de Android. Puedo obtener la imagen para arrastrar por la pantalla, desaparece tan pronto como lo suelte. En la consola, obtengo un resultado de informe "drop: false"

Aquí está mi código:

ImageView mImageView; String mString; private android.widget.RelativeLayout.LayoutParams mLayoutParams; mImageView.setOnLongClickListener(new View.OnLongClickListener(){ @Override public boolean onLongClick(View v){ ClipData.Item item = new ClipData.Item((CharSequence)v.getTag()); String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN }; ClipData dragData = new ClipData(v.getTag().toString(), mimeTypes, item); View.DragShadowBuilder myShadow = new View.DragShadowBuilder(mImageView); v.startDrag(dragData, myShadow, null, 0); return true; } }); mImageView.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { switch(event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: mLayoutParams = (RelativeLayout.LayoutParams)v.getLayoutParams(); Log.d(mString, "Action is DragEvent.ACTION_DRAG_STARTED"); // Do nothing break; case DragEvent.ACTION_DRAG_ENTERED: Log.d(mString, "Action is DragEvent.ACTION_DRAG_ENTERED"); int x_cord = (int) event.getX(); int y_cord = (int) event.getY(); break; case DragEvent.ACTION_DRAG_EXITED : Log.d(mString, "Action is DragEvent.ACTION_DRAG_EXITED"); x_cord = (int) event.getX(); y_cord = (int) event.getY(); mLayoutParams.leftMargin = x_cord; mLayoutParams.topMargin = y_cord; v.setLayoutParams(mLayoutParams); break; case DragEvent.ACTION_DRAG_LOCATION : Log.d(mString, "Action is DragEvent.ACTION_DRAG_LOCATION"); x_cord = (int) event.getX(); y_cord = (int) event.getY(); break; case DragEvent.ACTION_DRAG_ENDED : Log.d(mString, "Action is DragEvent.ACTION_DRAG_ENDED"); // Do nothing break; case DragEvent.ACTION_DROP: Log.d(mString, "ACTION_DROP event"); // Do nothing break; default: break; } return true; } }); mImageView.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { ClipData data = ClipData.newPlainText("", ""); View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(mImageView); mImageView.startDrag(data, shadowBuilder, mImageView, 0); mImageView.setVisibility(View.INVISIBLE); return true; } else { return false; } } }); } 

}

Editado: Cambiado con un ejemplo de cómo mover todas las vistas contenidas en un RelativeLayout usando onTouch. Creo que el evento onDrag se aplica mejor para arrastrar y soltar elementos de datos, no para mover vistas.

 public class MainActivity extends AppCompatActivity implements View.OnTouchListener { private RelativeLayout mRelLay; private float mInitialX, mInitialY; private int mInitialLeft, mInitialTop; private View mMovingView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRelLay = (RelativeLayout) findViewById(R.id.relativeLayout); for (int i = 0; i < mRelLay.getChildCount(); i++) mRelLay.getChildAt(i).setOnTouchListener(this); } @Override public boolean onTouch(View view, MotionEvent motionEvent) { RelativeLayout.LayoutParams mLayoutParams; switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: mMovingView = view; mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams(); mInitialX = motionEvent.getRawX(); mInitialY = motionEvent.getRawY(); mInitialLeft = mLayoutParams.leftMargin; mInitialTop = mLayoutParams.topMargin; break; case MotionEvent.ACTION_MOVE: if (mMovingView != null) { mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams(); mLayoutParams.leftMargin = (int) (mInitialLeft + motionEvent.getRawX() - mInitialX); mLayoutParams.topMargin = (int) (mInitialTop + motionEvent.getRawY() - mInitialY); mMovingView.setLayoutParams(mLayoutParams); } break; case MotionEvent.ACTION_UP: mMovingView = null; break; } return true; } } 

Hay un problema con el código que se da que será fácil de arreglar. El OnDragListener() debe establecer para la vista de destino (o cualquier destino posible). Así que OnLongClickListener() y OnTouchListener() se establecen en la vista de origen, imageView entonces debería haber imageView2 para OnDragListener() . Esa es una explicación larga, pero debe ser una solución fácil.

Vea drag-drop para un buen ejemplo.

El resto de la solución es mucho más involucrado si se hace correctamente (sin embargo, hay un trabajo alrededor).

Al iniciar una arrastrar, básicamente tiene que copiar la imagen en el portapapeles, y luego pegarlo en la vista de la gota. Esto requiere crear un ContentProvider luego usar ContentResolver ( link ).

Documentación del Portapapeles: ClipData

Tengo planes futuros para hacer esto para una aplicación, pero eso no va a suceder en el futuro, así que, por desgracia, no podré proporcionar ningún código.

Sin embargo, hay una solución que es mucho menos involucrado.

Establezca etiqueta (s) en cualquier imagen que potencialmente se moverá.

 imageView.setTag("ImageTag1"); 

En onLongClick() , defina item y dragData como se hace en la pregunta.

A continuación, en OnDragListener() , lea la etiqueta, determine qué imagen se está eliminando y, a continuación, establezca esa imagen en la vista. Algo como esto:

 case DragEvent.ACTION_DROP: ClipData.Item item = event.getClipData().getItemAt(0); CharSequence dragData = item.getText(); if(dragData.equals("ImageTag1")) { // this gets jpg image from "drawable" folder, // set ImageView appropriately for your usage ((ImageView)v).setImageResource(R.drawable.image1); } else if(dragData.equals("ImageTag2")) { ((ImageView)v).setImageResource(R.drawable.image2); } break; 

También es necesario hacer algo similar en el caso "ACTION_DRAG_EXITED". Si la imagen se deja caer en un área no válida, esto vuelve a colocar la imagen en la vista original.

Así es como lo hago en mi aplicación:

Para la "vista" que desea arrastrar, defina esto en el onTouchListener:

  public final class ChoiceTouchListener implements OnTouchListener { Context context; //int index; public static float offsetX = 0,offsetY = 0; DragShadowBuilder shadowBuilder; public ChoiceTouchListener(Context context) { super(); this.context = context; //this.index = index; } public boolean onTouch(View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { //view.setTag("option"+index); ClipData data = ClipData.newPlainText("tag", view.getTag().toString()); shadowBuilder = new View.DragShadowBuilder(view); //start dragging the item touched view.startDrag(data, shadowBuilder, view, 0); offsetX = view.getLeft();//(int)view.getX();//(int)motionEvent.getX(); offsetY = view.getTop();//(int)view.getY();//motionEvent.getY(); view.setVisibility(View.INVISIBLE); Log.v("here","it is ::" + (int)motionEvent.getX() + " , "+(int)motionEvent.getY()); return false; } return true; } } 

Y aquí está un RelativeLayout que tiene el destino "view" establecido en el medio y escucha los eventos de arrastrar y soltar:

  public class DragLayout extends RelativeLayout { boolean DEBUG = true; AnimationDrawable blenderAnim; Handler handlerAnim2; Context context; private int dimensionInPixel = 200; int screenWidth,screenHeight; public DragLayout(Context context) { super(context); this.context = context; //not to include in main program getDimensionsofScreen(); setLayout(); setViews(); } private void setLayout() { // set according to parent layout (not according to current layout) RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); rLp.topMargin = 2 * (screenHeight / 25); // calculating 1/10 of 4/5 // screen this.setLayoutParams(rLp); } void setViews() { ImageView img2 = new ImageView(context); int dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics()); RelativeLayout.LayoutParams rLp = new RelativeLayout.LayoutParams( (screenWidth / 5), (screenHeight / 5)); rLp.topMargin = (screenHeight / 10); rLp.leftMargin = (4*screenWidth / 10); rLp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); img2.setLayoutParams(rLp); img2.getLayoutParams().height = dimensionInDp; img2.getLayoutParams().width = dimensionInDp; img2.setImageDrawable(getResources().getDrawable(R.drawable.blender_anim)); img2.setOnDragListener(new ChoiceDragListener(context)); this.addView(img2); blenderAnim = (AnimationDrawable)img2.getDrawable(); blenderAnim.setOneShot(true); blenderAnim.stop(); } public ArrayList<Integer> getDimensionsofScreen() { //metrics that holds the value of height and width DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();; ArrayList<Integer> vals = new ArrayList<Integer>(); vals.add(displayMetrics.widthPixels); vals.add(displayMetrics.heightPixels); screenHeight = displayMetrics.heightPixels; screenWidth = displayMetrics.widthPixels; return vals; } @SuppressLint("NewApi") @Override public boolean onDragEvent(DragEvent event) { int mCurX = (int) event.getX(); int mCurY = (int) event.getY(); if(event.getAction() == DragEvent.ACTION_DRAG_STARTED || event.getAction() == DragEvent.ACTION_DRAG_ENTERED) { if (blenderAnim.isRunning()) { blenderAnim.stop(); } else { blenderAnim.run(); handlerAnim2 = new Handler(); handlerAnim2.postDelayed( new Runnable(){ @Override public void run() { blenderAnim.stop(); }}, getAnimationDuration(blenderAnim)); } } if(event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_EXITED) { if (blenderAnim.isRunning()) { blenderAnim.stop(); } else { blenderAnim.run(); handlerAnim2 = new Handler(); handlerAnim2.postDelayed( new Runnable(){ @Override public void run() { blenderAnim.stop(); }}, getAnimationDuration(blenderAnim)); } Log.v("here", "it is :: " + mCurX + ", " + mCurY); View view1 = (View) event.getLocalState(); view1.setVisibility(View.VISIBLE); ObjectAnimator animationx = ObjectAnimator.ofFloat(view1,"translationX", mCurX - ChoiceTouchListener.offsetX-(screenWidth / 10),0.0f); ObjectAnimator animationy = ObjectAnimator.ofFloat(view1, "translationY", mCurY - ChoiceTouchListener.offsetY - (screenHeight / 10), 0.0f); AnimatorSet animSet = new AnimatorSet(); animSet.setDuration(500); animSet.playTogether(animationx,animationy); animSet.start(); } if(event.getAction() == DragEvent.ACTION_DROP || event.getAction() == DragEvent.ACTION_DRAG_ENDED){ if(blenderAnim.isRunning()){ blenderAnim.stop(); } } return true; } private int getAnimationDuration(AnimationDrawable src){ int dur = 0; for(int i=0; i<src.getNumberOfFrames(); i++){ dur += src.getDuration(i); } return dur; } } 

Éste es el oyente de arrastre para ImageView en DragLayout:

  public class ChoiceDragListener implements View.OnDragListener { boolean DEBUG = true; Context context; public String TAG = "Drag Layout:"; public ChoiceDragListener(Context context){ this.context = context; } @Override public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: if(DEBUG) Log.v("here","drag started"); break; case DragEvent.ACTION_DRAG_ENTERED: break; case DragEvent.ACTION_DRAG_LOCATION: int mCurX = (int) event.getX(); int mCurY = (int) event.getY(); if(DEBUG) Log.v("Cur(X, Y) : " ,"here ::" + mCurX + ", " + mCurY ); break; case DragEvent.ACTION_DRAG_EXITED: if(DEBUG) Log.v("here","drag exits"); break; case DragEvent.ACTION_DROP: //handle the dragged view being dropped over a drop view View view = (View) event.getLocalState(); ClipData cd = event.getClipData(); ClipData.Item item = cd.getItemAt(0); String resp = item.coerceToText(context).toString(); //view dragged item is being dropped on ImageView dropTarget = (ImageView) v; //view being dragged and dropped final ImageView dropped = (ImageView) view; dropped.setEnabled(false); //if an item has already been dropped here, there will be a tag final Object tag = dropTarget.getTag(); LayoutInflater li = LayoutInflater.from(context); View promptsView = li.inflate(R.layout.ns_scoop_dialog, null); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( context); // set prompts.xml to alertdialog builder alertDialogBuilder.setView(promptsView); final EditText userInput = (EditText) promptsView .findViewById(R.id.edit1); // set dialog message alertDialogBuilder .setIcon(R.mipmap.ic_launcher) .setTitle(dropped.getTag().toString()) .setCancelable(false) .setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog,int id) { // get user input and set it to result // edit text String inAmt = userInput.getText().toString(); CreateSmoothie.nsList.add(inAmt + " Green Scoops " + dropped.getTag().toString()); Log.d(TAG, inAmt + " Green Scoops " + dropped.getTag().toString() + " added to list"); dialog.dismiss(); //dropped.setEnabled(true); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); int existingID = dropped.getId(); //set the original view visible again ((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE); dropped.setEnabled(true); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); //Button nButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE); //nButton.setBackgroundColor(Color.GREEN); //Button pButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); //pButton.setBackgroundColor(Color.GREEN); if(tag!=null) { //the tag is the view id already dropped here int existingID = (Integer)tag; //set the original view visible again ((Activity) context).findViewById(existingID).setVisibility(View.VISIBLE); } break; case DragEvent.ACTION_DRAG_ENDED: if(DEBUG) Log.i("drag event", "ended::" + ChoiceTouchListener.offsetX + "," + ChoiceTouchListener.offsetY); /** * returning false so that goes to parentView onDrag function */ return false; //break; default: break; } return true; } } 

Espero que ayude.

  • ¿Cómo puedo actualizar la imagen de fresco SimpleDraweeView, si se estableció una vez por setImageURI
  • Cómo obtener una imagen recortada de ImageView
  • Cómo agregar un Marcador / Pin en un Android de ImageView?
  • Establezca la altura de imageview como matchparent programmatically
  • Cargar imagen en ImageView de la URL almacenada en JSONString en Android
  • ViewPager onClickListener hace referencia a la vista errónea en android
  • Inserción de una vista de texto en medio de una vista de imagen de Android
  • Hacer diferencias entre setOnClickListener y setOnTouchListener
  • Cuadrícula de imágenes dentro de ScrollView
  • Hacer una imagen circular con borde circular blanco
  • Cómo obtener el color de fondo de un ImageView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.