【好玩的AOSP】没有UI设计师如何自制Android开机动画

近期学习进展

最近RedfinDemo应用开发基本停滞,一是工作繁忙,二是因为想要结合framework联动完成需求,不会C++是不行滴。所以在主攻C++的学习,又有大佬推荐《21天学通C++》,看了下果然简洁高效,编排合理。

在学习C++过程中还发现Kotlin的一些特性和C++很相似啊,比如自动类型推断,函数的语法糖,默认函数参数等等。Kotlin算是站在巨人的肩膀上,其也是一门优秀的语言,在Android领域被谷歌选为First的语言页不足为奇了。

玩点好玩的

学习C++之余,想把原生AOSP的开机动画给更新替换下,换换口味。

我们都知道,AOSP的默认开机动画是一个"ANDROID"的字样,配合一个渐变的底色动画。定制一个自己的开机动画,对于手机厂商来说,有利于宣传品牌,彰显企业文化。

像国内广为人知的定制系统,比如MIUI,ColorOS,FlymeOS等,都是没有直接使用默认动画的,定制了一套他们自己厂商的开机动画。而考虑到大厂都是人力充足,设计师,动效师,应有尽有。

(以下两张图片来自网络,如有侵权联系删除)

那像我这自己在下面玩玩源码的,没有设计师帮忙,该怎么搞一套看得过去的定制化的开机动画呢?

开始制作

从压缩包制作倒推流程

首先了解到,我们如果想要做开机动画的替换,需要准备一个bootanimation.zip的压缩包。

压缩包里面的文件格式一般比较固定:一个disc.txt,用来描述帧动画的播放策略和显示大小。若干个文件夹,里面是按照顺序命名的帧动画文件。像我的就是下面这个结构:

disc.txt里的文件内容格式也比较简单:

css 复制代码
364 830 15
p 1 0 part0

第一排364 830 15 ,依次表示:动画显示区域height高度364,width宽度830,帧数15

第二排p 1 0 part0 ,这个首个字母有三个可选:

kotlin 复制代码
p -- this part will play unless interrupted by the end of the boot
c -- this part will play to completion, no matter what
f -- same as p but in addition the specified number of frames is being faded out while continue playing. Only the first interrupted f part is faded out, other subsequent f parts are skipped

像p就表示直接全程播放,直到开机完成。第二位的1表示播放一次,如果是0就是循环播放。

第三位的0表示两帧图片之间间隔0ms,最后的part0表示这些帧动画在这个文件夹中。

文件写法明确了。难点在于如何搞到这些帧动画呢?

帧动画的制作

直接先展示制作路线:

Android应用里手动写一个简单的渐亮动画------>录屏------>MP4转PNG

我准备在Android应用里手写一个动画,在想办法转成png。

设计上力求简洁,用"Stephen OS"作为文案,也是做一个渐亮的表现形式。

方案定下来了,接下来随便新建一个demo项目。我找到一个免费字体Cooper Black,到应用xml里添加TextView控件,设置字体fontFamily:

ini 复制代码
 <TextView
        android:id="@+id/tv_animationtext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/cooper_black"
        android:rotation="90"
        android:alpha="0"
        android:text="Stephen OS"
        android:textColor="@color/white"
        android:textSize="88sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

因为我是Pixel 5 上刷的AOSP车机系统,所以开机时的屏幕方向还是vertical方向的,而我需要让其横向展示,所以在这个控件放置时直接旋转了90度。而且初始的透明度为0.

然后在Activity里准备写逻辑,顺手在工具类里写一个顶层扩展方法,给Activity设置强制全屏:

ini 复制代码
fun AppCompatActivity.setFullScreenMode() {
    val layoutParams = window.attributes
    layoutParams.layoutInDisplayCutoutMode =
        WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
    window.attributes = layoutParams
    window.setFlags(
        WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN
    )
    val uiOptions = (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN)
    window.decorView.systemUiVisibility = uiOptions
}

动画编码为求简洁迅速,没有用传统的ValueAnimator,而是直接协程里使用repeat加delay,这种写法相当简单粗暴。

scss 复制代码
val logoText = rootView.findViewById<TextView>(R.id.tv_animationtext)
MainScope().launch {
     delay(2000L)
     repeat(255) {
          delay(7)
          infoLog(it.toString())
          logoText.alpha = (it / 255.0).toFloat()
     }
}

然后开启录屏软件,减去收尾,得到一个纯净的MP4,里面就是预计显示的开机动画了。

最后用到这样一个网站,可以将MP4转为png:Video to PNG image sequence converter

同样也是简单粗暴,免费版的功能已经够用了。

得到png后我们下载到本地,批量重命名成顺序的格式。将其放置到part0的文件夹中。准备和disc.txt一起打包。这里有一个坑,不可以直接用7zip打包成zip,最好使用winrar,压缩方式要选择存储:

集成到源码

压缩完成后,我们将bootanimation.zip放置到源码的某一个文件夹中。然后在你设备product的mk文件中,随意一个位置,加一句文件复制的指令:

ruby 复制代码
PRODUCT_COPY_FILES += \
<path-to-your-bootanimation.zip>:system/media/bootanimation.zip

在打包时,将这个zip包复制到ROM的system/media文件夹下,开机后android系统会搜索这个文件夹下有没有文件,有的话就优先播这个动画。

最后的成品

成品就像下面这样,一个大文字,从无到有渐亮的简单动画。感兴趣的独立开发者,也可以考虑考虑这种自制的方案。

相关推荐
子非衣1 小时前
MySQL修改JSON格式数据示例
android·mysql·json
openinstall全渠道统计4 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
双鱼大猫4 小时前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫4 小时前
一句话说透Android里面的查找服务
android
双鱼大猫4 小时前
一句话说透Android里面的SystemServer进程的作用
android
双鱼大猫4 小时前
一句话说透Android里面的View的绘制流程和实现原理
android
双鱼大猫5 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫6 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫6 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android
苏金标6 小时前
android 快速定位当前页面
android