How to swap two images using drag and drop on Android?

I am trying to implement a very simple drag and drop in Android, where the dragged item changes positions with the item it was dropped to.

I have successfully implemented the onLongClick and onDrag listeners. When I drag an item, it replaces the item it was deleted from, but I can't figure out how to replace the replaced item with the dragged item.

I spent some time looking for answers, but most of the answers just linked complex drag and drop implementations involving many files with a lot of code, and I couldn't figure them out enough to apply them to my code.

It was originally assumed that I did not get a genuine copy of the ImageView with

ImageView temp = (ImageView) event.getLocalState();

      

so i tried

ImageView dragged = (ImageView) findViewById(temp.getId());  

      

but that didn't make any difference.

I'm pretty sure the problem is with the "OnDragListener", in the "DragEvent.ACTION_DROP:" case. Here is my code (from Main.java):

public class Main extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.ball1).setOnLongClickListener(listenClick);
        findViewById(R.id.ball1).setOnDragListener(listenDrag);
        findViewById(R.id.target1).setOnLongClickListener(listenClick);
        findViewById(R.id.target1).setOnDragListener(listenDrag);
        findViewById(R.id.target2).setOnDragListener(listenDrag);
        findViewById(R.id.target2).setOnLongClickListener(listenClick);
        findViewById(R.id.target3).setOnDragListener(listenDrag);
        findViewById(R.id.target3).setOnLongClickListener(listenClick);



View.OnLongClickListener listenClick = new View.OnLongClickListener()
    {
        @Override
        public boolean onLongClick(View v)
        {

            ClipData data = ClipData.newPlainText("","");
            DragShadow dragShadow = new DragShadow(v);

            v.startDrag(data, dragShadow, v, 0);

            return false;
        }
    };

    private class DragShadow extends View.DragShadowBuilder
    {
        ColorDrawable greyBox;

        public DragShadow(View view)
        {
            super(view);
            greyBox = new ColorDrawable(Color.LTGRAY);
        }

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

        @Override
        public void onProvideShadowMetrics(Point shadowSize,
                                           Point shadowTouchPoint)
        {
            View v = getView();

            int height = (int) v.getHeight();
            int width = (int) v.getWidth();

            greyBox.setBounds(0, 0, width, height);

            shadowSize.set(width, height);

            shadowTouchPoint.set((int)width/2, (int)height/2);
        }
    }



View.OnDragListener listenDrag = new View.OnDragListener() {

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

            switch (dragEvent)
            {
                case DragEvent.ACTION_DRAG_ENTERED:
                    Log.i("Drag Event", "Entered");
                    break;

                case DragEvent.ACTION_DRAG_EXITED:
                    Log.i("Drag Event", "Exited");
                    break;

                case DragEvent.ACTION_DROP:
                    ImageView target = (ImageView) v;

                    ImageView temp = (ImageView) event.getLocalState();
                    ImageView dragged = (ImageView) findViewById(temp.getId());


                    target.setId(dragged.getId());
                    target.setImageDrawable(dragged.getDrawable());

                    dragged.setId(temp.getId());
                    dragged.setImageDrawable(temp.getDrawable());

                    break;

            }

            return true;
        }
    };

      

If anyone can tell me why setImageDrawable works on target but not on tasks, I would be very grateful.

+6


source to share


2 answers


One of the greatest joys in computer science is the study of humility. At least 90% of the time, the answer to the quest is: "Why doesn't it work?" is that you told the computer to do the wrong thing.

In the "case of DragEvent.ACTION_DROP:" I was getting links to both views. For some reason I didn't understand that when I was doing

target.setImageDrawable(dragged.getDrawable());

      

I also changed the returned temp as temp was referencing the actual view. Because of this, when I did



dragged.setImageDrawable(temp.getDrawable());

      

I was actually just setting up the drag and drop to what it originally was. Here is the corrected code.

            case DragEvent.ACTION_DROP:
                ImageView target = (ImageView) v;

                ImageView dragged = (ImageView) event.getLocalState();

                Drawable target_draw = target.getDrawable();
                Drawable dragged_draw = dragged.getDrawable();

                dragged.setImageDrawable(target_draw);
                target.setImageDrawable(dragged_draw);

                break;

      

+5


source


I updated the answer to actually swap views instead of swapping images;



@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
private fun initView(view: View) {
    view.setOnDragListener(View.OnDragListener { target, event ->
        when (event.action) {
            DragEvent.ACTION_DRAG_STARTED -> return@OnDragListener true

            DragEvent.ACTION_DRAG_ENTERED -> {
                target.setBackgroundColor(ContextCompat.getColor(this, R.color.colorAccent))
                return@OnDragListener true
            }

            DragEvent.ACTION_DRAG_LOCATION -> return@OnDragListener true

            DragEvent.ACTION_DRAG_EXITED -> {
                target.setBackgroundColor(ContextCompat.getColor(this, R.color.colorPrimary))
                return@OnDragListener true
            }

            DragEvent.ACTION_DROP -> {
                target.setBackgroundColor(ContextCompat.getColor(this, R.color.colorPrimary))

                val dragged = event.localState as ImageView
                val targetView = target as ImageView

                //Swap Image
               // val target_draw = targetView!!.drawable
               // val dragged_draw = dragged!!.drawable

               // dragged.setImageDrawable(target_draw)
               // targetView.setImageDrawable(dragged_draw)

                val oldOwner  = dragged.parent as ViewGroup
                val newOwner  = target.parent as ViewGroup

                val draggedPosition = oldOwner.indexOfChild(dragged)
                val targetPosition = oldOwner.indexOfChild(dragged)


                oldOwner.removeView(dragged)
                newOwner.addView(dragged,targetPosition)

                newOwner.removeView(target)
                oldOwner.addView(target,draggedPosition)

                return@OnDragListener true
            }

            DragEvent.ACTION_DRAG_ENDED -> return@OnDragListener true

            else -> {
            }
        }
        false
    })


    view.setOnLongClickListener { v ->

        val dummyData = ClipData.newPlainText("dummyData", "") // don't forget to pass empty String
        val shadowBuilder = View.DragShadowBuilder(v)
        v.startDrag(dummyData, shadowBuilder, v, 0)

        //val data = ClipData.newPlainText("value", "1")
        // view.startDrag(data, View.DragShadowBuilder(v), null, 0)
        true
    }
}

      

0


source







All Articles