Android动画了解—RecyclerView Animator

本文深入探讨了RecyclerView动画的实现原理,包括初始化、添加、移除、更新数据时的动画效果。通过自定义ItemAnimator,详细解释了如何实现添加、移动ItemView的动画效果,以及如何利用ViewCompat进行兼容性处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Recyclerview animation

什么时候开始的 RecyclerView animation,在我们UI 2.0~3.0的时候,很多地方都需要这种 RecyclerView 界面 初始化添加移除更新 数据的 动画效果样式.

看几个RecycelrView Adapter 初始化的小DEMO
在这里插入图片描述
在这里插入图片描述
除了这种方式进行初始化,我们还可以用前面所讲的过渡动画来进行

Transition explode = new Explode();
explode.setDuration(1000);
TransitionManager.beginDelayedTransition(recyclerView, explode);
if (recyclerView.getAdapter() != null) {
	recyclerView.setAdapter(null);
} else {
	recyclerView.setAdapter(mColorsAdapter);
}

在这里插入图片描述

再看看 RecyclerView Item 添加,移除,更新的的小栗子
在这里插入图片描述

如果没有设置 Item animation,RecyclerView 默认使用的就是 DefaultItemAnimator(继承的 SimpleItemAnimator)

如果想实现上面的一些效果(Demo地址),我们就需要 自定义自己的 Item Animator ,只需要继承 SimpleItemAnimator,重写几个关键的重要函数

函数名含义
animateRemoveitem 移除时的动画
animateAdditem 添加时的动画
animateMove移动时的动画 列表项位置移动时调用
animateChangeitem 更新时的动画
runPendingAnimations真正控制执行动画的地方
endAnimation停止某个Item的动画
endAnimations停止所有动画
isRunning返回当前是否有动画需要执行

在自定义Item Animator 中会调用到的相关函数:

函数名含义
dispatch(Add/Remove/Move/Change)Starting动画开始时调用,比如Add dispatchAddStarting
dispatch(Add/Remove/Move/Change)Finished动画结束时调用,比如Add dispatchAddFinished
dispatchAnimationsFinished所有动画结束时调用

引发 Item 动画的几个函数

Adapter.notifyItemInserted(int position) // 触发 Add Item Animator
Adapter.notifyItemRemoved(int position) // 触发 Remove Item Animator
Adapter.notifyItemChanged(int position) // 触发 Change Item Animator
Adapter.notifyItemMoved(int fromPosition, int  toPosition) // 触发 MoveItem Animator

先来自定义的一个添加Item View的动画效果的小DEMO

public class CumtomAnimator extends SimpleItemAnimator {
	// 保存 需要做 add 动画效果的 itemView 的数组
	private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
	@Override
    public boolean animateAdd(RecyclerView.ViewHolder holder) {
    	// 添加对应的数据,主要用于 runPendingAnimations 执行动画效果
    	mPendingAdditions.add(holder);
    }
    @Override
    public void runPendingAnimations() {
    	for (RecyclerView.ViewHolder holder : mPendingAdditions) {
            ViewCompat.animate(holder.itemView)
                    .scaleX(1.0f)
                    .scaleY(1.0f)
                    .setDuration(getAddDuration())
                    .start();
        }
        // 记得要清理掉,不然其它动画执行后,要被影响,而且也影响 isRunning 的判断
        mPendingAdditions.clear();
	}
	@Override
    public boolean isRunning() {
        return !mPendingAdditions.isEmpty()
               || ... ...
    }
    ... ...
}

ViewCompat:android官方实现兼容的一个帮助类,具体可以查找网上相关资料 官方资料

可以试试(notifyItemInserted(position))有没有动画效果,肯定是没有效果的,因为没有去初始化它 起始的样子!!!
在这里插入图片描述

来改改代码… …

