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.