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()
),则可能间接触发重绘。
scss
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> |
多个动画组合一起播放 |
示例:
ini
<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 范畴。
xml
<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 中的子元素 的动画处理,常见于如 RecyclerView
、LinearLayout
、GridLayout
等容器控件。
分类
类型 | 简介 |
---|---|
LayoutAnimation | 针对整个布局中子 View 的初始进入动画 |
LayoutTransition | 针对 ViewGroup 在运行时添加/删除子 View 时的动画(更灵活) |
RecyclerView 动画 | Item 增删/移动动画,由 ItemAnimator 控制,属于布局动画的子集 |
核心特点对比
特性 | LayoutAnimation | LayoutTransition |
---|---|---|
适用时机 | 布局初始加载 | 动态添加、删除 View 时 |
控制粒度 | 针对所有子项统一应用 | 对添加、删除、改变分别可设置动画 |
使用难度 | 简单 | 中等 |
性能 | 中等(子项越多越慢) | 中等 |
是否触发重绘 | ✅ 是(布局变化引发重绘) | ✅ 是 |
ini
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+(支持库可向下兼容部分功能) |
优点 | 文件小、无限缩放不失真、适合图标、按钮动画 |
示例:
ini
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常见动画,属性动画
,补间动画(视图动画)
和帧动画(视图动画)
,布局动画
,帧动画
.按需索取,码字不容易 ,点个赞再走吧