I have been going at this problem for many days now with no end in sight, so any help would definetely be appreciated! This is the problem:
I have a room database and a recycler view where I display part of that database. And generally everything works fine. However, if I try to drag (thus switching the order) of two items with different viewtypes, the adapter drops the item back at his original place.
This previous stack overflow question displays the problem beautifully:Android RecyclerView: drag and drop over multiple ViewType
The code: (In the fragment java)
// Configuring RecycleView
RecyclerView recyclerView = root.findViewById(R.id.recyclerview_viewpager_schedule);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setHasFixedSize(true);
// configuring Adapter
daysAdapter = new DaysAdapter();
prevfrom = -1;
flagish = -1;
//daysAdapter.setHasStableIds(true);
recyclerView.setAdapter(daysAdapter);
daysViewModel.getNotesInDay(args.getInt(ARG_OBJECT)).observe(getViewLifecycleOwner(), new Observer<List<DayActivity>>() {
@Override
public void onChanged(List<DayActivity> dayActivities) {
//I use a flag in order for the list not to update onMove because that makes a weird looking effect. It updates later on and it works just fine!
if (flagish != 5) daysAdapter.submitList(dayActivities);
flagish = 1;
}
});
ItemTouchHelper mIth = new ItemTouchHelper(
new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0) {
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
final int fromPos = viewHolder.getAdapterPosition();
final int toPos = target.getAdapterPosition();
Log.d("onMove", "From:" + fromPos);
Log.d("onMove", "to:" + toPos);
Log.d("STOP_HERE_please_1", fromPos + " " + toPos);
Bundle arguments = getArguments();
Log.d("STOP_HERE_3", String.valueOf(arguments.getInt(ARG_OBJECT)));
if (fromPos==toPos) return false;
//prevFrom is the previous fromPos in case the item hansn't been dropped yet
if (prevfrom == -1) prevfrom = fromPos;
if (prevfrom == toPos) return false;
getView().clearFocus();
// Change position
DayActivity lItem;
newList = new ArrayList<>();
int lIncrement = (fromPos<toPos) ? -1 : +1; // true if scroll down
int lMax = Integer.max(prevfrom, toPos);
int lMin = Integer.min(prevfrom, toPos);
List<DayActivity>oldList =daysAdapter.getOrdersBetween(lMin, lMax);
//This function (getOrdersBetween) gets the DayActivities whose positions are between those two values
for (int i=lMin; i<= lMax; i++) {
lItem = oldList.get(i);
if (i == fromPos) {
lItem.setOrder_Day(toPos);
} else
lItem.setOrder_Day(lItem.getOrder_Day() + lIncrement);
//The program uses the order to order the items in the recycler view
newList.add(lItem);
}
daysAdapter.notifyItemMoved(fromPos, toPos);
return true;
}
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ACTION_STATE_DRAG)
viewHolder.itemView.setAlpha(0.5f);
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1.0f);
flagish = 5;
if(newList != null) daysViewModel.updateList(newList);
prevfrom = -1;
}
I believe the problem is routed in the adapter.notifyitemmoved, but I haven't been able to solve it! Some people reccommended in other posts for me to make sethasStableIds(), but this function only lead notifyItemMoved to have a similar effect even if the two items have simiar viewtypes.
I don't think there is any need to overload this post with code from the adapter, but if anyone needs it, just let me know. Thanks!!!