是否有可能拖延和将一个ImageView放到另一个上以创建一个新的?

时间:2017-11-28 21:08:21

标签: android drag-and-drop imageview

我知道这个问题看起来有点模糊,但我正在制作一个“炼金术”游戏,用户将不同的地球元素拖到另一个上,看看这个组合产生了什么。

目前,我可以在屏幕上拖动视图,但我希望它们能够互相交互。例如,当用户将一个ImageView拖到另一个上时,它将以编程方式或以一些时髦的方式生成一个新的... ...

我只是想知道最好的方法是什么?

到目前为止,这是我的代码,我删除了所有必须显示准系统的废话:

public class MainActivity extends AppCompatActivity {

private ImageView earthImg;
private ImageView waterImg;
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;


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

    rootLayout = findViewById(R.id.root_view);
    earthImg = rootLayout.findViewById(R.id.earthView);
    waterImg = rootLayout.findViewById(R.id.waterView);
    earthImg.setOnTouchListener(new UserTouchListener());
    waterImg.setOnTouchListener(new UserTouchListener());
}

private final class UserTouchListener implements View.OnTouchListener {
    float dX, dY;

    public boolean onTouch(View view, MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {


            case MotionEvent.ACTION_DOWN:

                dX = view.getX() - event.getRawX();
                dY = view.getY() - event.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:

                view.animate()
                        .x(event.getRawX() + dX)
                        .y(event.getRawY() + dY)
                        .setDuration(0)
                        .start();
                break;
            default:
                return false;
        }
        rootLayout.invalidate();
        return true;

    }
}

    <?xml version="1.0" encoding="utf-8"?>
<android.widget.RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.android.alchgame.MainActivity">

    <ImageView
        android:id="@+id/earthView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="59dp"
        android:layout_marginStart="59dp"
        android:layout_marginTop="70dp"
        app:srcCompat="@drawable/earth_element"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <ImageView
        android:id="@+id/waterView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/earthView"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="150dp"
        android:layout_toEndOf="@+id/earthView"
        android:layout_toRightOf="@+id/earthView"
        app:srcCompat="@drawable/water_element" />
</android.widget.RelativeLayout>

我添加了上面的视图以供参考

2 个答案:

答案 0 :(得分:0)

您可以将MotionEvent.ACTION_UP添加到switch语句中,然后根据x和y坐标计算拖动视图的边界(根据拖动代码可以得到)和大小视图。检查这些数字是否与另一个视图的数字相匹配。如果他们这样做,你可以做任何你需要的事情,比如制作一个新的图像,删除旧的图像,将拖动的图像设置回原来的位置等等。

此外,视图还有getTop()getLeft() ...等方法,这些方法将根据父级返回该边缘。

所以你可以这样做:

case MotionEvent.ACTION_UP:
    //view = view being dragged
    String dTag = view.getTag();
    for (View mView: myImageViews){
        if (!mView.getTag().equals(dTag){                
               if (view.getTop() <= mView.getBottom() && view.getBottom() >= mView.getBottom()){
               if (view.getLeft() <= mView.getRight() && view.getRight() >= mView.getRight()){
                    //match
                }
                else if (view.getRight() >= mView.getLeft() && view.getLeft() <= mView.getLeft()){
                    //match
                }
                //No match
            }
            else if (view.getBottom() >= mView.getTop() && view.getTop() <= mView.getTop()){
                if (view.getLeft() <= mView.getRight()  && view.getRight() >= mView.getRight()){
                    //match
                }
                else if (view.getRight() >= mView.getLeft() && view.getLeft() <= mView.getLeft()){
                    //match
                }
                //No match
            }
        }
    }
    break;

我不确定是否有一些时髦的&#39;在vanilla Android中执行此操作的方法,但我确定可能存在某种类型的库,或者您可以如上所述手动执行此操作。

希望这有所帮助。

编辑: 我在这里假设您将制作图像视图或类似视图的arraylist。我还想指出,你需要检查循环中的当前视图是否是你要拖动的视图,如果是,你应该继续下一个。您可以通过向每个视图添加标记然后检查标记是否与拖动视图的标记匹配来实现此目的。我将更新上面的代码。

答案 1 :(得分:0)

扩展View.OnDragListener并将其设置为每个“元素”的容器

class MyDragListener implements View.OnDragListener {
    Drawable enterShape = getResources().getDrawable(...);
    Drawable normalShape = getResources().getDrawable(...);

    @Override
    public boolean onDrag(View v, DragEvent event) {
        View element = (View) event.getLocalState();
        View elementContainer = (View) element.getParent();
        switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED:
                element.setVisibility(View.INVISIBLE);
                break;
            case DragEvent.ACTION_DRAG_ENTERED:
                v.setBackground(enterShape);
                break;
            case DragEvent.ACTION_DRAG_EXITED:
                v.setBackground(normalShape);
                break;
            case DragEvent.ACTION_DROP:
                // Dropped, reassign Entry to Day
                View newContainer = v;
                doSnazzyStuff(element, newContainer);
                break;
            case DragEvent.ACTION_DRAG_ENDED:
                v.setBackground(normalShape);
                element.setVisibility(View.VISIBLE);
            default:
                break;
        }
        return true;
    }

    private void doSnazzyStuff(View element, View newContainer) {
        // do stuff
    }
}

并在每个“元素”上设置类似这样的内容,以影响它在拖动时的外观。

private final class ElementClickListener implements OnLongClickListener {
    @Override
    public boolean onLongClick(View view) {
        ClipData data = ClipData.newPlainText("", "");
        DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                view);
        view.startDrag(data, shadowBuilder, view, 0);
        return true;
    }
}

如果你为“元素”和容器创建/扩展自定义视图,那么你可以做一些非常强大的东西。