6

First of all, I worked on this all day but could not get anything done. I have a RecyclerView with an adapter that uses RecyclerView's SortedList. I tried implementing TouchHelper with the callback class:

public class TimerListTouchHelperCallback extends ItemTouchHelper.SimpleCallback {

    private OnItemChangeListener onItemChangeListener;

    public TimerListTouchHelperCallback(OnItemChangeListener listener, int dragDirs, int swipeDirs) {
        super(dragDirs, swipeDirs);

        this.onItemChangeListener = listener;

    }

    @Override
    public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        TimerHolder holder = (TimerHolder) viewHolder;

        int holderState = holder.getState();

        if (holderState == TimerHolder.TIMER_PENDING_DELETE) return 0;
        else return super.getSwipeDirs(recyclerView, viewHolder);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
        return false;
    }




    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
        TimerHolder holder = (TimerHolder) viewHolder;

        int position = holder.getAdapterPosition();
        // ViewHolder's state is changed that should handle the layout change.
        holder.setState(TimerHolder.TIMER_PENDING_DELETE); 

        if (onItemChangeListener != null) onItemChangeListener.onItemSwiped(position);
    }


    protected interface OnItemChangeListener{
        void onItemSwiped(int position);
    }
}

Here is the initialization of the TouchHelper

timerAdapter = new TimerAdapter(this, timerList);
    timerListView.setAdapter(timerAdapter);

TimerListTouchHelperCallback touchHelperCallback = new TimerListTouchHelperCallback(
        timerAdapter,
        ItemTouchHelper.LEFT,
        ItemTouchHelper.LEFT);

ItemTouchHelper swipeToDismissTouchHelper = new ItemTouchHelper(touchHelperCallback);

swipeToDismissTouchHelper.attachToRecyclerView(timerListView);

My adapter implements the interface OnItemChangeListener

@Override
public void onItemSwiped(int position) {
    notifyItemChanged(position);
    removalPendingTimers.add(timerList.get(position));
}

My ViewHolder reads the state and when the state is TimerHolder.TIMER_PENDING_DELETE it hides the rest of the view and shows the interface with an undo button. But this is not happening until I scroll the view out and scroll it back again. Any suggestions what I am missing?

Problem case

Links

Adapter class ViewHolder class

Aayush Subedi
  • 141
  • 1
  • 12

2 Answers2

3

Finally got it running. Since notifyItemChanged was not cutting it (which it should have), I used notifyItemRemoved followed by notifyItemInserted.

Lags just a little bit but works.

Aayush Subedi
  • 141
  • 1
  • 12
  • I'm currently running into the same issue and using `notifyItemRemoved` followed by `notifyItemInserted` seems to work. Oddly `notifyDataSetChanged` also works but not`notifyItemChanged`. It's not an ideal fix but better then refreshing the entire list. – Kris B May 24 '19 at 00:31
  • on my `dimissListener` i needed to add a `notifyItemChanged` to get work perfectly – Acauã Pitta Apr 15 '20 at 20:58
2

I've created a simple example Android App to better understand the question.

It makes use of notifyItemChanged(position); when the user swipes the item left or right to show the undo view. When the undo time expires it calls notifyItemRemoved(position) to remove it from the list. See the GIF for example, does not leave any empty rows.

https://github.com/DawidvanGraan/ExampleRecycleViewSwipeDismiss

  • I was looking at the code all night yesterday, and it seems there is something wrong with my implementation of recyclerview and adapter and not with the TouchHelperClass – Aayush Subedi Aug 19 '16 at 10:24