【问题标题】:How to disable animation for ListAdapter如何禁用 ListAdapter 的动画
【发布时间】:2018-11-05 08:51:04
【问题描述】:

我正在使用新的ListAdapter,它会自动为更改设置动画。我想禁用动画或以编程方式启用/禁用它。

class UserAdapter extends ListAdapter<User, UserViewHolder> {
     public UserAdapter() {
         super(User.DIFF_CALLBACK);
     }
     @Override
     public void onBindViewHolder(UserViewHolder holder, int position) {
         holder.bindTo(getItem(position));
     }
     public static final DiffUtil.ItemCallback<User> DIFF_CALLBACK =
             new DiffUtil.ItemCallback<User>() {
         @Override
         public boolean areItemsTheSame(
                 @NonNull User oldUser, @NonNull User newUser) {
             // User properties may have changed if reloaded from the DB, but ID is fixed
             return oldUser.getId() == newUser.getId();
         }
         @Override
         public boolean areContentsTheSame(
                 @NonNull User oldUser, @NonNull User newUser) {
             // NOTE: if you use equals, your object must properly override Object#equals()
             // Incorrectly returning false here will result in too many animations.
             return oldUser.equals(newUser);
         }
     }
 }

【问题讨论】:

  • 在父布局上试试android:animateLayoutChanges="false"
  • 我在父布局和 recyclerview 上尝试过 (android:animateLayoutChanges="false"),但没有工作。

标签: android android-recyclerview listadapter


【解决方案1】:

另一种解决方案是完全删除项目动画师。

recyclerView.itemAnimator = null

【讨论】:

  • 然后通过recyclerView.itemAnimator = new DefaultItemAnimator()恢复动画
【解决方案2】:

您可以尝试在 RecyclerView 项目动画师上使用 setSupportsChangeAnimations 禁用或启用动画:

SimpleItemAnimator itemAnimator = (SimpleItemAnimator) recyclerView.getItemAnimator();
itemAnimator.setSupportsChangeAnimations(false);

【讨论】:

  • 不错的亚伦!您是否为 Espresso 测试这样做过?
  • 嗨,马特!不,我没有将它用于 Espresso 测试,它应该可以在不关闭更改动画的情况下正常工作:D
【解决方案3】:

绕过DiffUtil的解决方案

itemAnimator 设置为null 并调用submitList() 仍会在后台线程中运行DiffUtil.ItemCallback,并且不会在同一帧上提交列表!如果您想要与调用notifyDataSetChanged() 相同的行为,您可以这样做:

adapter.submitList(null)
adapter.submitList(newItems)

如果您知道内容确实完全不同并且不在乎是否松开滚动位置,这很有用。或者,如果您有多个RecyclerViews,它们都必须在同一帧上更新(以减少屏幕闪烁)。

为什么会这样?

AsyncListDiffer.submitList()的源码:

// fast simple remove all
if (newList == null) {
    //noinspection ConstantConditions
    int countRemoved = mList.size();
    mList = null;
    mReadOnlyList = Collections.emptyList();
    // notify last, after list is updated
    mUpdateCallback.onRemoved(0, countRemoved);
    onCurrentListChanged(previousList, commitCallback);
    return;
}

// fast simple first insert
if (mList == null) {
    mList = newList;
    mReadOnlyList = Collections.unmodifiableList(newList);
    // notify last, after list is updated
    mUpdateCallback.onInserted(0, newList.size());
    onCurrentListChanged(previousList, commitCallback);
    return;
}

当您第一次拨打submitList() 时,所有项目都会立即删除。第二次立即插入,从不调用DiffUtil 或启动后台线程计算。

把它们放在一起

if(animations) {
    adapter.submitList(newItems)
} else {
    recyclerView.itemAnimator = null
    adapter.submitList(null)
    adapter.submitList(newItems) {
        recyclerView.post {
            //Restore the default item animator
            recyclerView.itemAnimator = DefaultItemAnimator()
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2019-11-23
    • 2015-06-08
    • 1970-01-01
    相关资源
    最近更新 更多