NotifyItemMoved between different ViewTypes Not Working

Viewed 205

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!!!

0 Answers
Related