RecyclerView corrupts view using notifyItemMoved()

前端 未结 4 2063
不知归路
不知归路 2021-01-02 04:08

I\'m having a problem with using the notifyItemMoved() method. It seems to be incorrectly displaying unmoved views.

My list has 4 element in it. What I w

相关标签:
4条回答
  • 2021-01-02 04:26

    To get the actual position of your item after a drag&drop, add this method to your adapter:

    private int getItemPosition(Item item){ // (<-- replace with your item)
        int i = 0;
        // (replace with your items and methods here)
        for (Item currentItem : mItems) {
            if (currentItem.getItemId() == item.getItemId()) break;
            i++;
        }
        return i;
    }
    

    and call this instead of the position given by the viewHolder.

    0 讨论(0)
  • 2021-01-02 04:27

    I had the same issue. RecyclerView-Items are corrupt on drag&drop. But I have found a simple solution: In your RecyclerView.Adapter.class be sure to have the following

    @Override
    public long getItemId(int position) {
        // here code for getting the right itemID, 
        // i.e. return super.getItemId(mPosition);
        // where mPosition ist the Position in the Collection.
    }
    

    You must return the right itemID for the position. From now on the Items are not corrupt.

    0 讨论(0)
  • Thank you to @david.mihola for leading me to what I'm doing wrong.

    This took so long to figure out as the symptom didn't make the problem obvious!

    I was doing this:

    Collections.swap(mProductItems, i, indexOfCorrectItem);
    notifyItemMoved(i, indexOfCorrectItem)
    

    But, I obviously didn't think through what notifyItemMoved() was actually doing. It is only notifying the adapter that item i has moved to indexOfCorrectItem it isn't telling the adapter that indexOfCorrectItem has also moved to i.

    Under the covers it was doing the following:

    1. Move item 1 to 3
    2. Move what was at 2 to 1 to fill the gap
    3. Move what was at 3 to 2 to fill the gap
    4. notifyItemChanged(1);
    5. notifyItemChanged(3);

    The above of course leaves item 3 moved down to item 2 without a refreshed view! It was steps 4 and 5 which were hiding the problem by making item1 and item3 display correctly and leaving item2 incorrect!

    As soon as I realised this I tried the following code:

    notifyItemMoved(indexOfCorrectItem, i);
    notifyItemMoved(i, indexOfCorrectItem);
    

    This left the list in the correct order, but it short circuited the animation.

    So, instead, I dumped swapping altogether:

    mProductItems.remove(indexOfCorrectItem);
    mProductItems.add(i, correctItem);
    notifyItemMoved(indexOfCorrectItem, i);
    
    0 讨论(0)
  • 2021-01-02 04:43

    Well, I handled it in a slightly different way, might help others.

            Collections.swap(mItemList, fromPosition, toPosition);
            // Need to do below, because NotifyItemMove only handle one sided move
            Item fromItem = mItemList.get(fromPosition);
            Item toItem = mItemList.get(toPosition);
            notifyItemChanged(fromPosition, toItem);
            notifyItemChanged(toPosition, fromItem);
    

    I had to reorder items on a grid, and save the positions to a file. @Graeme was right, but i didn't wanted to give up on swapping. So just like @saganaut i sticked to notifyItemChanged. But only using notifyItemChanged sometimes left both swapped items on my grid with same items, so I binded the items with notifyItemChanged. It is not killing the animation, and is working as expected.

    0 讨论(0)
提交回复
热议问题