Android 常用动画梳理

307 阅读8分钟

Android 日常开发中为了页面美观,我们要实现控件的各种动画.Android系统提供了各种各样的动画来满足我们的需求.但是各种动画是满足不同需求的控件展示.以前开发只是用 没系统梳理过.最近实现直播用到各种各样的动画,再次梳理一下.

1:动画种类以及性能表现

以下是 Android 动画类型及其是否触发重绘、性能表现的对比表格:

Android 动画类型对比表(优化版)

动画类型核心实现方式是否触发重绘性能表现典型应用场景示例类 / 属性
属性动画修改 View 或对象属性(支持硬件加速)✅ 是(多数)⭐⭐⭐⭐平移、缩放、透明度、旋转translationX/Y, scaleX/Y, alpha, ObjectAnimator
补间动画修改 Canvas 的变换矩阵,不改变真实属性❌ 否⭐⭐⭐简单视觉动画(如淡入淡出)TranslateAnimation, AlphaAnimation, <scale>
帧动画按帧切换图片资源(Bitmap)✅ 是(每帧)加载动画、帧动画特效AnimationDrawable, <animation-list>
布局动画布局变更时对子 View 应用动画✅ 是(布局)⭐⭐RecyclerView 增删动画LayoutTransition, DefaultItemAnimator
矢量动画动态修改 SVG 路径、颜色、属性✅ 是(矢量)⭐⭐⭐⭐图标切换、菜单动效AnimatedVectorDrawable, pathData, fillColor

2:动画介绍以及使用

2.1 属性动画(设置属性会重绘)

在 Android 开发中,属性动画(Property Animation)  是通过直接修改视图的属性(如位置、旋转角度、透明度等)来实现动画效果的机制.

核心类

  • ValueAnimator:计算属性值的变化,但不直接作用于对象,需手动更新属性。
  • ObjectAnimator:继承自 ValueAnimator,直接操作对象的属性,无需手动更新。
  • AnimatorSet:组合多个动画,支持并行或顺序播放。

重绘说明:

  • 属性动画默认基于 硬件加速(Android 3.0+ 系统默认开启),通过 GPU 直接操作视图的属性(如位移、旋转等),无需通知 View 重新绘制自身

  • 如果动画修改的属性涉及 布局参数(如 LayoutParams.width)或 内容更新(如 TextView.setText()),则可能间接触发重绘。

1. 平移动画
val anim = ObjectAnimator.ofFloat(view, "translationX", 0f, 200f)
anim.duration = 500
anim.start()

2. 透明度动画
ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
    duration = 800
    start()
}
3. 旋转动画
ObjectAnimator.ofFloat(view, "rotation", 0f, 360f).apply {
    duration = 1000
    interpolator = AccelerateDecelerateInterpolator()
    start()
}
4. 缩放动画
AnimatorSet().apply {
    playTogether(
        ObjectAnimator.ofFloat(view, "scaleX", 1f, 1.5f),
        ObjectAnimator.ofFloat(view, "scaleY", 1f, 1.5f)
    )
    duration = 500
    start()
}

5:组合动画 AnimatorSet
val move = ObjectAnimator.ofFloat(view, "translationX", 0f, 300f)
val fade = ObjectAnimator.ofFloat(view, "alpha", 1f, 0.5f)

AnimatorSet().apply {
    playSequentially(move, fade)  // 或 playTogether(...)
    duration = 1000
    start()
}

插值器说明:

插值器效果
LinearInterpolator匀速
AccelerateInterpolator加速
DecelerateInterpolator减速
BounceInterpolator弹跳
OvershootInterpolator超出再回弹

2.2 视图动画

在 Android 中,视图动画(View Animation)  是一个统称,包含了 补间动画(Tween Animation)  和 帧动画(Frame Animation)  两种类型

视图动画是 Android 早期(API Level 1 开始支持)提供的动画系统,通过对 View 的视觉效果进行变换来实现动画,但 不改变 View 的实际属性(如布局参数、坐标值)

