【问题标题】:How to swap two image views using drag and drop in Android?如何在 Android 中使用拖放交换两个图像视图?
【发布时间】:2015-08-05 04:18:18
【问题描述】:

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

我已经成功实现了 onLongClick 和 onDrag 监听器。当我拖放一个项目时,它会替换它被拖放的项目,但我不知道如何使替换的项目取代拖动的项目。

我花了一段时间寻找答案,但大多数答案只是将复杂的拖放实现联系起来,涉及许多文件和大量代码,我无法充分理解它们以将它们应用到我的代码中。

我最初认为我没有得到 ImageView 的真实副本

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

所以我尝试了

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

但这并没有什么不同。

我几乎可以肯定问题出在“OnDragListener”中,在“案例 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;
        }
    };

如果有人能告诉我为什么 setImageDrawable 在目标上有效,但在拖动时无效,我将不胜感激。

【问题讨论】:

    标签: android drag-and-drop swap


    【解决方案1】:

    学习计算机科学的一大乐趣就是学会谦逊。至少 90% 的时间,这个问题的答案是:“为什么这不起作用?”是你告诉计算机做错事。

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

    target.setImageDrawable(dragged.getDrawable());
    

    我还更改了 temp 的可绘制对象,因为 temp 指的是实际视图。因为我这样做的时候

    dragged.setImageDrawable(temp.getDrawable());
    

    我实际上只是将拖动的可绘制对象设置为原来的样子。 这是更正后的代码。

                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;
    

    【讨论】:

      【解决方案2】:

      我更新了实际交换视图而不是交换图像的答案;

      @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
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多