-2

This is a application image

I have a project on android studio and I want to drag and drop images items in RecylerView to an Container on my Activity...

In my activity I have a fragment container and this displays fragments with an RecyclerView and this display animal parts in JSON connection, it's posible to make a Drag And Drop to move images to Cointainer to make a animal character and send data to my database, and how I do it???

Sky
  • 1,435
  • 1
  • 15
  • 24

1 Answers1

1

You have to implement ItemTouchHelper and this is an example about how to do it:

1- Add your recyclerview

 <android.support.v7.widget.RecyclerView
        android:id="@+id/note_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

2 - Add Model Class

public class Customer {
private Long id;
private String name;
private String emailAddress;
private int imageId;
private String imagePath;
}

3 - Add Dependencies

compile 'de.hdodenhof:circleimageview:2.0.0'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.yqritc:recyclerview-flexibledivider:1.2.6'
compile 'com.google.code.gson:gson:2.3.1'

4 - Add Internet permission

<uses-permission android:name="android.permission.INTERNET" />

5- Create a new List of Customer in your Activity and add customers into it.

6- Create a new class named CustomerListAdapter

 package com.okason.draganddrop;

import android.content.Context;
import android.graphics.Color;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.okason.draganddrop.listeners.OnCustomerListChangedListener;
import com.okason.draganddrop.listeners.OnStartDragListener;
import com.okason.draganddrop.utilities.ItemTouchHelperAdapter;
import com.okason.draganddrop.utilities.ItemTouchHelperViewHolder;
import com.squareup.picasso.Picasso;

import java.util.Collections;
import java.util.List;

/**
 * Created by Valentine on 10/18/2015.
 */
public class CustomerListAdapter extends
        RecyclerView.Adapter<CustomerListAdapter.ItemViewHolder>
        implements ItemTouchHelperAdapter {

private List<Customer> mCustomers;
private Context mContext;
private OnStartDragListener mDragStartListener;
private OnCustomerListChangedListener mListChangedListener;

public CustomerListAdapter(List<Customer> customers, Context context,
                           OnStartDragListener dragLlistener,
                           OnCustomerListChangedListener listChangedListener){
    mCustomers = customers;
    mContext = context;
    mDragStartListener = dragLlistener;
    mListChangedListener = listChangedListener;
}


@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View rowView = LayoutInflater.from
    (parent.getContext()).inflate(R.layout.row_customer_list, parent, false);
    ItemViewHolder viewHolder = new ItemViewHolder(rowView);
    return viewHolder;
}

@Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {

    final Customer selectedCustomer = mCustomers.get(position);

    holder.customerName.setText(selectedCustomer.getName());
    holder.customerEmail.setText(selectedCustomer.getEmailAddress());
    Picasso.with(mContext)
            .load(selectedCustomer.getImagePath())
            .placeholder(R.drawable.profile_icon)
            .into(holder.profileImage);



    holder.handleView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
                mDragStartListener.onStartDrag(holder);
            }
            return false;
        }
    });
}

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

@Override
public void onItemMove(int fromPosition, int toPosition) {
    Collections.swap(mCustomers, fromPosition, toPosition);
    mListChangedListener.onNoteListChanged(mCustomers);
    notifyItemMoved(fromPosition, toPosition);
}

@Override
public void onItemDismiss(int position) {

}

public static class ItemViewHolder extends RecyclerView.ViewHolder implements
        ItemTouchHelperViewHolder {
    public final TextView customerName, customerEmail;
    public final ImageView handleView, profileImage;


    public ItemViewHolder(View itemView) {
        super(itemView);
        customerName = (TextView)itemView.findViewById(R.id.text_view_customer_name);
        customerEmail = (TextView)itemView.findViewById(R.id.text_view_customer_email);
        handleView = (ImageView)itemView.findViewById(R.id.handle);
        profileImage = (ImageView)itemView.findViewById(R.id.image_view_customer_head_shot);
    }

    @Override
    public void onItemSelected() {
        itemView.setBahttp://valokafor.com/wp-admin/post.php?post=1804&action=edit#ckgroundColor(Color.LTGRAY);
    }

    @Override
    public void onItemClear() {
        itemView.setBackgroundColor(0);
    }
}
}

7- Implement ItemTouchHelper In your utilities package, add ItemTouchHelperAdapter.java and below is the content:

public interface ItemTouchHelperAdapter {
/**
 * Called when an item has been dragged far enough to trigger a move. This is called every time
 * an item is shifted, and not at the end of a "drop" event.
 *
 * @param fromPosition The start position of the moved item.
 * @param toPosition   Then end position of the moved item.

 */
void onItemMove(int fromPosition, int toPosition);


/**
 * Called when an item has been dismissed by a swipe.
 *
 * @param position The position of the item dismissed.

 */
void onItemDismiss(int position);
}

And in your utilities package, add ItemTouchHelperViewHolder.java and below is the content:

public interface ItemTouchHelperViewHolder {
    /**
      * Implementations should update the item view to indicate it's active state.
     */
    void onItemSelected();


    /**
     * state should be cleared.
     */
    void onItemClear();
}

In your utilities package, add SimpleItemTouchHelperCallback.java and here is the content:

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

private final ItemTouchHelperAdapter mAdapter;

public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
    mAdapter = adapter;
}

@Override
public boolean isLongPressDragEnabled() {
    return true;
}

@Override
public boolean isItemViewSwipeEnabled() {
    return false;
}

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
    final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
    return makeMovementFlags(dragFlags, swipeFlags);
}

