如何在Android中使用拖放交换两个图像视图?

hen*_*ign 6 android swap drag-and-drop

我一直在尝试在Android中实现一个非常简单的拖放操作,其中拖动的项目与放置它的项目交换位置.

我已经成功实现了onLongClick和onDrag监听器.当我拖放一个项目时,它会替换掉它所放置的项目,但我无法弄清楚如何使被替换的项目取代被拖动的项目.

我花了一些时间寻找答案,但大多数答案只是链接复杂的拖放操作,涉及许多带有大量代码的文件,而我无法理解它们将它们应用到我的代码中.

我最初假设我没有得到ImageView的真实副本

ImageView temp = (ImageView) event.getLocalState();
Run Code Online (Sandbox Code Playgroud)

所以我试过了

ImageView dragged = (ImageView) findViewById(temp.getId());  
Run Code Online (Sandbox Code Playgroud)

但这并没有什么不同.

我几乎可以肯定问题出现在'OnDragListener'中,在'case DragEvent.ACTION_DROP:'中.这是我的代码(来自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;
        }
    };
Run Code Online (Sandbox Code Playgroud)

如果有人能告诉我为什么setImageDrawable在目标上工作,而不是在拖动,我会非常感激.

hen*_*ign 5

学习计算机科学的一大乐趣就是学习谦虚.至少有90%的时间,这个任务的答案是:"为什么这不起作用?" 是你告诉电脑做错事.

在"case DragEvent.ACTION_DROP:"中,我获得了对两个视图的引用.我出于某种原因没有意识到的是,当我这样做时

target.setImageDrawable(dragged.getDrawable());
Run Code Online (Sandbox Code Playgroud)

我也在改变temp的drawable,因为temp指的是实际的视图.因为那时我做了

dragged.setImageDrawable(temp.getDrawable());
Run Code Online (Sandbox Code Playgroud)

我实际上只是将拖动的drawable设置为它原来的样子.这是更正后的代码.

            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;
Run Code Online (Sandbox Code Playgroud)