RecyclerView适配器notifyDataSetChanged停止花哨的动画

elg*_*gui 29 android adapter android-recyclerview

我正在构建一个基于RecyclerView的组件,允许用户通过拖放重新排序项目.一旦我在DragListener端,我需要它在适配器中的位置,以便执行正确的移动,但我只能访问视图.所以这是我在适配器视图绑定中所做的事情:

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    Track track = mArray.get(position);
    viewHolder.itemView.setTag(R.string.TAG_ITEM_POSITION, position);
}
Run Code Online (Sandbox Code Playgroud)

你觉得这样对吗?因为如果我移动这样的项目:

public void move(int from, int to){
    Track track = mArray.remove(from);
    mArray.add(to, track);
    notifyItemMoved(from, to);
}
Run Code Online (Sandbox Code Playgroud)

然后位置标记不再正确,如果我notifyDataSetChanged(),我失去了花哨的动画.有什么建议吗?

toc*_*kov 112

有一种方法可以保留精美的动画 notifyDataSetChanged()

  1. 你需要GridLayoutManager使用overriden supportsPredictiveItemAnimations()方法返回自己的true;

  2. 你需要 mAdapter.setHasStableIds(true)

  3. 我发现棘手的部分是你需要覆盖适配器的getItemId()方法.它应该返回真正独特的值而不是直接函数position.就像是mItems.get(position).hashCode()

在我的情况下完美地工作 - 美丽的动画只添加,删除和移动项目使用 notifyDataSetChanged()

  • 你救了我很多痛苦的人,tyvm.顺便说一句,这应该被接受,而不是上面的答案. (17认同)
  • 最佳方案! (3认同)

yig*_*git 5

不,这是错的.首先,在该方法返回后,您无法引用传递给onBindViewHolder的位置.当物品的位置发生变化时(由于物品移动等),RecyclerView不会重新绑定视图.

相反,您可以使用ViewHolder#getPosition()哪个将返回更新的位置.

如果你解决了这个问题,你的移动代码应该工作并提供漂亮的动画.

调用notifyDataSetChanged将阻止预测动画,所以只要你可以避免它.请参阅文档了解详细信

编辑(来自评论):从外部获取位置,从recyclerview获取子视图持有者,然后从vh获取位置.有关详细信息,请参阅RecyclerView api