【问题标题】:RecyclerView predictive item animations not working (APPEARING)RecyclerView 预测项目动画不起作用(出现)
【发布时间】:2015-05-24 12:50:56
【问题描述】:

我有一个带有 GridLayoutManager 的 RecyclerView(支持 lib v7)。我更新适配器并制作 notifyItemMoved。如果项目源位置在屏幕上并且目标位置也在屏幕上 - 播放“移动动画”。如果项目位于屏幕外的位置(位置 1000,或任何其他远离视口的位置)并移入视口,它将显示“动画淡入淡出”。

看起来预测项目动画不起作用,尽管事实上 supportsPredictiveItemAnimations() 返回 true。难道我做错了什么?我应该重写一些方法来启用它吗?

我在看RecyclerView的源码,在javadoc中dispatchLayout方法是这样写的:

  • PERSISTENT 视图被移动({@link ItemAnimator#animateMove(ViewHolder, int, int, int, int)})
  • REMOVED 视图被移除 ({@link ItemAnimator#animateRemove(ViewHolder)})
  • 添加了视图 ({@link ItemAnimator#animateAdd(ViewHolder)})
  • 消失的视图被移出屏幕
  • 出现的视图在屏幕上移动

尽管如此,ItemAnimator 并不区分 ADDED 和 APPEARING。 是否可以修复预测动画或至少使 APPEARING 动画看起来像“从屏幕动画外部移动”而留下 ADDED 动画?

【问题讨论】:

标签: android android-recyclerview gridlayoutmanager


【解决方案1】:

您可以尝试覆盖LinearLayoutManager 中的getExtraLayoutSpace(RecyclerView.State state),以为管理器提供额外的空间用于预测动画。

例子:

@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
    return getHeight(); // add extra page for better predictive animations
}

额外的空间将在开始或结束时添加,具体取决于滚动视图的前一个滚动增量。您可以查看LinearLayoutManager 的onLayoutChildren 的实现以获取更多详细信息。

【讨论】:

    【解决方案2】:

    我有同样的问题。检查是否设置了 ItemAnimator。 预测动画依赖于它,所以如果你打算使用 TransitionManager,然后创建空的 ItemAnimator 来启用预测动画。

    您可以查看源代码(LinearLayoutManager:组:'com.android.support',名称:'recyclerview-v7',版本:'27.0.2')。

    第 700-703 行:

    if (!state.willRunPredictiveAnimations() ||  getChildCount() == 0 || state.isPreLayout()
                || !supportsPredictiveItemAnimations()) {
            return;
        }
    

    state.willRunPredictiveAnimations() - 如果 ItemAnimator 为 null,则返回 false。

    EmptyItemAnimator.java

    public class EmptyItemAnimator extends RecyclerView.ItemAnimator {
    @Override
    public boolean isRunning() {
        return false;
    }
    
    @Override
    public void endAnimations() {}
    
    @Override
    public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
        return false;
    }
    
    @Override
    public void endAnimation(RecyclerView.ViewHolder item) {}
    
    @Override
    public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
        return false;
    }
    
    @Override
    public void runPendingAnimations() {}
    
    @Override
    public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
        return false;
    }
    
    @Override
    public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
        return false;
    }}
    

    现在你可以试试:

    TransitionManager.beginDelayedTransition(recyclerView);
    recyclerViewAdapter.notifyItem... //add, remove, change etc.
    

    【讨论】:

      猜你喜欢
      • 2021-11-20
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 2014-12-30
      • 2015-09-11
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      相关资源
      最近更新 更多