2.2.1 补间动画(不重绘)

补间动画是 Android 早期提供的一种动画机制,属于 View Animation 框架。通过在两个关键帧之间插值(tweening),实现 视觉上的动画效果,如平移、旋转、缩放、透明度等。

❗注意:补间动画只改变视觉,不改变 View 实际属性!

  • View 的 x/y、大小、点击区域都不会改变。
  • 不会触发 invalidate(),也不会重新布局
支持的动画类型
动画类型类名XML 标签描述
平移动画TranslateAnimation<translate>视觉上左右上下移动
缩放动画ScaleAnimation<scale>放大缩小视图
旋转动画RotateAnimation<rotate>绕某点旋转
透明动画AlphaAnimation<alpha>淡入淡出
动画集合AnimationSet<set>多个动画组合一起播放

示例:

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="100"
    android:duration="500"
    android:fillAfter="true" />

val anim = AnimationUtils.loadAnimation(context, R.anim.translate)
view.startAnimation(anim)


val animation = TranslateAnimation(0f, 300f, 0f, 0f).apply {
    duration = 1000
    fillAfter = true // 动画结束后保留状态(仅视觉)
}
view.startAnimation(animation)

注意事项
  • fillAfter = true:动画结束后保留视觉状态,但真实属性未改变。
  • 点击区域不会改变,即使视图“看起来”动了。
  • 不支持对非 View 对象(如数据类、属性值)做动画。
补间动画与属性动画的对比
对比项补间动画(Tween)属性动画(Property)
是否修改真实属性❌ 否✅ 是
是否触发重绘❌ 否✅ 是(多数情况)
动画目标限制只能作用于 View任意对象(包括非 UI)
控制粒度较低精细(自定义属性动画)
推荐程度❌ 过时✅ 推荐

2.2.2 帧动画

帧动画(Frame Animation)是通过依次播放一组静态图片(Drawable)来实现动画效果,就像“翻页书”或传统的手绘动画一样。

它是 Android 中最简单直接的动画方式,属于 Drawable Animation 范畴。

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false"> <!-- false 表示循环播放 -->
    
    <item android:drawable="@drawable/frame1" android:duration="100" />
    <item android:drawable="@drawable/frame2" android:duration="100" />
    <item android:drawable="@drawable/frame3" android:duration="100" />
    <!-- 可继续添加更多帧 -->
</animation-list>

val imageView = findViewById<ImageView>(R.id.imageView)
imageView.setBackgroundResource(R.drawable.frame_anim)

val animationDrawable = imageView.background as AnimationDrawable
animationDrawable.start()
注意事项与缺点
  • 每帧一张图,占用内存大(尤其是高清图)
  • 不适合高帧率或复杂动画
  • 加载帧数多时容易 OOM,建议帧数量控制在合理范围(<30)或使用小尺寸图片
  • 不能在 XML 中设置延迟启动或自动停止

2.3 布局动画

布局动画是指当布局中的 子视图被添加、删除或位置变化时,为这些变化应用过渡动画效果。
它是针对 ViewGroup 中的子元素 的动画处理,常见于如 RecyclerViewLinearLayoutGridLayout 等容器控件。

分类

类型简介
LayoutAnimation针对整个布局中子 View 的初始进入动画
LayoutTransition针对 ViewGroup 在运行时添加/删除子 View 时的动画(更灵活)
RecyclerView 动画Item 增删/移动动画,由 ItemAnimator 控制,属于布局动画的子集

核心特点对比

特性LayoutAnimationLayoutTransition
适用时机布局初始加载动态添加、删除 View 时
控制粒度针对所有子项统一应用对添加、删除、改变分别可设置动画
使用难度简单中等
性能中等(子项越多越慢)中等
是否触发重绘✅ 是(布局变化引发重绘)✅ 是
1:LayoutAnimation 使用方式(布局初次显示)

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1"
    android:duration="500" />
    
 <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/layout_anim_fade"
    android:delay="0.2"
    android:order="normal" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layoutAnimation="@anim/layout_animation_controller">
    
    <!-- 子 View 如 Button、TextView 等 -->
