当前位置: 首页 > 知识库问答 >
问题:

禁用在回收器的项目动画器上更改动画查看

谯英彦
2023-03-14

我正在使用使用SortedListAdapterCallbackSortedList中提供数据的RecyclView。我想禁用onChange事件的动画,但将它们保留为onInserted/onRemve/onMove。我尝试在RecyclView使用的DefaultItemAnimator上调用setSupport portsChangeAnimations(false),但动画仍然出现。如果我调用setItemAnimator(null),所有动画都会按预期成功删除。

我尝试查看实现,似乎如果support sChangeAnimationstrueRecyclView将通过保留旧的viewHolder并将其交叉淡出到新的viewHolder来对更改事件进行动画处理。我不想这样。如果support sChangeAnimationsfalse,则旧的和新的viewHolders将是相同的对象,取而代之的是从x到x的onMove动画(即没有实际移动)。然而,这意味着该项目将获得烦人的反弹效果。我也不想这样,我根本不想要动画。:(

来自DefaultItemAnimator.java:

@Override
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
        int fromX, int fromY, int toX, int toY) {
    if (oldHolder == newHolder) {
        // Don't know how to run change animations when the same view holder is re-used.
        // run a move animation to handle position changes.
        return animateMove(oldHolder, fromX, fromY, toX, toY);
    }
    ...

有时候,当我加载我的列表时,我会异步获取一些数据并更新条目1-3次,当它每次跳动和闪烁时,看起来真的很糟糕。

如何有效地完全禁用onChange动画,而不必编写完全自定义的ItemAnimator?

共有3个答案

公孙锋
2023-03-14

上述解决方案不适用于25.3.1版本的支持库,因为我想禁用所有回收器视图项目的动画。我通过重写< code > simpleitemnanimator 解决了这个问题:

private class NoAnimationItemAnimator extends SimpleItemAnimator {
    @Override
    public boolean animateRemove(RecyclerView.ViewHolder holder) {
        dispatchRemoveFinished(holder);

        return false;
    }

    @Override
    public boolean animateAdd(RecyclerView.ViewHolder holder) {
        dispatchAddFinished(holder);

        return false;
    }

    @Override
    public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
        dispatchMoveFinished(holder);

        return false;
    }

    @Override
    public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
        dispatchChangeFinished(oldHolder, true);
        dispatchChangeFinished(newHolder, false);

        return false;
    }

    @Override
    public void runPendingAnimations() {
        // stub
    }

    @Override
    public void endAnimation(RecyclerView.ViewHolder item) {
        // stub
    }

    @Override
    public void endAnimations() {
        // stub
    }

    @Override
    public boolean isRunning() {
        return false;
    }
}
淳于玺
2023-03-14

查看代码(我正在使用支持库25.2.0):setSupportsChangeAnimations(

在<code>DefaultItemAnimator</code>的代码中执行文本搜索,会发现既不查询<code>MSSupportsChangeAnimations</code>也不查询<code>GetSupportsChangAnimationS()</code>--

正确的解决方案是以下列方式扩展< code > defaultitemanitor :

public class CustomItemAnimator extends DefaultItemAnimator {
@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
    if (getSupportsChangeAnimations()) {
        return super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY);
    } else {
        if (oldHolder == newHolder) {
            if (oldHolder != null) {
                //if the two holders are equal, call dispatch change only once
                dispatchChangeFinished(oldHolder, /*ignored*/true);
            }
        } else {
            //else call dispatch change once for every non-null holder
            if (oldHolder != null) {
                dispatchChangeFinished(oldHolder, true);
            }
            if (newHolder != null) {
                dispatchChangeFinished(newHolder, false);
            }
        }
        //we don't need a call to requestPendingTransactions after this, return false.
        return false;
    }
}

请参阅文档animateChange(…),了解在没有运行动画时为什么需要调用dispatchChangeFinished(…)

当没有要运行的动画时,可能有一种更优雅的方式来编写else分支,但是,唉,这实现了期望的行为。

有点晚了,但希望这有所帮助!

简培
2023-03-14

在这一点上,我有点晚了,但使用< code > androidx . recycle view:recycle view:1 . 1 . 0 我可以将更改默认动画师的< code>changeDuration设置为0,这有效地禁用了动画,同时允许添加/移动/删除动画继续正常运行。不需要自定义重写< code>DefaultItemAnimator。

示例(在 Kotlin 中):

view.my_recycler_view.itemAnimator?.changeDuration = 0
 类似资料:
  • 我添加了一个自定义的< code > ItemTouchHelper。我的< code > recycle view 的SimpleCallback类,以添加“滑动时消除”功能,用户可以向左滑动项目,项目将从列表中删除。 我将视图可以“滑动”到左侧的量限制为视图长度的 10%,方法是将 dX(来自 onChildDraw())除以 10。但是,用户必须滑动的长度量是屏幕的 100%,以便项目被滑动

  • 假设我单击2位置的项目(记住其布局是颠倒的),然后调用 通知项目已更改(2[位置]) 在onBindViewHolder中,我在单击的项目上显示一些视图,因此它的高度会发生变化,当RecyclView测量它的孩子时,它会意识到它应该移动一些项目以使该项目的高度变化看起来引人入胜))。DefaultItemAnimator会处理它,但它会将所有低于“U are??? Omg谢谢u”项目的孩子向下移动

  • 动画控制器 动画控制器允许你为一个角色或其他游戏对象安排和维护一组动画。 控制器引用了动画剪辑,并且使用 状态机 来管理各种动画状态和它们之间的转换,可以把状态机认为是一种流程图,或者是一段在 Unity 中用可视化编程语言编写的简单程序。 下面的章节涵盖了 动画系统 Mecanim 提供的控制和序列化动画的主要功能。

  • 我正在尝试使回收器视图中的cardview展开。我让扩展部分正常工作,但是当向其添加过渡时,开始出现一些视觉错误。当没有屏幕外项目时,过渡工作正常,但是当我向回收器视图添加超过(在我的情况下)4个项目时,它开始发生。 带4件物品的GIF 包含 4 个以上项目的 GIF 当我禁用过渡动画时,卡视图扩展可以很好地处理超过4个项目。我认为问题与职位变化有关,但我找不到解决问题的任何解决方案。 我用来实现

  • 我正在从事一个自由职业者的android项目。我有一个问题,就是根据项目设计需要改变RecyclerView项目之间的利润率。我想显示屏幕上最后一个可见项目的一半,这样用户就可以猜测水平滚动。我尝试创建一个自定义的RecyclerView.itemEdition。当屏幕第一次打开时,一切正常,但当我开始在这个回收视图上水平滚动时,项目之间的间隔增加了,有时甚至减少了。我如何用一般方法解决这个问题。

  • 如何在swapCursor函数中实现回收器视图默认项添加/删除动画。notifyDataSetChanged()不会显示任何动画。