注册

Android 动效方案探索

前言

我们知道在 Android 中实现动画效果,可以通过补间动画、帧动画和属性动画。对于一些简单的动画效果,用上述方式实现没啥问题。但是对于复杂的动画,无论从动态效果展示和动画资源大小,还是支持动态更新,上述三种方式都无法完全满足这种需求。这时候就需要重新考虑实现方式了,下面介绍两种市面上比较常见的动效播放 SDK,主要从如何接入和 UI 动效两方面进行介绍。

开始

PAG

PAG(Portable Animated Graphics)是腾讯出品的一套完整动效解决方案,目标是降低或消除动效相关的研发成本,能够一键将设计师在 AE(Adobe After Effects)中制作的动效内容导出成素材文件,并快速上线应用于几乎所有的主流平台。

其中提供社区版和企业版版本供大家选择,其中企业版又提供大杯、中杯、小杯三种选择。社区版只提供基础能力,支持 2D 效果的动效展示。社区版同时支持视频和音频播放、3D 动效的展示,并且支持在线动效资源动态替换。

PAG 优势

高效的动效文件

  • PAG 动效文件采用了二进制的数据结构来存储AE动效信息,这使得它能够非常方便地单文件集成任何资源,如位图、音频、视频资源等,实现单文件交付。
  • 二进制数据结构不需要像 JSON 一样处理字符串匹配问题,解码速度可以快 90% 以上。
  • 在压缩率方面,相比 JSON,二进制数据结构可以跳过 Key 的内容,只存储 Value,这样能节省大量空间。
  • 经过一系列的压缩策略,导出相同的AE动效内容,PAG 在文件解码速度和压缩率上均大幅领先于同类型方案。
广泛的平台支持

  • PAG 支持 Android、iOS、Web、macOS、Windows、Linux 和微信小程序等平台,为开发者提供了跨平台的一致性体验。
高性能的渲染

  • PAG 的渲染主体通过跨平台的 C++ 来实现,所有平台均一致开启 GPU 硬件加速,确保各平台测的渲染一致性。
  • 高效的动效文件和优化的渲染引擎使得 PAG 在性能上表现出色,能够轻松应对复杂场景下的动效渲染需求。
丰富的应用场景

  • PAG 可以应用于照片模板、视频模板、智能剪辑等多种场景,满足设计师和开发者在不同业务场景下的需求。

PAG 集成

aar 集成

  1. 将 libpag 的 aar 文件放置在 android 工程项目的 libs 目录下。
  2. 添加 aar 库依赖,在 app 的 gradle 文件 app/build.gradle,添加 libpag 的库依赖。
    android {
repositories {
flatDir {
dirs 'libs'
}
}

dependencies {
//libpag 的核心库
//将 libpag_enterprise_4.2.41_android_armeabi_armv7a_arm64v8a.aar 换成你下载的 aar 文件名
implementation(name: 'libpag_enterprise_4.2.41_android_armeabi_armv7a_arm64v8a.aar', ext: 'aar')
implementation("androidx.exifinterface:exifinterface:1.3.3")
}

注意:  需要在混淆列表里面,添加 libpag 的 keep 规则:

    -keep class org.libpag.** {*;}
-keep class androidx.exifinterface.** {*;}

配置完以后,sync 一下,再编译。

Maven 集成

这里介绍一下,PAG 一共提供六个版本(以4.2.41版本为例):

企业基础版本:com.tencent.tav:libpag-enterprise:4.2.41,不包含 Movie 模块,不支持多字节 emoji,包含素材加密和 3D 图层能力。

企业 movie 版本:com.tencent.tav:libpag-enterprise:4.2.41-movie,包含音频播放、素材加密、占位图一键替换视频、导出视频文件和 3D 图层以及多字节 emoji 的能力。

企业 noffavc 版本:com.tencent.tav:libpag-enterprise:4.2.41-noffavc,不包含 Movie 模块和多字节 emoji 能力、内部不包含软件解码器,支持解码器外部注入。

社区基础版本 com.tencent.tav:libpag:4.2.41 不支持多字节 emoji,包含 PAG 的基础能力。

社区 harfbuzz 版本 com.tencent.tav:libpag:4.2.41-harfbuzz 支持多字节 emoji 的能力。

社区 noffavc 版本 com.tencent.tav:libpag:4.2.41-noffavc 不支持多字节 emoji,内部不包含软件解码器,支持解码器外部注入。

  1. 在 root 工程目录下面修改 build.gradle 文件,增加mavenCentral()
buildscript {

repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}

  1. 在 app 的 gradle 文件 app/build.gradle,添加 libpag 的库依赖
    dependencies {
//基础版本,如需保持最新版本,可以使用 latest.release 指代
implementation 'com.tencent.tav:libpag:latest.release'
}

注意:  需要在混淆列表里面,添加 libpag 的 keep 规则:

    -keep class org.libpag.** {*;}
-keep class androidx.exifinterface.** {*;}

配置完以后,sync 一下,再编译。

示例

代码实现

在 XML 中引入 PAGImageView,然后在代码中设置动画资源并开启播放。

libpag.PAGImageView
android:id="@+id/pagImageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
class PAGAnimActivity:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pag_anim)
val pagIv = findViewById<PAGImageView>(R.id.pagImageView)
//设置资源路径
pagIv.setPath("assets://data_video.pag")
//设置重复播放次数
pagIv.setRepeatCount(Int.MAX_VALUE)
//开启播放
pagIv.play()
}
}
UI 动效