</LinearLayout>

2:LayoutTransition 使用方式(动态添加/删除 View)

val layout = findViewById<LinearLayout>(R.id.myLayout)

val transition = LayoutTransition().apply {
    enableTransitionType(LayoutTransition.APPEARING)
    enableTransitionType(LayoutTransition.DISAPPEARING)
}
layout.layoutTransition = transition

// 动态添加 View
val newView = Button(this).apply { text = "新增" }
layout.addView(newView)

3: RecyclerView 布局动画

recyclerView.itemAnimator = DefaultItemAnimator()
recyclerView.itemAnimator = object : DefaultItemAnimator() {
    override fun animateAdd(holder: RecyclerView.ViewHolder?): Boolean {
        // 自定义添加动画
        return super.animateAdd(holder)
    }
}

2.4 矢量动画

矢量动画是基于 VectorDrawable 的动画,通过动态修改矢量图的路径、颜色、形状等属性,实现平滑、可缩放且清晰的动画效果。

它包含两种主要形式:

  • AnimatedVectorDrawable:对矢量图形进行属性动画(Path、颜色、变换等)
  • VectorDrawable:静态矢量图形,支持基本形状和渐变

核心特点

特性描述
动画类型基于矢量图形属性变化的动画
控制对象AnimatedVectorDrawable 支持路径和属性动画
是否触发重绘✅ 是(每帧都会重绘矢量路径和颜色)
性能⭐⭐⭐⭐(矢量加硬件加速,性能优良)
兼容性API 21+(支持库可向下兼容部分功能)
优点文件小、无限缩放不失真、适合图标、按钮动画

示例:

1. 定义矢量图(res/drawable/ic_heart.xml)
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:name="heart"
        android:fillColor="#FF0000"
        android:pathData="M12,21.35L10.55,20.03 ..."/>
</vector>

2. 定义动画(res/animator/heart_path_morph.xml)
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="pathData"
    android:valueFrom="M12,21.35L10.55,20.03 ..."
    android:valueTo="M12,19L10,17.5 ..."
    android:valueType="pathType"/>

val imageView = findViewById<ImageView>(R.id.imageView)
imageView.setImageResource(R.drawable.avd_heart)
3. 定义 AnimatedVectorDrawable(res/drawable/avd_heart.xml)
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_heart">
    <target
        android:name="heart"
        android:animation="@animator/heart_path_morph" />
</animated-vector>


4. 在代码中使用
val drawable = imageView.drawable as AnimatedVectorDrawable
drawable.start()

注意事项

  • 动画属性要求是矢量路径或支持的可动画属性
  • 动画持续时间、插值器等都可自定义
  • 需注意兼容性,Android Support Library 提供 AnimatedVectorDrawableCompat 向下兼容
  • 路径动画对路径的点数和结构有要求,需匹配才能平滑过渡

3:常用动画库

  • Lottie:支持 AE 导出的 JSON 动画,实现复杂设计效果。
  • Glide/Coil:图片加载库自带淡入动画,可自定义。
  • Rebound:Facebook 弹性动画库,模拟物理效果。
  • ViewPropertyAnimator:简化版属性动画 API,链式调用更简洁。

4: 选择合适的动画系统

需求场景推荐动画类型
简单过渡效果视图动画 / 属性动画
复杂交互动画属性动画
连续帧动画帧动画 / Lottie
列表 / 网格元素动画布局动画 / RecyclerView 动画
图标 / 状态切换矢量动画
场景 / 页面切换过渡动画

总结

Android常见动画,属性动画,补间动画(视图动画)帧动画(视图动画),布局动画,帧动画.按需索取,码字不容易 ,点个赞再走吧