Skip to content
Advertisement

How I can position an Imageview On Runtime at specific coordinates during on a DragEvent?

My app has the following view:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:orientation="horizontal"
            android:layout_gravity="center">
                <Button
                    android:id="@+id/rectangle"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Rectangle" />

                <Button
                    android:id="@+id/circle"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Circle" />

                <Button
                    android:id="@+id/triangle"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Triangle" />
        </LinearLayout>
        <View android:id="@+id/dropzone"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/background_color">
        </View>
</LinearLayout>

And the Following activity:

package com.example.dragtest;

import androidx.appcompat.app.AppCompatActivity;

//import android.graphics.Canvas;
//import android.graphics.Paint;
//import android.graphics.Path;
//import android.graphics.Point;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.util.ArrayList;


public class MainActivity extends AppCompatActivity {

    private Button circle=null;
    private Button rectangle=null;
    private Button triangle=null;
    private View dropzone = null;

    private MyTouchListener touch= new MyTouchListener();
    private MyDragListener d =new MyDragListener();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rectangle=(Button)findViewById(R.id.rectangle);
        rectangle.setOnLongClickListener(touch);
//        rectangle.setOnDragListener(d);

        circle=(Button)findViewById(R.id.circle);
        circle.setOnLongClickListener(touch);
//        circle.setOnDragListener(d);

        triangle=(Button)findViewById(R.id.triangle);
        triangle.setOnLongClickListener(touch);
//        triangle.setOnDragListener(d);

        dropzone=(View)findViewById(R.id.dropzone);
        dropzone.setOnDragListener(d);
    }

    private final class MyTouchListener implements View.OnLongClickListener {
        @SuppressLint("UseCompatLoadingForDrawables")
        @Override
        public boolean onLongClick(View v) {
                final int id = v.getId();
                Drawable shadow = null;
                ClipData.Item shape = null;

                if(id == R.id.circle) {
                    shape = new ClipData.Item("circle");
                    shadow = getResources().getDrawable(R.drawable.circle,null);
                } else if( id == R.id.rectangle) {
                    shape = new ClipData.Item("rectangle");
                    shadow = getResources().getDrawable(R.drawable.rectangle, null);
                } else if( id == R.id.triangle ) {
                    shape = new ClipData.Item("circle");
                    shadow = getResources().getDrawable(R.drawable.triangle, null);
                }
                ImageView shadowImage = new ImageView(v.getContext());
                shadowImage.setImageDrawable(shadow);

                Canvas shadowCanvas = new Canvas();
                shadow.draw(shadowCanvas);

                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
                shadowBuilder.onDrawShadow(shadowCanvas);

                String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
                ClipData draggedData = new ClipData(new ClipDescription("ClipData".toString(),mimeTypes),shape);
                v.startDragAndDrop(draggedData,shadowBuilder,v,0);

                return true;
        }
    }

    private final class MyDragListener implements View.OnDragListener {
        public boolean onDrag(View v, DragEvent event) {
            final int id = v.getId();
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    // do nothing
                    Log.v("DROP","Coordinates: "+event.getX()+" , "+event.getY());
                    break;
                case DragEvent.ACTION_DRAG_ENTERED:
                    break;
                case DragEvent.ACTION_DRAG_EXITED:
                    break;
                case DragEvent.ACTION_DROP:
                    Log.v("DROP","item has been dropped");

                    ClipData.Item item = event.getClipData().getItemAt(0);
                    String shape = item.getText().toString();
                    Log.v("DROP","Coordinates: "+event.getX()+" , "+event.getY());
                    Log.v("DROP","Shape: "+shape);

                    Drawable d = null;

                    switch (shape){
                        case "cirlce":
                            d = getResources().getDrawable(R.drawable.circle,null);
                            break;
                        case "rectangle":
                            d = getResources().getDrawable(R.drawable.rectangle,null);
                            break;
                        case "triangle":
                            d = getResources().getDrawable(R.drawable.triangle,null);
                            break;
                    }

                    Context ctx = v.getContext();
                    ImageView img = new ImageView(ctx);
                    img.setImageDrawable(d);
                    img.setX(event.getX());
                    img.setY(event.getY());
                    ArrayList<View> items = new ArrayList<View>();
                    items.add(img);
                    v.addTouchables(items);

                    break;
                case DragEvent.ACTION_DRAG_ENDED:

                default:
                    break;
            }
            return true;

        }
    }
}

At the following lines:

                    Context ctx = v.getContext();
                    ImageView img = new ImageView(ctx);
                    img.setImageDrawable(d);
                    img.setX(event.getX());
                    img.setY(event.getY());
                    ArrayList<View> items = new ArrayList<View>();
                    items.add(img);
                    v.addTouchables(items);

I try to place an image into a view but I fail to do so. My aim with this activity is to draw and reposition some items on a Custom Layout? What I want is some sort of view where I can position the ImageView.

Do you know how I can do that?

Advertisement

Answer

The appropiate layout is the ConstraintLayout And the reason why is because it allows you to position an item to specific X and Y positions.

The activity view should be:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:orientation="horizontal"
            android:layout_gravity="center">
                <Button
                    android:id="@+id/rectangle"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Rectangle" />

                <Button
                    android:id="@+id/circle"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Circle" />

                <Button
                    android:id="@+id/triangle"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:text="Triangle" />
        </LinearLayout>
        <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/dropzone"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/background_color">

        </androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

So in the onDrag action to be able to do:

   public boolean onDrag(View v, DragEvent event) {
            final int id = v.getId();
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    // do nothing
                    Log.v("DROP","Coordinates: "+event.getX()+" , "+event.getY());
                    break;
                case DragEvent.ACTION_DRAG_ENTERED:
                    break;
                case DragEvent.ACTION_DRAG_EXITED:
                    break;
                case DragEvent.ACTION_DROP:
                    Log.v("DROP","item has been dropped");

                    ClipData.Item item = event.getClipData().getItemAt(0);
                    String shape = item.getText().toString();
                    Log.v("DROP","Coordinates: "+event.getX()+" , "+event.getY());
                    Log.v("DROP","Shape: "+shape);

                    Drawable d = null;

                    switch (shape){
                        case "circle":
                            d = getResources().getDrawable(R.drawable.circle,null);
                            break;
                        case "rectangle":
                            d = getResources().getDrawable(R.drawable.rectangle,null);
                            break;
                        case "triangle":
                            d = getResources().getDrawable(R.drawable.triangle,null);
                            break;
                    }

                    Context ctx = v.getContext();
                    ImageView img = new ImageView(ctx);
                    img.setImageDrawable(d);
                    img.setX(event.getX());
                    img.setY(event.getY());

                    ConstraintLayout layout = (ConstraintLayout)v;
                    layout.addView(img);

                    break;
                case DragEvent.ACTION_DRAG_ENDED:

                default:
                    break;
            }
            return true;

        }

Pay attention to the following lines:

                    Context ctx = v.getContext();
                    ImageView img = new ImageView(ctx);
                    img.setImageDrawable(d);
                    img.setX(event.getX());
                    img.setY(event.getY());

                    ConstraintLayout layout = (ConstraintLayout)v;
                    layout.addView(img);
3 People found this is helpful
Advertisement