daimajia / AndroidSwipeLayout

The Most Powerful Swipe Layout!
MIT License
12.38k stars 2.67k forks source link

RecyclerView Delete Element on Swipe #201

Open agrrwall opened 9 years ago

agrrwall commented 9 years ago

I've noticed some strange issues with Swiping to Delete elements. To make this easy, I've used the sample to show case my issue. If I swipe to delete an element, the element below stays in the delete state. Basically, it looks like the bottom layout stays over the next element.

Here's what happens in the sample: Original Load: screenshot_2015-08-10-12-25-39

Swipe Left on Top Element (Alabama):

screenshot_2015-08-10-12-26-23

Notice that Alabama gets deleted, but Alaska (the element below) still has the bottom view open. I can't figure out how to prevent this behavior. To try out the code, simply replace the OnCreateViewHolder from the sample with the following (has some logging):

    @Override
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
    final SimpleViewHolder viewHolder = new SimpleViewHolder(view);

    SwipeLayout swipeLayout = viewHolder.swipeLayout;

    swipeLayout.addSwipeListener(new SimpleSwipeListener() {

        @Override
        public void onOpen(SwipeLayout layout) {

            Log.d("Swiped Opened", viewHolder.textViewData.getText().toString());
            int position = mDataset.indexOf(viewHolder.textViewData.getText());
            mItemManger.removeShownLayouts(viewHolder.swipeLayout);
            mDataset.remove(position);
            notifyItemRemoved(position);
            notifyItemRangeChanged(position, mDataset.size());
            mItemManger.closeAllItems();

            Log.d("Swipe Deleted", viewHolder.textViewData.getText().toString() + String.valueOf(position));
            //Toast.makeText(view.getContext(), "Deleted " + viewHolder.textViewName.getText().toString() + "!", Toast.LENGTH_SHORT).show();

        }

    });

    return viewHolder;
}

I noticed when I remove the notifyItemRangeChanged(...), the situation looks a little better, but it turns out random elements still look like Delete Item. Any thoughts/suggestions?

Edit: Ignore the multiple/single mode. Looks like this happens regardless :(

Alexander-- commented 9 years ago

This is because SwipeItemMangerImpl tracks item state using position in list instead of id. Position is just a visible location on screen, so when something gets deleted (and another item takes it's position), things get ugly.

Usage of stable ids (returned by adapter.getItemId(position)) would solve this issue. You can read more about stables ids in this SO answer; it is about ListView, but same things apply to RecyclerView too.

Hope this helps. I also have a branch with fix, but it is against 1.1.8, and has few other changes.

fantasybei commented 8 years ago

+1 meet the same problem.

MHKalantarian commented 7 years ago

Same problem, it even brings back the deleted items. Please fix this @daimajia

AlaaZarifa commented 4 years ago

@Alexander-- getItemId did the trick! Thanks a lot.

r020477888 commented 4 years ago

Same problem.....