Android动画详解PAG
前文分析了SVGA等动画的对比,但是SVGAPlayer(由 YY 团队开发)目前已归档(Public archive) ,今天我们来看看另外一种动画 PAG (Portable Animated Graphics) , 它是目前安卓开发中,替代 SVGA 和 Lottie 的最强方案,尤其是针对直播礼物、游戏特效、UI 复杂动效等场景。
它由 腾讯 (Tencent) 内部研发并开源,目前已经成为国内大厂(腾讯系、抖音、快手、B站等)的行业标准。
以下是对 PAG 的详细技术介绍,包括核心优势、工作原理以及与 SVGA/Lottie 的对比。

PAG 是什么?
PAG 是一套完整的动画工作流解决方案。它不仅仅是一个播放器,还包含了 AE (Adobe After Effects) 导出插件、桌面预览工具 和 多端 SDK(Android, iOS, Web, macOS, Windows)。
- 核心逻辑: 它的底层是一个 C++ 编写的渲染引擎 (
libpag),不依赖安卓原生的 Canvas 绘制指令(像 Lottie 那样),而是自己处理渲染管线。 - 文件格式:
.pag文件是一种二进制格式,不像 Lottie/SVGA 是 JSON/文本格式。
为什么它是 SVGA 的最佳替代者?(核心优势)
相比于已归档的 SVGA 和通过 JSON 解析的 Lottie,PAG 解决了三个核心痛点:
- 极致的 AE 特性支持(设计师最爱)
- 痛点: 以前用 Lottie/SVGA,设计师在 AE 里用了滤镜、遮罩、或者复杂的图层样式,导出来后发现安卓手机上显示效果不对,甚至直接崩了。
- PAG 方案: PAG 支持几乎所有的 AE 特性。它甚至支持将 AE 的特效“烘焙”成位图序列与矢量混合。这意味着设计师在 AE 里看到什么样,手机上就一定是什么样。
- 性能与解码速度(开发最爱)
- 二进制文件:
.pag是二进制文件,解码速度比 JSON 快几十倍。 - 单文件交付: SVGA 有时需要外挂图片资源,Lottie 也带有 img 文件夹。PAG 将所有图片、音频、矢量数据打包在一个文件里,且经过极高压缩。
- GPU 加速: 深度利用 GPU 渲染,减轻 CPU 压力。
- 运行时编辑(直播/业务刚需)
这是 PAG 最强大的功能,也是 SVGA 很难做到的:
- 替换文本: 比如一个“火箭”礼物动画,你可以在代码里动态把火箭上的文字改成“感谢榜一大哥”。
- 替换图片: 可以在动画播放过程中,把动画里的某个占位图替换成用户的实时头像。
PAG vs Lottie vs SVGA 深度对比
| 维度 | PAG (腾讯) | Lottie (Airbnb) | SVGA (YY - 已归档) |
|---|---|---|---|
| 核心原理 | C++ 引擎 + 二进制文件 | 原生 Canvas/Skia + JSON | 原生 Canvas + Protobuf/Zlib |
| 文件体积 | ⭐⭐⭐⭐⭐ (极小) | ⭐⭐⭐ (中等) | ⭐⭐⭐ (中等,含位图较大) |
| 性能消耗 | ⭐⭐⭐⭐⭐ (极低) | ⭐⭐⭐ (矢量复杂时高) | ⭐⭐⭐ (一般,易内存泄漏) |
| AE 支持度 | 完美 (支持滤镜/特效) | 一般 (受限于原生 API) | 较差 (很多特效不支持) |
| 动态替换 | 强大 (换字、换图、改色) | 支持 (但代码复杂) | 支持 (功能较弱) |
| 稳定性 | 高 (大厂生产环境验证) | 高 | 低 (无人维护) |
| 接入成本 | 中 (需引入 C++ so库) | 低 (纯 Java/Kotlin) | 低 |
Android 接入指南 (Kotlin)
-
添加依赖
PAG 依赖 Native 库,会增加一点 APK 体积(约 3-4MB,视架构而定)。// app/build.gradle dependencies { implementation 'com.tencent.tav:libpag:4.5.2' // 建议去官网查最新版本 } // 建议配置 ABI 过滤,避免引入全架构 SO 包导致体积过大 android { defaultConfig { ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' } } } -
布局文件
<org.libpag.PAGView android:id="@+id/pagView" android:layout_width="match_parent" android:layout_height="match_parent" /> -
播放动画
val pagView = findViewById<PAGView>(R.id.pagView) // 1. 从 Assets 加载 val pagFile = PAGFile.Load(assets, "gift_rocket.pag") // 2. 设置源并播放 pagView.composition = pagFile pagView.setRepeatCount(0) // 0 不循环, -1 无限循环 pagView.play() -
高级功能 - 替换内容 (Runtime Editing)
假设设计师在 AE 里给一个文本图层起名叫username,给一个图片图层起名叫avatar。
// 加载文件
val pagFile = PAGFile.Load(assets, "gift.pag")
// --- 1. 替换文本 ---
// 找到所有叫 "username" 的文本图层并修改内容
val textDataList = pagFile.getTextData(0) // 获取所有文本数据
for (i in 0 until pagFile.numTexts()) {
val textData = pagFile.getTextData(i)
if (textData.layerName == "username") {
textData.text = "张三"
pagFile.replaceText(i, textData)
}
}
// --- 2. 替换图片 (用户头像) ---
// 将图层 "avatar" 替换为一个 Bitmap
val myBitmap = BitmapFactory.decodeResource(resources, R.drawable.my_avatar)
val pagImage = PAGImage.FromBitmap(myBitmap)
pagFile.replaceImage(0, pagImage) // index 需根据图层索引查找,通常配合图层名查找
// 应用修改并播放
pagView.composition = pagFile
pagView.play()
潜在缺点与注意事项
虽然 PAG 很好,但也有两个你需要考虑的“代价”:
- APK 体积增加:
因为 PAG 底层是 C++ (libpag.so),不像 SVGAPlayer 是纯 Java。引入它会让你的 APK 增加 3MB - 5MB 左右的大小。如果你的 App 对包体大小极其敏感,需要权衡。 - 设计师的学习成本:
设计师必须安装 PAG 的 AE 插件(虽然安装很简单),并且在导出时需要预览检查。如果设计师习惯了 Lottie 的 Bodymovin 插件,需要让他们适应新流程。
总结
如果你的安卓 App 需要替换 SVGAPlayer,且涉及直播礼物、复杂 UI 动效,PAG 是目前唯一的、最完美的“版本答案”。
- 官网地址:
pag.io(文档非常详细,有中文) - GitHub: Tencent/libpag
本文链接:Android动画详解PAG - https://h89.cn/archives/493.html
版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。
评论已关闭