Today we are going to make a post on request, that how to drag and drop an image outside of RecyclerView. First, you need to know about RecyclerView.

Drag and Drop image outside
Drag and Drop image outside

Step-1
Create a new project.

Step-2
Now we will make a model for RecyclerView. In this model, I will use the properties title and image. You can make it according to your requirements.

package com.becody.carddragingexample;

import android.graphics.drawable.Drawable;

/**
 * Created by becody.com on 09,10,2019
 */
public class ListModal {
    private String title;
    private int drawable;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getDrawable() {
        return drawable;
    }

    public void setDrawable(int drawable) {
        this.drawable = drawable;
    }
}

Step-3
Now we will design the adapter layout according to requirement. I will display an image along with the title.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="200dp"
    android:layout_height="150dp"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="0dp"
                android:layout_height="130dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/image_1" />

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textSize="20sp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.5"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/imageView2" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

Step-4
Now we will create a RecyclerView Adapter Java class called AdapterListing.java.

package com.becody.carddragingexample;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

/**
 * Created by becody.com on 09,10,2019
 */
public class AdapterListing extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    List<ListModal> listModals;

    AdapterListing(List<ListModal> imagesList) {
        this.listModals = imagesList;
    }

    private class ImageViewHolder extends RecyclerView.ViewHolder {
        private ImageView imageView;
        private TextView textView;

        private ImageViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView2);
            textView = itemView.findViewById(R.id.textView);
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_test_layout, parent, false);
        final ImageViewHolder holder = new ImageViewHolder(view);
        final View shape = holder.imageView;
        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                final ListModal item = listModals.get(holder.getAdapterPosition());
                final DragData state = new DragData(item, shape.getWidth(), shape.getHeight());
                final View.DragShadowBuilder shadow = new View.DragShadowBuilder(shape);
                ViewCompat.startDragAndDrop(shape, null, shadow, state, 0);
                return true;
            }
        });

        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        ImageViewHolder imageViewHolder = (ImageViewHolder) holder;
        ListModal list = listModals.get(position);
        imageViewHolder.imageView.setImageResource(list.getDrawable());
        imageViewHolder.textView.setText(list.getTitle());

    }

    @Override
    public int getItemCount() {
        return listModals.size();
    }
}

Now you can see in onCreateViewHolder method. I am applying onLongClick listener on row item. When onLongClick listener will class then I will set an object of DragState. I will use the built-in method startDragAndDrop. You can customize the DragState object according to your requirements.

package com.becody.carddragingexample;

/**
 * Created by becody.com on 09,10,2019
 */
public class DragData {
    public final ListModal item;
    public final int width;
    public final int height;

    public DragData(ListModal item, int width, int height) {
        this.item= item;
        this.width = width;
        this.height = height;
    }
}

Step-5
In our MainActivity.java class, first, we will design a layout for this class. In this layout, we will have a container with ImageView. We will add RecyclerView. Here is a full code of activity_main.xml file

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">


    <View
        android:id="@+id/view"
        android:layout_width="0dp"
        android:layout_height="303dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:background="@drawable/container_border"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/listing"
        android:layout_width="0dp"
        android:layout_height="160dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/view"
        app:layout_constraintEnd_toEndOf="@+id/view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/view"
        app:srcCompat="@drawable/image_1" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step-6
In MainActivity.java class, we will set onDragListener on the container. With the different states of DragListener, we will set the color of container.

  private void initContainer() {
        dragView.setOnDragListener(new View.OnDragListener() {
            @Override
            public boolean onDrag(View view, DragEvent dragEvent) {

                switch (dragEvent.getAction()) {
                    case DragEvent.ACTION_DRAG_ENTERED:
                        dragView.setBackgroundColor(Color.GREEN);
                        break;
                    case DragEvent.ACTION_DRAG_EXITED:
                        dragView.setBackgroundColor(Color.RED);
                        break;
                    case DragEvent.ACTION_DRAG_ENDED:
                        dragView.setBackgroundColor(Color.WHITE);
                        break;
                    case DragEvent.ACTION_DROP:
                        //  final float dropX = dragEvent.getX();
                        //  final float dropY = dragEvent.getY();
                        final DragData state = (DragData) dragEvent.getLocalState();
                        setImgIntoContainer(state.item);

                    default:
                        break;
                }
                return true;
            }
        });
    }

When drag action will end then we will get the DragData Object. From the DragData object, we will get the object of the list model. After that, we will get the image from the list model and will set it into the container image. Here is the full code of ActivityMain.java file

package com.becody.carddragingexample;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    String[] titles = {"Men", "Women", "Kid", "Baby"};
    int[] drawables = {R.drawable.image_1, R.drawable.image_2, R.drawable.image_3, R.drawable.image_4};
    private View dragView;
    private RecyclerView recyclerView;
    private List<ListModal> listModalList;
    private AdapterListing adapterListing;
    private ImageView imageView;

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

    private void initComponents() {
        dragView = findViewById(R.id.view);
        recyclerView = findViewById(R.id.listing);
        imageView = findViewById(R.id.imageView);
        listModalList = new ArrayList<>();

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        DividerItemDecoration mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
                linearLayoutManager.getOrientation());
        recyclerView.addItemDecoration(mDividerItemDecoration);
        setDataToAdapter();
        initContainer();
    }

    private void setDataToAdapter() {
        for (int j = 0; j < titles.length; j++) {
            ListModal listModal = new ListModal();
            listModal.setTitle(titles[j]);
            listModal.setDrawable(drawables[j]);
            listModalList.add(listModal);
        }
        adapterListing = new AdapterListing(listModalList);
        recyclerView.setAdapter(adapterListing);
    }

    private void initContainer() {
        dragView.setOnDragListener(new View.OnDragListener() {
            @Override
            public boolean onDrag(View view, DragEvent dragEvent) {

                switch (dragEvent.getAction()) {
                    case DragEvent.ACTION_DRAG_ENTERED:
                        dragView.setBackgroundColor(Color.GREEN);
                        break;
                    case DragEvent.ACTION_DRAG_EXITED:
                        dragView.setBackgroundColor(Color.RED);
                        break;
                    case DragEvent.ACTION_DRAG_ENDED:
                        dragView.setBackgroundColor(Color.WHITE);
                        break;
                    case DragEvent.ACTION_DROP:
                        //  final float dropX = dragEvent.getX();
                        //  final float dropY = dragEvent.getY();
                        final DragData state = (DragData) dragEvent.getLocalState();
                        setImgIntoContainer(state.item);

                    default:
                        break;
                }
                return true;
            }
        });
    }

    private void setImgIntoContainer(ListModal listModal) {
        imageView.setImageResource(listModal.getDrawable());
    }
}

Thanks for reading the tutorial. Please like our Facebook page for a new and latest tutorial. Join our WhatsApp group for asking any questions about this tutorial. Please subscribe to our Youtube channel for the latest updates and tutorials.

7 Comments

  1. Excellent tutorial, elegant.
    Only one problem – you should write the names of the xml files, because it is little confusing.

    • hamza Reply

      Sure, next time, I will consider this thing in my next tutorial, keep reading and share it with your friends.

Write A Comment