output3.gif

Lottie

Lottie 是 Airbnb 开源的一套跨平台的完整动画效果解决方案,是一种基于 JSON 的动画文件格式,可以在任意平台进行动画播放。在不同的设备上,可以放大或缩小而不会出现像素化。在多个平台上无缝运行,大大节省了开发资源。

Lottie 优势

文件小

与 GIF 或 MP4 等其他格式相比,Lottie 动画更小,但质量保持不变。

无限可扩展

Lottie 动画基于矢量,这意味着您可以放大或缩小它们而不必担心分辨率。

多平台支持和库

对于所有开发人员来说,Lottie 的交付非常简单。您可以在 iOS、Android、Web 和 React Native 上使用 Lottie 动画,无需修改。

交互性

在 Lottie 动画中,动画元素是公开的,因此您可以操纵它们进行交互并响应滚动、点击和悬停等交互。在交互指南中了解更多信息。

Lottie 集成

配置 Gradle

dependencies {
implementation "com.airbnb.android:lottie:$lottieVersion"
}

目前最新的版本是 6.6.2,如需获取最新版本请戳这里

示例

下面用两种实现方式演示 Lottie 播放动画的效果。

Kotlin 实现

首先用代码的方式实现,主要方法也进行了注释。

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val lottieView = findViewById<LottieAnimationView>(R.id.lottieView)
//设置动画资源,资源放在assets目录下,注意这里只设置资源名称即可
lottieView.setAnimation("anim2.json")
//设置动画重复播放次数
lottieView.repeatCount = Int.MAX_VALUE
//播放动画
lottieView.playAnimation()
}

}
XML 实现

首先我们在 XML 布局中引入 LottieAnimationView,通过 lottie_fileName 设置资源文件,并设置无限轮询播放和自动开启播放。

airbnb.lottie.LottieAnimationView
android:id="@+id/lottieView"
android:layout_width="0dp"
android:layout_height="0dp"
app:lottie_fileName="anim2.json"
app:lottie_loop="true"
app:lottie_autoPlay="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
UI 动效

播放的效果如下图所示,动画播放流畅度还是比较丝滑的。

output.gif

Lottie 详细介绍

动画资源

Lottie 支持以下来源的动画,能满足产品需求。

  • src/main/res/raw目录下,json 格式的动画资源文件。
  • src/main/assets目录中,json/zip/[dotLottie] 格式的动画资源文件。
  • 来源于 url/InputStream 的 json 或 zip 动画资源文件 。
  • JSON 字符串,来源方式不限。
动画缓存

Lottie 同样也支持动画缓存,通过 LruCache 来实现,支持最大缓存数是20。可以通过 setCacheComposition(boolean cacheComposition) 方法来决定是否开启预缓存。

全局配置

Lottie 支持全局配置,如有以下需求可以进行单独配置,放在Application进行初始化:

  • 从网络加载动画时,使用自定义网络请求框架。
  • 从网络获取的动画使用自定义缓存目录,摒弃原有的 Lottie 的默认目录 ( cacheDir/lottie_network_cache)。
  • 启用 Systrace 标记以进行调试。
  • 自定义网络框架缓存策略,需要关闭 Lottie 的网络缓存。
Lottie.initialize(
LottieConfig.Builder()
.setNetworkFetcher(...)
.setEnableSystraceMarkers(true)
.setNetworkCacheDir(...)
.setEnableNetworkCache(false)
)
动画监听器

Lottie 支持多种动画播放状态的监听,记得注册和解注册成对出现。

lottieView.addAnimatorListener()
lottieView.addAnimatorPauseListener()
lottieView.addAnimatorUpdateListener()
自定义动画效果

