早期的Android上App的启动速度常为人诟病,如今的启动表现已不逊iOS。Google针对系统的不断优化绝对功不可没,从8.0独立出来的SplashWindow
,到12上推出的全新SplashScreen
。
在App的主要内容展示之前,按照需求的不同,或多或少会先展示这样几个画面。
画面 | 用途 |
Splash Screen | 展示品牌Logo或Slogan |
Advertisement Screen | 展示节日活动或日常广告 |
Guide Screen | 演示重点功能,一般只展示一次 |
1 前言
我们常常花费精力去打造引导画面或广告画面,而作为第一印象的启动画面却容易被忽视。回想下以前都是怎么处理这个画面的:
一般通过设置windowSplashscreenContent属性来展示UI提供的启动图,系统将为它创建专门的Window
假使忘记设置这个属性的话,默认的白色背景将导致启动过程中会有个白画面一闪而过
要去掉这个突兀的白画面可不能简单地设置Background为null,不然一闪而过的又会变成黑画面
最终发现windowDisablePreview属性可以彻底关闭这个画面,这样一来确实没有任何突兀的画面一闪而过了
但这又会带来启动"变慢"的副作用,因为用来过渡的启动画面被关闭之后,App描画前屏幕几乎没有什么变化。即便App性能没有劣化,但为了留住用户,我们还是得好好对待这个启动画面。
然而现有的windowSplashscreenContent可供定制的空间着实有限。也许官方也注意到了这点,便精心设计了Splash Screen API,并在Android 12里重磅推出。
有了这个全新特性的帮助,启动画面的定制将更加自由、方便。先来看下采用SplashScreen API 快速定制的启动效果。
下面将逐步演示全新SplashScreen可供定制的各个方面。
2 定制进入效果
采用xml即可快速定制各式进入效果。
2.1 默认的启动效果
默认情况下启动画面将展示白色背景和Launcher上的Adaptive Icon
,也是不错的,比以前的白画面要好很多。
2.2 自定义静态Icon
替换Icon为Adaptive Icon的前景图,背景色微调为米黄色。
<item name="android:windowSplashScreenBackground">@color/newSplashScreenColor</item> <item name="android:windowSplashScreenAnimatableIcon">@drawable/ic_kotlin_hero_new</item>
2.3 自定义Icon背景
Icon色调和画面背景色的对比不够明显的情况下,可以添加Icon背景色加强辨识度。
<item name=”android:windowSplashScreenIconBackground”>@color/newSplashIconMaskColor</item>
2.4 自定义品牌Logo
添加品牌Logo可以展示企业形象或Slogan,使得启动画面更为完整和精细。
<item name=”android:windowSplashScreenBrandingImage”>@drawable/ic_tm_brand_newer</item>
2.5 自定义动画Icon
动画形式的Icon可以增添设计和创意,使得启动流程更加流畅和有趣。
<item name="android:windowSplashScreenAnimatableIcon">@drawable/ic_kotlin_hero_new_animated_rotate</item> <item name="android:windowSplashScreenAnimationDuration">@integer/icon_animator_duration</item>
比如让机器人图标旋转起来。
再比如让机器人在Kotlin上侧滑。
或者让几何图案拼凑出字母K之后和机器人汇合,象征着Android
和Kotlin
的强强联合。
注意:
- 动画Icon的时长上限为
1000ms
。 - 图标的进入动画可以定制,但由系统控制,不可以被监听和额外处理。
2.6 延长启动画面
The splash screen is dismissed as soon as your app draws its first frame. If you need to load a small amount of data such as in-app theme settings from a local disk asynchronously, you can use ViewTreeObserver.OnPreDrawListener to suspend the app to draw its first frame.
后台数据的加载难免耗时,启动画面结束了主要内容仍未加载好的话,体验不是太好。能够控制启动画面的持续时时长就好了。
现有的ViewTreeObserver的OnPreDrawListener回调是可以挂起描画的,如果我们在数据准备好之后再放行描画,就可以间接地延长启动画面的显示。
比如Activity初始化2s后才放行描画。
class SplashActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... keepSplashScreenLonger() } private fun keepSplashScreenLonger() { // 监听Content View的描画时机 val content: View = findViewById(android.R.id.content) content.viewTreeObserver.addOnPreDrawListener( object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { // 准备好了描画放行,反之挂起 return if (viewModel.isDataReady()) { content.viewTreeObserver.removeOnPreDrawListener(this) true } else { false } } } ) } } class MyViewModel(application: Application): AndroidViewModel(application) { companion object { const val WORK_DURATION = 2000L } private val initTime = SystemClock.uptimeMillis() fun isDataReady() = SystemClock.uptimeMillis() - initTime > WORK_DURATION }
看一下效果,发现启动画面的展示时间确实变长了。