Reputation: 4731
I have a RecyclerView
whose layout is a GridLayout
of 3 columns. I am using ItemTouchHelper to drag and drop in the GridLayout
of the RecyclerView
. In my Adapter there is a method onItemMove()
which notify me the items which i have moved. It only swaps those items in the ArrayList
which I have dragged and dropped. But due to the drag and drop there is a shift in other elements as well. I want to update their positions as well in the ArrayList
.
Here is the Adapter of my Recyclerview:
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.MyViewHolder> implements com.sagar.quizdemo.helper.ItemTouchHelperAdapter {
String[] str = {"Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6", "Level 7", "Level 8", "Level 9"};
List<String> itemList, actualList;
LayoutInflater inflater;
Context context;
private final OnStartDragListener mDragStartListener;
public GridAdapter(Context context, OnStartDragListener dragStartListener) {
this.context = context;
mDragStartListener = dragStartListener;
inflater = LayoutInflater.from(context);
itemList = new ArrayList<>();
actualList = new ArrayList<>(Arrays.asList(str));
}
public void getItemList(List<String> nameList) {
int currentSize = itemList.size();
itemList.clear();
itemList.addAll(nameList);
notifyItemRangeRemoved(0, currentSize);
notifyItemRangeInserted(0, nameList.size());
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.custom_level_row, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.textView.setText(itemList.get(position));
// Start a drag whenever the handle view it touched
holder.cardView.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 itemList.size();
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(itemList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
notifyItemChanged(fromPosition);
notifyItemChanged(toPosition);
return true;
}
@Override
public void onItemDismiss(int position) {
itemList.remove(position);
notifyItemRemoved(position);
}
public class MyViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
CardView cardView;
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.gameCard);
textView = (TextView) itemView.findViewById(R.id.gameText);
}
@Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
itemView.setBackgroundColor(Color.WHITE);
}
}
}
if initially the list is :
{"Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "Level 6", "Level 7", "Level 8", "Level 9"}
After I swap 2nd and 4th positioned elements in the RecyclerView. The updated list should look like this (which I want):
{"Level 1", "Level 5", "Level 2", "Level 3", "Level 4", "Level 6", "Level 7", "Level 8", "Level 9"}
But I am getting this updated list:
{"Level 1", "Level 5", "Level 3", "Level 4", "Level 2", "Level 6", "Level 7", "Level 8", "Level 9"}
Upvotes: 4
Views: 3146
Reputation: 199
Code here working for me.
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(listData, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(listData, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
Upvotes: 2
Reputation: 235
Try calling notifyDataSetChanged() in onItemMove menthod.
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
notifyItemMoved(fromPosition, toPosition);
notifyItemChanged(fromPosition);
notifyItemChanged(toPosition);
notifyDataSetChanged();
return true;
}
Upvotes: 1
Reputation: 81
Try this instead. In your case, you will first have to find the index of the item to be replaced (fromPosition) and then add toPosition to that index. How to move specific item in array list to the first item
Upvotes: 0
Reputation: 240
I believe that your problem is that you use Collections.swap(itemList, fromPosition, toPosition);
, which swaps objects on the specified positions. So the output is correct. What you need, though:
String item = itemList.remove(fromPostion);
itemList.insert(item, toPosition);
Upvotes: 6