@Override
public boolean onMove(RecyclerView recyclerView, 
RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
    mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
    return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
    mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}

@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
        ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
        itemViewHolder.onItemSelected();
    }

    super.onSelectedChanged(viewHolder, actionState);
}

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    super.clearView(recyclerView, viewHolder);

    ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
    itemViewHolder.onItemClear();
}
}

Add a package called listener and add an interface called OnStartDragListener.java and here is the content:

public interface OnCustomerListChangedListener {
void onNoteListChanged(List<Customer> customers);
}

Implement Custom Row

private RecyclerView mRecyclerView;
private CustomerListAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private ItemTouchHelper mItemTouchHelper;
private List<Customer> mCustomers;

After the onCreate method, add this method. And then call this method from the onCreate() method probably after the call to set Toolbar. Ignore the error warning for a minute.

private void setupRecyclerView(){
        mRecyclerView = (RecyclerView) `findViewById(R.id.note_recycler_view);`
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mCustomers = SampleData.addSampleCustomers();

        //setup the adapter with empty list
        mAdapter = new CustomerListAdapter(mCustomers, this, this, this);
        ItemTouchHelper.Callback callback = new `SimpleItemTouchHelperCallback(mAdapter);`
        mItemTouchHelper = new ItemTouchHelper(callback);
        mItemTouchHelper.attachToRecyclerView(mRecyclerView);
mRecyclerView.addItemDecoration(new  HorizontalDividerItemDecoration.Builder(this)

                .colorResId(R.color.colorPrimaryDark)
                .size(2)
                .build());
        mRecyclerView.setAdapter(mAdapter);
    }

Update the signature of your MainActivity to implement the two listeners that we added like below and use Android Studio quick fix to implement the methods.

public class MainActivity extends AppCompatActivity
implements OnCustomerListChangedListener,
    OnStartDragListener{

Here is the implementation of one of the methods, and we will implement the other one in the next section.

@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
    mItemTouchHelper.startDrag(viewHolder);

}

At this point, your drag and drop list should be working and we now want to remember the position of the list items after they have been re-organized. Like I mentioned at the beginning of the post, this is accomplished by saving the ids of the list items to SharedPreference so go ahead and add the following class members to the top of the file.

private SharedPreferences mSharedPreferences;
private SharedPreferences.Editor mEditor;
public static final String LIST_OF_SORTED_DATA_ID = "json_list_sorted_data_id";
public final static String PREFERENCE_FILE = "preference_file";

And in the onCreate() instantiate the SharedPreference like so:

mSharedPreferences = this.getApplicationContext()
            .getSharedPreferences(PREFERENCE_FILE, Context.MODE_PRIVATE);
    mEditor = mSharedPreferences.edit();

Then go ahead and implement the other method that listens for when the list changes and here is the implementation of that method:

@Override
public void onNoteListChanged(List<Customer> customers) {
    //after drag and drop operation, the new list of Customers is passed in here

    //create a List of Long to hold the Ids of the
    //Customers in the List
    List<Long> listOfSortedCustomerId = new ArrayList<Long>();

    for (Customer customer: customers){
        listOfSortedCustomerId.add(customer.getId());
    }

    //convert the List of Longs to a JSON string
    Gson gson = new Gson();
    String jsonListOfSortedCustomerIds = gson.toJson(listOfSortedCustomerId);


    //save to SharedPreference
    mEditor.putString(LIST_OF_SORTED_DATA_ID, jsonListOfSortedCustomerIds).commit();
    mEditor.commit();
}

Then, add this method to your MainActivity.java:

private List<Customer> getSampleData(){

    //Get the sample data
    List<Customer> customerList = SampleData.addSampleCustomers();

    //create an empty array to hold the list of sorted Customers
    List<Customer> sortedCustomers = new ArrayList<Customer>();

    //get the JSON array of the ordered of sorted customers
    String jsonListOfSortedCustomerId = mSharedPreferences.getString(LIST_OF_SORTED_DATA_ID, "");

    //check for null
    if (!jsonListOfSortedCustomerId.isEmpty()){

        //convert JSON array into a List<Long>
        Gson gson = new Gson();
        List<Long> listOfSortedCustomersId = gson.fromJson
        (jsonListOfSortedCustomerId, new TypeToken<List<Long>>(){}.getType());

        //build sorted list
        if (listOfSortedCustomersId != null && listOfSortedCustomersId.size() > 0){
            for (Long id: listOfSortedCustomersId){
                for (Customer customer: customerList){
                    if (customer.getId().equals(id)){
                        sortedCustomers.add(customer);
                        customerList.remove(customer);
                        break;
                    }
                }
            }
        }

        //if there are still customers that were not in the sorted list
        //maybe they were added after the last drag and drop
        //add them to the sorted list
        if (customerList.size() > 0){
            sortedCustomers.addAll(customerList);
        }

        return sortedCustomers;
    }else {
       return customerList;
    }
}

Now update the line in setupRecyclerView() that you get the data from:

mCustomers = SampleData.addSampleCustomers();

to:

mCustomers = getSampleData();

Here is the source of my answer you can find more information and description about every single step.

Glory
  • 1,007
  • 9
  • 14
  • 1
    This is a borderline [link-only answer](//meta.stackexchange.com/q/8231). You should expand your answer to include as much information here, and use the link only for reference. – Blue Jun 10 '17 at 03:18
  • @Glory I have tried this answer but this is not working it is leading to me at `non-null exception` at the `if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { mDragStartListener.onStartDrag(holder); }` – TheCoderGuy Feb 25 '19 at 22:28