... ...
public boolean animateAdd(RecyclerView.ViewHolder holder) {
	// 初始化动画状态
    // 将 ItemView 设置为 ScaleX,ScaleY 都为0
    // 那么执行动画效果的时候,就是从 中间位置 然后 放大 0.0f -> 1.0f
    View itemView = holder.itemView;
    ViewCompat.setPivotY(itemView, itemView.getMeasuredHeight() / 2);
    ViewCompat.setPivotX(itemView, itemView.getMeasuredWidth() / 2);
    ViewCompat.setScaleX(itemView, 0);
    ViewCompat.setScaleY(itemView, 0);
    // 添加对应的数据,主要用于 runPendingAnimations
    mPendingAdditions.add(holder);
}
... ...

代码修改后,添加 ItemView 就能达到下面的效果。
在这里插入图片描述
你会发现,上面的 RecyclerView ItemView的添加动画效果,还行,就是新增的时候,下面的其它的ItemView 移动的很生硬,所以这里就引出了 animateMove 函数。

函数名参数参数含义
animateMove(final ViewHolder holder, int fromX, int fromY, int toX, int toY)列表项位置移动时调用,移动的ViewHolder;fromX 起始x,y值;toX 目标x,y值
@Override
public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
	// 设置它的初始位置.
	final View view = holder.itemView;
	// 目标的位置 减去 起始位置(原来的位置),得到需要位移的距离
    int deltaX = toX - fromX;
    int deltaY = toY - fromY;
    // 设置后,相当于从 新的位置 回到了 原来的位置上.
    if (deltaX != 0) {
       ViewCompat.setTranslationX(view, -deltaX);
    }
    if (deltaY != 0) {
    	ViewCompat.setTranslationY(view, -deltaY);
    }
    mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
}

@Override
public void runPendingAnimations() {
    ... ...
    // 最后从原来的位置 做动画,回到新的位置上,就完整了移动的动画效果.
	for (MoveInfo moveInfo : mPendingMoves) {
		ViewCompat.animate(moveInfo.holder.itemView)
                  .translationX(0)
                  .translationY(0)
                  .setDuration(getMoveDuration())
                  .start();
	}
	mPendingMoves.clear();
	... ...
}

整个添加Item View的动画效果,就这样完成啦!!!
在这里插入图片描述
当然在项目,肯定没有那么简单,这里只是简单的举个小栗子,给大家说明下几个函数的重要性.

如果是项目中使用,只需要继承这个 BaseitemAnimator,写一些自己想要的效果就OK,不过这里已经实现了大多数的动画效果。
在这里插入图片描述 在这里插入图片描述
需要使用以上效果的小伙伴,自行下载,代码库地址
在这里插入图片描述

5.x 参考资料

RecyclerView animations 国外大神文章
RecyclerView anim视频

掌握RecyclerView动画不得不看的文章

谷歌API文档

深入理解 RecyclerView 系列之二:ItemAnimator

自定义RecyclerView ItemAnimator 上

自定义RecyclerView ItemAnimator 下


Android动画了解—转场/过渡(Transition) 动画<=上个章节 下个章节=> Android动画了解—其它动画

