akon01
akon01

Reputation: 33

custom drag and drop

i am a begginer android develpoer and i am tring to build a small soiltare game. for dragging the cards i implemented a custom viewgroup which is a "DragContainer" from one of the questions here. my problem is that when i drag a linear layout. my linear layout holds the cards with a - margin (to overlap the cards) but when i start the drag the dragged "shadow" is my layout without the margin. here is an example

this is the start of the activity, the left is a linear layout with two children and also the right

when i start the drag this is what i see

as you can see the dragged "shadow" is bigger(without the - margin)

this is the code for the custom drag container(only the stuff that matters):

    public boolean startDragChild(View child, ClipData data,
        Object myLocalState, int flags) {
    setDragTarget(child);
    return child.startDrag(data, new EmptyDragShadowBuilder(child),
            myLocalState, flags);
}

private void setDragTarget(View v) {
    target = v;
    onSetDragTarget(v);
}

/**
 * this is similar to the constructor of DragShadowBuilder
 * 
 * @param v
 */
protected void onSetDragTarget(View v) {

}
    @Override
protected void dispatchDraw(Canvas canvas) {

    super.dispatchDraw(canvas);
    if (mOnDrag && target != null) {
        canvas.save();
        drawDragShadow(canvas);
        canvas.restore();
    }
}

protected void drawDragShadow(Canvas canvas) {
    int h = target.getHeight();
    int w = target.getWidth();
    canvas.translate(mDragX - w / 2, mDragY - h / 2);
    target.draw(canvas);
}

Upvotes: 2

Views: 1499

Answers (2)

Pankaj Nimgade
Pankaj Nimgade

Reputation: 4549

I guess akon does not require the explanation but I would like to tell to the audience of the question. The margins inside the LinearLayout should be intact as you would be moving ViewGroup itself, so it's children won't have any issue with it's design, Code is also available on the Github

public class DragTestTwoActivity extends AppCompatActivity {

    private LinearLayout source_linearLayout;
    private LinearLayout destination_linearLayout;
    private static final String TAG = "DragTestTwoActivity";


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

        initializeUI();
    }

    private void initializeUI() {

        source_linearLayout = (LinearLayout) findViewById(R.id.DragTestTwoActivity_Source_LinearLayout);
        destination_linearLayout = (LinearLayout) findViewById(R.id.DragTestActivityActivity_Destination_LinearLayout);

//        source_linearLayout.setOnDragListener(new MyDragListener());
        destination_linearLayout.setOnDragListener(new MyDragListener());

        source_linearLayout.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(source_linearLayout);
                source_linearLayout.startDrag(data, shadowBuilder, source_linearLayout, 0);
                return true;
            }
        });
    }

    private class MyDragListener implements View.OnDragListener {


        @Override
        public boolean onDrag(View v, DragEvent event) {

            switch (event.getAction()) {

                case DragEvent.ACTION_DRAG_STARTED:
                    Log.d(TAG, "Drag has started");
                    break;
                case DragEvent.ACTION_DRAG_ENDED:
                    Log.d(TAG, "Drag has ended");
                    v.setVisibility(View.VISIBLE);
                    break;
                case DragEvent.ACTION_DRAG_ENTERED:
                    Log.d(TAG, "Drag has entered");
                    break;
                case DragEvent.ACTION_DRAG_LOCATION:
                    Log.d(TAG, "Drag location");
                    break;
                case DragEvent.ACTION_DROP:
                    Log.d(TAG, "Drag has dropped");
                    View source_linear_Layout = (LinearLayout) event.getLocalState();
                    LinearLayout view = (LinearLayout) source_linear_Layout.getParent();
                    view.removeView(source_linear_Layout); // This will remove the imageView where it was

                    LinearLayout linearLayout = (LinearLayout) v;
                    if (v.getId() == R.id.DragTestActivityActivity_Source_LinearLayout) {
                        Log.d(TAG, "This is a source location");

                    } else if (v.getId() == R.id.DragTestActivityActivity_Destination_LinearLayout) {
                        Log.d(TAG, "This is a destination");

                    }
                    linearLayout.addView(source_linear_Layout); // this will add the ImageView to the new location where it was dropped.
                    source_linear_Layout.setVisibility(View.VISIBLE);


                    break;
                case DragEvent.ACTION_DRAG_EXITED:
                    Log.d(TAG, "Drag has exited");
                    break;
            }

            return true;
        }


    }
}

activity_drag_test_two.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="activities.list.first.DragTestTwoActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:padding="4sp">


        <LinearLayout

            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="4dp"
            android:layout_weight="0.5"
            android:background="#ABABAB"
            android:orientation="vertical"
            android:padding="4dp">

            <LinearLayout
                android:id="@+id/DragTestTwoActivity_Source_LinearLayout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/DragTestTwoActivity_imageView"
                    android:layout_width="wrap_content"
                    android:layout_height="100dp"
                    android:layout_margin="4dp"
                    android:scaleType="centerInside"
                    android:src="@drawable/gohan" />

                <ImageView
                    android:id="@+id/DragTestTwoActivity_imageView2"
                    android:layout_width="wrap_content"
                    android:layout_height="100dp"
                    android:layout_margin="4dp"
                    android:scaleType="centerInside"
                    android:src="@drawable/goku" />
            </LinearLayout>


        </LinearLayout>

        <LinearLayout
            android:id="@+id/DragTestActivityActivity_Destination_LinearLayout"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_margin="4dp"
            android:layout_weight="0.5"
            android:background="#CACACB"
            android:orientation="vertical"
            android:padding="4dp">

        </LinearLayout>


    </LinearLayout>

</LinearLayout>

Output this is how it would look like...

enter image description here

Upvotes: 1

Denis Steinman
Denis Steinman

Reputation: 7799

Of course, you can use standart views for this purpose but it is irrational. It will better to use SurfaceView (or if you know OpenGL GLSurfaceView).

Upvotes: 0

Related Questions