通过 Lottie 实现动画基本上满足我们大部分场景需求,当然要是有特殊要求,Lottie 也支持自定义动画效果,下面示例是对动画透明度进行单独设置。

val animator = ValueAnimator.ofFloat(0f, 1f)
animator.addUpdateListener {
lottieView.alpha = animator.animatedValue as Float
}
animator.duration = 3000
animator.start()
Lottie 对 APK 大小有什么影响

非常小:

  • 约 1600 种方法。
  • 未压缩时为 287kb。
Lottie 的优点

  • 支持更多 After Effects 功能。请参阅支持的功能以获取完整列表。
  • 手动设置进度以将动画连接到手势、事件等。
  • 支持网络下载动画资源。
  • 可以动态改变播放速度。
  • 图像支持抗锯齿。
  • 动态改变动画特定部分的颜色
Lottie 的缺点

Lottie 是为矢量形状而设计的,虽然 Lottie 支持渲染图像,但使用它们也有一些缺点:

  • 相同的动画效果,Lottie 使用的文件大小要比等效的矢量动画要大一个数量级。
  • 当 Lottie 缩放时,动画会变得像素化。
  • 用 Lottie 增加了动画的复杂性,动画资源不仅仅是一个文件,而是 json 文件加上所有图像。

DotLottie

DotLottie是一个新的 Lottie 播放器,依靠 ThorVG 进行渲染,其通过新的 dotLottie Runtimes 实现跨平台支持,拥有更快的加载速度,同时还能保证不同平台的动画一致性和高性能的表现。

DotLottie 优势

  • 动画文件小:高达 80% 动画压缩,且在放大或缩小而不会出现像素化。
  • 自适应主题:支持昼夜主题模式,或者自定义模式
  • 支持动画资源包:资源包中的 dotLottie 文件中包含多个动画,简化动画的管理和部署。
  • 高性能:dotLottie 图形处理由高性能图形引擎 ThorVG 提供支持,支持比普通 JSON 小 80% 的 dotLottie 格式。

DotLottie 集成

配置 Gradle

repositories {
maven(url = "https://jitpack.io")
}
dependencies {
implementation("com.github.LottieFiles:dotlottie-android:0.5.0")
}

示例

下面用两种实现方式演示 DotLottie 播放动画的效果。

Kotlin 实现

首先在 XML 布局中引入 DotLottieAnimation,然后在代码里面配置相应的 Config,这里 Config 是必须要配置的,否则无法正常播放动画。

lottiefiles.dotlottie.core.widget.DotLottieAnimation
android:id="@+id/dotLottieView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
class DotLottieAnimActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dot_lottie_anim)
val dotLottieView = findViewById<DotLottieAnimation>(R.id.dotLottieView)
val dotConfig = Config.Builder()
.autoplay(true)
.speed(1f)
.loop(true)
// 本地资源,支持.json或.lottie两种格式
// .source(DotLottieSource.Asset("anim.lottie"))
//在线资源
.source(DotLottieSource.Url("https://lottie.host/5525262b-4e57-4f0a-8103-cfdaa7c8969e/VCYIkooYX8.json"))
.playMode(Mode.FORWARD)
.useFrameInterpolation(true)
.build()
dotLottieView.load(dotConfig)
dotLottieView.play()
}
}
UI 动效

output1.gif

Compose 实现

用 Compose 实现相对来说简单许多,只需设置对应的资源文件和播放参数。

@Composable
fun AnimDotLottieView() {
DotLottieAnimation(
source = DotLottieSource.Asset("bicycle.lottie"),
autoplay = true,
loop = true,
speed = 1f,
useFrameInterpolation = true,
playMode = com.dotlottie.dlplayer.Mode.FORWARD
)
}
UI 动效

output2.gif

总结

  • Lottie/DotLottie:适用于需要在多种平台上实现一致动画效果的应用场景,采用 JSON 或 Lottie 文件格式。在Android上通过Canvas绘制,并且支持动态更新动画内容。由于其轻量级和高效渲染的特点,即使在低端设备上也能保持流畅的动画效果。
  • PAG:广泛应用于腾讯等公司的产品中,涵盖 UI 动画、贴纸动画、照片/视频模板等场景。采用 PAG 二进制文件格式,采用动态比特位压缩技术,所以文件体积小。渲染方式各端共享一套 C++ 实现,平台端只做接口封装,并且支持动态更新动画内容

作者:码上搬砖
来源:juejin.cn/post/7452547398670319653

0 个评论

要回复文章请先登录注册