<think>我们正在讨论如何在Android中关闭RecyclerView在更新时的动画。 根据Android开发知识,RecyclerView动画是由ItemAnimator控制的。要禁用更新动画,我们需要设置一个自定义的ItemAnimator,并重写或禁用更新动画。 具体步骤: 1. 获取RecyclerView的ItemAnimator实例。 2. 我们可以通过设置一个自定义的ItemAnimator,并覆盖更新动画相关的方法,使其不执行动画。 3. 或者,我们可以使用一个已经存在的、没有动画的ItemAnimator,例如将ItemAnimator设置为null(但这样会禁用所有动画,包括添加、删除、移动等)。 4. 如果我们只想禁用更新动画(即change动画),而保留其他动画,我们可以自定义ItemAnimator。 然而,在RecyclerView中,默认的更新动画是通过DefaultItemAnimator实现的。我们可以通过设置一个自定义的ItemAnimator,并重写change相关的动画方法,使其不执行动画。 一个简单的方法是将ItemAnimator的change duration设置为0,但这样可能不会完全禁用动画(因为动画可能立即结束,但依然会触发)。更可靠的方式是覆盖相关方法。 实际上,我们可以创建一个自定义的ItemAnimator,继承自DefaultItemAnimator,然后重写`animateChange`方法,使其不执行动画,而是立即处理变更。 但更简单的方式是:在RecyclerView中,我们可以设置一个没有更新动画的ItemAnimator。例如,我们可以使用如下代码: ```java recyclerView.getItemAnimator().setSupportsChangeAnimations(false); ``` 注意:`setSupportsChangeAnimations(false)`是DefaultItemAnimator中的方法,它专门用于禁用change动画(即更新动画)。但前提是我们的ItemAnimator是DefaultItemAnimator(或其子类)。因为RecyclerView默认使用的是DefaultItemAnimator。 因此,我们可以这样写: ```java RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); if (animator instanceof DefaultItemAnimator) { ((DefaultItemAnimator) animator).setSupportsChangeAnimations(false); } ``` 这样,更新动画就会被禁用,而其他动画(如添加、删除)仍然保留。 如果我们想要禁用所有动画,我们可以将ItemAnimator设置为null: ```java recyclerView.setItemAnimator(null); ``` 但根据需求,我们只需要禁用更新动画,所以第一种方法更合适。 另外,如果我们使用的是其他LayoutManager或自定义的ItemAnimator,我们需要确保它支持禁用更新动画。 因此,推荐的方法是使用`setSupportsChangeAnimations(false)`。 参考:在Android官方文档中,DefaultItemAnimator的setSupportsChangeAnimations方法正是用于控制是否启用change动画。 根据引用[1]的内容,它并没有直接提到动画控制,所以我们可以忽略该引用。我们主要依据Android开发知识。 所以,总结如下: 要禁用RecyclerView的更新动画(即item更新时的动画),可以使用以下代码: ```java if (recyclerView.getItemAnimator() instanceof DefaultItemAnimator) { ((DefaultItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); } ``` 这样,当调用notifyItemChanged或notifyDataSetChanged等方法更新item时,就不会有动画效果了。 注意:如果我们的RecyclerView没有使用DefaultItemAnimator(例如使用了自定义的ItemAnimator),那么我们需要检查自定义的ItemAnimator并重写相关方法以禁用更新动画。 但是,默认情况下,RecyclerView使用的是DefaultItemAnimator。 因此,以上代码在大多数情况下是有效的。 现在,生成相关问题。</think>要在 Android 中禁用 RecyclerView 的更新动画,可以通过修改 ItemAnimator 实现。以下是具体方法和代码示例: ### 方法 1:禁用所有动画(推荐) ```java // 完全移除所有动画(包括更新、添加、删除等) recyclerView.setItemAnimator(null); ``` ### 方法 2:仅禁用更新动画 ```java // 保留其他动画,仅禁用更新动画 if (recyclerView.getItemAnimator() instanceof SimpleItemAnimator) { ((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false); } ``` ### 方法 3:自定义无动画 ItemAnimator ```java // 创建自定义动画recyclerView.setItemAnimator(new DefaultItemAnimator() { @Override public boolean animateChange(...) { // 直接分发更新事件而不执行动画 dispatchChangeFinished(oldHolder, true); dispatchChangeFinished(newHolder, false); return false; } }); ``` ### 关键说明: 1. **`setItemAnimator(null)`** 是最彻底的解决方案,会完全移除所有类型的动画 2. **`setSupportsChangeAnimations(false)`** 仅针对更新操作禁用动画(需 API 11+) 3. 这些修改不会影响数据更新逻辑,仅改变视觉表现 4. 默认动画效果由 `DefaultItemAnimator` 提供[^1] ### 最佳实践: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = findViewById(R.id.recyclerview); recyclerView.setLayoutManager(new LinearLayoutManager(this)); // 禁用更新动画 recyclerView.setItemAnimator(null); // 设置适配器等后续操作... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值