
可能有不少小伙伴已經留意到
Android 12上推出了全新的啟影片面 APISplashScreen,同時為了兼容低版本的使用,Jetpack框架里推出了同名庫,
本次針對這個庫的使用和原理做個全面的介紹,將按照如下幾個方面去展開:
- 首先簡單探討一下為什么需要啟影片面
- 接著一起回顧一下之前打造啟影片面的常規做法
- 然后重點闡述一下 SplashScreen 庫的目的,以及如何使用
- 最后介紹一下 SplashScreen 庫大致的實作原理
1. 為什么需要啟影片面
1.1 啟影片面的作用
-
當我們打開各種桌面軟體或移動端 App 的時候,首先會看到的經常是一段過渡畫面,用以展示產品所屬的公司、品牌的圖示、公司的 Slogan 等,借以宣傳公司的調性和傳達一些特色
-
同時在節日慶典、特殊活動的時候展示廣告頁面或活動海報
-
在啟影片面展示的同時,背后的內容得以加載
同時在一定程度上緩解用戶的等待,啟影片面良好設計的話,還能使得這個枯燥的程序顯得有趣和充滿期待!
1.2 App 啟動的典型流程
來看一下 App 啟動的典型流程,

點擊 Launcher 上的 Logo 之后,首先用戶將看到一個啟影片面,如果是初次啟動的話接著會展示 Guide 畫面引導用戶了解如何使用;如果是節榷訓廣告需要的話展示的是廣告宣傳畫面,最后才是展示內容的主畫面,
我們本次探討的核心就是第一個啟影片面,
Jetpack SplashScreen 庫正是用來打造用戶看到的第一個啟影片面,在講述之前,先來回顧一下之前的常規做法,
2. 常規做法
我們知道從點擊 Launcher 上的 icon 到 App 內容描畫之前,有很多準備作業,在這段時間是看不到目標 App 內容的,
為了快速回應用戶的點擊或緩解用戶的等待,在 App 描畫之前系統將啟動專用的 SplashScreenWindow 蓋在 App 之上,該Window 的呈現源自于 App 主題方面的配置,
配置的不同進而影響到啟動 Window 的表現,我們來看看各種配置的做法,
2.1 默認的啟影片面背景
假使 App 的主題針對 Window 背景什么都不設定,你會發現啟動的程序中總有個默認的白畫面一閃而過,
<style name="SplashThemeBase.DefaultBg"/>
2.2 不設定啟影片面背景
當然可以將 windowBackground 設定為空,可是你會發現啟動的程序中又變成黑色一片閃過,
<style name="SplashThemeBase.NoBg">
<item name="android:windowBackground">@null</item>
</style>
無論是白畫面還是黑畫面一閃而過,都無法接受,所以還得繼續優化,
2.3 直接關閉啟影片面
無論白畫面還是黑畫面一閃而過的體驗都不好,這時候可能會想到關閉默認的啟影片面,通過 windowDisablePreview 屬性可以徹底關閉啟影片面,
<style name="SplashThemeBase.TransparentBg">
<item name="android:windowDisablePreview">true</item>
</style>
這樣一來,確實看不到啟影片面的存在了,但整個程序貌似“變慢”了,實際上性能并沒有**“劣化”**,只是啟動中過渡的 Window 不存在了,假使 Application 或 Activity 等組件里存在耗時邏輯的話,這種劣化會更加明顯,
相較于前面的黑白畫面一閃而過,這種變慢的體驗也好不到哪去,
2.4 設定啟影片面背景
繞來繞去,最后我們發現還是得提供一個恰當的啟影片面,具體在于將 UI 提供的背景色、Icon、Brand 等資源組合成一個 LayerListDrawable,然后將其設定到 windowBackground 中即可,
<!--theme-->
<style name="SplashThemeBase.WithBg">
<item name="android:windowBackground">@drawable/ic_splash_bg</item>
</style>
<!--drawable-->
<layer-list ... >
<item android:drawable="@drawable/ic_logo"></item>
<item android:drawable="@drawable/ic_brand"></item>
</layer-list>
這種做法既可以提供體驗良好的過渡畫面,同時可以快速回應用戶的點擊,可以說是最為簡單也最為便捷的一種實作方式,
2.5 設定啟影片面內容
Android 8 加入一個配置啟影片面的屬性 windowSplashscreenContent,用于配置啟影片面的內容,它的優先級高于 windowBackground,兩者一起設定的話呢,會覆寫在 windowBackground 上,大體的效果呢和前面的差不多,不再贅述,
<style name="SplashThemeBase.WithBg.SplashScreenContent">
<item name="android:windowSplashscreenContent">@drawable/ic_splash_content</item>
</style>
注意:這個屬性自 Android 8 加入,從 12 開始廢棄
2.6 定義啟動專用 Activity
有的時候覺得單單設定一張背景圖太過簡單,無法實作一些復雜的啟動效果,又或者希望能和廣告或節日的畫面深度配合起來,這時候難免需要定義一個專門的啟動 Activity,
具體來講需要在入口 Activity 前預設專門的 Splash Activity來顯示啟影片面,Splash Activity 在一定時間后自動跳轉到入口 Activity
啟動 Activity 提供類似啟影片面的布局,
<androidx.constraintlayout.widget.ConstraintLayout ... >
<ImageView android:src="@drawable/ic_icon" ... />
<ImageView android:src="@drawable/ic_brand" ... />
</androidx.constraintlayout.widget.ConstraintLayout>
在畫面展示后配合定時跳轉等邏輯去打開廣告或海報等畫面,
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
setContentView(binding.root)
goToMainScreenDelayed()
}
}
因為有了自己實作的啟動 Activity,所以系統提供的啟影片面可以關閉,當然也可以將系統的啟影片面的 windowBackground 設定為整體背景色相接近的色調,
<style name="SplashThemeBase.NoSplashWindow" >
<item name="android:windowDisablePreview">true</item>
</style>
上面是通過 Activity 方式打造的啟影片面的效果,
DEMO 的效果和前面的主題方式的效果差不多,但是這種做法將會擁有更大的定制空間,比如可以接入跨平臺的 Lottie 影片庫,打造更為豐富、炫酷、平臺統一的啟動效果!
3. Jetpack SplashScreen 的目的和使用
可以看到之前提供的主題配置方式只能展示一張背景圖,這種靜態效果看久了著實單調,而且這張圖還需要我們自行組合 App 的 Icon、Brand 的 Logo,這就需要考慮很多 Size、位置、螢屏適配等 UI 細節,不太方便,如果需要豐富、靈活一些的效果,又需要自定義專用的 Activity 來解決,這樣一來又顯得繁瑣,
正因為此,Jetpack 上推出了 SplashScreen 庫,來高效、靈活地重塑啟影片面,而 SplashScreen 庫基于 Android 12 的新特性 SplashScreen API,所以我們先來了解一下這個特性,
3.1 Android 12 SplashScreen
3.1.1 特性介紹
Android 12 上 App 啟動的時候將先展示一個啟影片面的進場部分,該部分的呈現由 SplashScreen API 提供的更為豐富的屬性來定制,之后在App 描畫第一幀的時候將該畫面的視圖回呼給我們來定制退場部分的效果,
進場和退場兩部分共同組成了全新的 SplashScreen API,

需要說明的是,不同于之前的版本,12 上什么即便都不配置,啟影片面會是白色背景下展示 Adaptive Icon 的一個效果,這相較于之前的純白背景要好了不少,
3.1.2 畫面構成

SplashScreen 的畫面由一個 SplashScreenWindow 承載,中間是一個 AdaptiveIcon,SplashScreen API 則提供了豐富的屬性來指定該的各部分構成,簡潔明了,比如:
windowSplashScreenAnimatedIcon:指定 App Icon 的圖片,如果指定的是Animated Vector Drawable的話,在啟影片面展示的同時會執行一個 Icon 影片效果windowSplashScreenIconBackgroundColor:Icon 背景色- Adaptive Icon Mask:由 Launcher 的配置指定,主題無法更改,說明一下
windowSplashScreenBackground:Window 背景色,和之前的 windowBackground 屬性類似windowSplashScreenBrandingImage:放置品牌 Logo
當 SplashScreenWindow 退場的時候整個畫面的視圖會被封裝到 SplashScreenView 中供我們實作退場效果,
下面這是 Gmail 適配了 SplashScreen API 后的啟動效果,簡單來講就是一個進場的 M 字母的 Path影片,退場的時候直接結束到目標內容的效果,
并沒有適配 Icon 背景、Brand Logo、退場影片等特性,后面的章節將充分演示各項特性,
3.1.3 啟動規則
在冷啟動和暖啟動的時候展示 SplashScreen,熱啟動的時候從不展示該畫面,
- 冷啟動:行程尚不存在的情況下點擊 App Icon 的啟動
- 暖啟動:行程存在但 App 不在前臺,并且 Activity 已經銷毀了的啟動
- 熱啟動:行程存在但 App 不在前臺,并且 Activity 尚未銷毀的啟動
3.2 Jetpack SplashScreen
3.2.1 目的

Android 12 的 SplashScreen API 非常好用,但是低版本無法嘗鮮,所以 Jetpack 里推出了同名庫,
它是為了兼容 12 之前低版本的 UI 庫,最早兼容到 Android 6(API 23),6.0 及以上的設備占用率近 9 成,完全夠用了,它通過整合和統一 SplashScreen API,達到一套代碼實作近乎一致的 App 啟動體驗,
簡述:
- 兼容低版本系統的啟影片面 UI 庫
- 支持到 Android 6.0(近 9 成)
- 整合 12 的 SplashScreen API
- 一套代碼打造近乎一致的啟動效果
3.2.2 提供的主題和屬性
SplashScreen 庫的版本到了 1.0.0-alpha01 版,在 gradle 檔案里簡單匯入即可,
dependencies {
implementation "androidx.core:core-splashscreen:1.0.0-alpha01"
}
它預設了主題供我們使用,必須將入口 Activity 的主題改成擴展自這個主題,
<style name="Theme.SplashScreen" parent="Theme.SplashScreenBase">
<item name="windowSplashScreenAnimatedIcon">@android:drawable/sym_def_app_icon</item>
...
</style>
同時預設了些屬性供我們覆寫和提供自己的啟影片面資源,
<attr format="reference" name="postSplashScreenTheme"/>
<attr format="reference" name="windowSplashScreenAnimatedIcon"/>
<attr format="integer" name="windowSplashScreenAnimationDuration"/>
<attr format="color" name="windowSplashScreenBackground"/>
這里需要提醒兩點:
- SplashScreen 庫針對 12 之前的低版本暫不支持設定 Icon Bg,和 Brand Icon 的屬性
postSplashScreenTheme屬性用來指定 Activity 最終的主題,避免使用預設的主題影響目標 Actvitiy 的主題展示
3.2.3 提供的 API
SplashScreen 庫還提供了邏輯方面的 API,供我們去實作啟影片面時長的控制,啟影片面退場效果的實作需求,
| API | 說明 |
|---|---|
| SplashScreen | Jetpack版獲取定制啟影片面入口的類 |
| Activity#installSplashScreen() | 覆寫Activity,用以獲取定制入口的靜態成員函式 |
| setKeepVisibleCondition | 指定保持啟影片面展示的條件 |
| KeepOnScreenCondition | 實作展示條件的介面 |
| setOnExitAnimationListener | 監聽啟影片面的退出時機 |
| OnExitAnimationListener | 啟影片面退出的回呼介面 |
| SplashScreenViewProvider | 定制退場效果的啟影片面視圖 |
3.3 SplashScreen 庫的使用
3.3.1 打造進場效果
進場效果的部分只涉及到資源方面的配置,
首先擴展自 SplashScreen 庫的預設主題作成一個 Base 主題,指定諸如啟影片面背景、目標 Activity 背景等方面的共同屬性,
<style name="SplashScreenTheme.Base" parent="Theme.SplashScreen">
...
<item name="windowSplashScreenBackground">@color/splashBackground</item>
<item name="postSplashScreenTheme">@style/TargetScreenTheme</item>
</style>
其他的一些屬性需要針對低版本和 12 作區分,比如 12上可以指定其獨有的影片 Icon,Icon 背景和 Brand logo,而低版本上指定一個靜態 Icon 即可,但為了效果接近,可以指定 App 的 Adaptive Icon,
<!-- version:12- -->
<style name="SplashScreenTheme" parent="SplashScreenTheme.Base">
<item name="windowSplashScreenAnimatedIcon">@mipmap/ic_icon_adaptive</item>
</style>
<!-- version:12+ -->
<style name="SplashScreenTheme" parent="SplashScreenTheme.Base">
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_icon_animated</item>
<item name="android:windowSplashScreenIconBackgroundColor">@color/iconBackground</item>
<item name="android:windowSplashScreenBrandingImage">@drawable/ic_brand</item>
</style>
我們來看一下分別運行在 Android 8 和 12 上的進場效果:

可以看到高低版本上是比較接近的進場畫面,只不過 12 上多了特有的 Kotlin 的組合影片和一個 TechMerger 字樣的 Brand Logo,
3.3.2 延長啟影片面
隨著 App 第一幀的開始描畫,SplashScreenWindow 即將消失,如果背面的業務邏輯尚未準備完畢,那體驗不是很好,魚骨屏什么的就是用來優化這個問題,
當然對于啟影片面來講,現在可以通過 SplashScreen 庫的 API 來靈活控制啟影片面的時長,確保內容好了再退出,這個 API 就是 installSplashScreen(),
通過這個靜態函式可以拿到定制的入口,之后可以呼叫 setKeepVisibleCondition() 設定啟影片面保持展示的條件,條件可以 ViewModel 的耗時加載相結合,這里提供的是一個 ViewModel 實體初始化 2s 之后再退出啟影片面的一個模擬邏輯,
注意:由于 installSplashScreen 函式內部將呼叫 setTheme 反映實際的主題,所以需要在 setContentView 之前呼叫
class JetpackSplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
splashScreen = installSplashScreen()
setContentView(binding.root)
splashScreen.setKeepVisibleCondition {
!viewModel.isDataReady()
}
}
}
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
}
我們來看一下分別運行在 Android 8 和 12 上啟影片面的延長效果:

可以看到高低版本上都成功實作了啟影片面的延遲退出,
3.3.3 打造整體退場效果
當啟影片面退出的時候如果能提供一個無縫過渡到目標內容的影片,體驗會更好,我們可以利用 SplashScreen 庫的 setOnExitAnimationListener 來針對進場畫面的整體視圖實作一個退場的影片,
比如這里我們定制一個 SplashScreen 整體的下移淡出效果,
注意:記得在影片結束的時候呼叫 SplashScreenViewProvider 的 remove() 及時將啟影片面的視圖移除,否則可能覆寫在實際畫面上,遮擋內容,
class JetpackSplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
splashScreen.setOnExitAnimationListener { splashScreenViewProvider ->
showSplashExitAnimator(splashScreenViewProvider.view) {
splashScreenViewProvider.remove()
}
}
private fun showSplashExitAnimator(splashScreenView: View, onExit: () -> Unit = {}) {
...
AnimatorSet().run {
...
playTogether(slideDown, alphaOut)
doOnEnd { onExit() }
}
}
}
我們來看一下分別運行在 Android 8 和 12 上的退場效果:

可以看到 12 上的 Brand Logo 是一起執行的退場影片,總的來說高低版本上都實作了幾乎一致的整體下移和淡出的效果,
3.3.4 打造 Icon 獨有的退場效果
如果覺得整體的退場影片太過突兀或夸張,還可以針對 App Icon 作單獨的退場效果,基本邏輯和定制整體的退場效果差不多,,區別在于執行影片的物件由 view 變成了 IconView,
同樣要注意在影片結束的時候呼叫 remove(),
class JetpackSplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
splashScreen.setOnExitAnimationListener { splashScreenViewProvider ->
showSplashIconExitAnimator(splashScreenViewProvider.iconView) {
splashScreenViewProvider.remove()
}
}
private fun showSplashIconExitAnimator(iconView: View, onExit: () -> Unit = {}) {
...
AnimatorSet().run {
...
playTogether(alphaOut, scaleOut, slideUp)
doOnEnd { onExit() }
}
}
}
這里延時的是針對 Icon 的上移和淡出影片,來看一下效果:

可以看到 12 上的 Brand Logo 是不動的,整體上都是一個 Icon 上移和淡出的效果,
3.3.5 控制退場影片的時長
設備性能或狀態會影響 App 開始描畫的時間,為了讓用戶早點看到實際內容,可以靈活控制退場影片的時長,比如當描畫得晚,可以考慮不展示退場影片或執行極短的固定時長;當描畫得早,進場影片可能尚未結束,將剩余的時長交接給退場部分,

主要通過 SplashScreen 庫回傳的進場影片開始時刻(iconAnimationStartMillis)和總時長(iconAnimationDurationMillis)的 API,與退場回呼的當前時刻進行計算即可,
需要注意的是,針對 12 之前的版本,SplashScreen 庫的進場部分不支持 Icon 影片,所以上述的兩個屬性總是回傳 0,需要特別處理一下,
private fun getRemainingDuration(provider: SplashScreenViewProvider): Long {
val animationDuration = provider.iconAnimationDurationMillis
val animationStart = provider.iconAnimationStartMillis
return if (animationDuration == 0L || animationStart == 0L)
defaultExitDuration
else (animationDuration - SystemClock.uptimeMillis() + animationStart)
.coerceAtLeast(0L)
}
3.4 Lottie 支持 SplashScreen 嗎?
Lottie 是跨平臺的影片庫,非常好用,那么 SplashScreen 庫支持嗎?
并不支持,因為 SplashScreen 庫只能配置 Drawable 檔案,不可以替換 View,而 Lottie 的效果完全依賴于自定義的 AnimationView,
但 SplashScreen 的設計者提供了一個魔改思路:
- 拷貝 Lottie
Json的第一幀,做成SVG并轉換為 Animated Vetor Drawable,設定到 Splash Icon - 目標布局正中放入執行 Icon 影片的 View
- 在 Splash 退出的時候將
LottieAnimationView決議 Json 并執行影片 - 影片結束后記得將真正的視圖展示
代碼示例:
splashScreen.setOnExitAnimationListener { vp ->
val lottieView = findViewById<LottieAnimationView>(R.id.animationView)
...
lottieView.postDelayed({
vp.view.alpha = 0f
vp.iconView.alpha = 0f
lottieView!!.playAnimation()
}, delay)
lottieView.addAnimatorListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
imageView.visibility = View.VISIBLE
}
})
}
我們來看一下高低版本上魔改之后支持 Lottie 的 SplashScreen 效果,可以看到是幾乎完全一致的非常流暢、絲滑的啟動體驗,

但這種做法違背了 SplashScreen 庫的設計初衷,不建議使用,這里只是提供一種思路,
更詳細的說明可以參考官方的 DEMO 介紹:https://github.com/vcaen/splashscreen-sample
4. SplashScreen 庫的實作原理
接下來了解一下 SplashScreen 庫如何兼容低版本,實作幾乎一致的啟動效果,
4.1 總體原理
寫這個資料的時候 Android 12 的原始碼尚未公開,最近公開了之后看了一眼,發現 SplashScreen 的實作非常繁雜,
這里簡單提一下關鍵地方,SplashScreenWindow 退出的時候,系統會通過 AIDL 將封裝了啟影片面的資訊的序列化物件傳遞給 App 行程,App 將物件反序列化并創建退場視圖即 SplashScreenView,然后添加到 DecorView 上去,之后 App 即可對這個視圖作退場效果的定制,
更多全面的細節,感興趣的朋友可自行研究,本次主要Jetpack SplashScreen 庫的原始碼進行解讀,

總體的原理分為進場和退場兩個部分,
進場部分的畫面針對 12 之前的版本是 windowBackground 思路,針對 12 是系統專屬的 SplashScreen 系屬性實作的,
退場部分,在 12 之前是自定義的 FrameLayout 添加到 Activity 的 ContentView 上,12 則是反序列化的 SplashScreenView 添加到了 DecorView 上,
4.2 進場畫面的原理
進場畫面的原理完全依賴于主題的配置,面向低版本的話和之前的常規做法是一樣的思路,即提供一個讀取我們配置的畫面資源的 LayerListDrawable 放置到 windowBackground 中,
<style name="Theme.SplashScreen" parent="Theme.SplashScreenBase">
...
</style>
<style name="Theme.SplashScreenBase" parent="android:Theme.NoTitleBar">
<item name="android:windowBackground">@drawable/compat_splash_screen</item>
...
</style>
<!--compat_splash_screen.xml-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="fill">
<color android:color="?attr/windowSplashScreenBackground" />
</item>
<item
android:drawable="?attr/windowSplashScreenAnimatedIcon"
... />
</layer-list>
面向 12 的話,則是由系統回呼專屬的屬性去構建啟影片面的視圖,
<style name="Theme.SplashScreen" parent="android:Theme.DeviceDefault.NoActionBar">
<item name="android:windowSplashScreenAnimatedIcon">?windowSplashScreenAnimatedIcon</item>
<item name="android:windowSplashScreenBackground">?windowSplashScreenBackground</item>
...
</style>
4.3 定制入口的初始化
獲取 SplashScreen 實體的 API 是 installSplashScreen(),其運行在低版本上的話,需要額外讀取和快取 Icon 和 Background 的配置,然后讀取并設定目標 Activity 的 Theme,12 上的話,Window 背景,Icon 和 Branding 等屬性由系統控制,只需要配置目標 Activity 的 Theme 即可,

4.4 延長啟影片面
通過 setKeepVisibleCondition() 可以延長啟影片面的展示,無關運行的版本,原理都是向 ContentView 的 ViewTreeObserver 注冊OnPreDrawListener回呼來實作,
系統在描畫前先回呼 onPreDraw(),獲取是否放行描畫的條件,此處將回呼 KeepVisibleCondition 的邏輯,如果不放行,在下次螢屏重繪的時候繼續回呼,直到滿足條件開始描畫,啟動 Window 消失,描畫放行的時候,低版本額外需要手動呼叫 dispatchOnExitAnimation 來執行退出回呼,12 則由系統自行執行,
需要注意:這個時候退場用的自定義視圖仍然還沒添加上來,只是延遲了 SplashScreenWindow 的退出而已,

4.5 退場畫面的回呼
setOnExitAnimationListener() 可以監聽退場時機,
運行在低版本上的時候,需要手動加載啟影片面的布局到 ContentView中,并將之前設定的 Window Background 和 Icon 等屬性顯示,然后添加 Layout change 回呼,在布局完畢的時候通過 adjustInsets 特殊處理將 Icon 位置調整一下,判斷啟影片面保持條件是否達到,達到的話呼叫 onSplashScreenExit,
運行在 12 上的時候,布局不需要手動準備,通過 12 專用的系統介面,將視圖快取到 Provider 里即可,后續的 Exit 也由系統執行,

4.6 adjustInsets 的特殊處理
面向低版本的退場畫面在布局成功后會呼叫的特殊處理,
進場部分的是 Window Drawable,Icon 是居中的,但退場部分是向 ContentView中手動添加的 Framelayout 布局,Icon 在布局里是居中的,但由于 StatusBar 和 NavigationBar 高度不一樣,Icon 在整個 Window 里是偏下的,
如果不加干預的話,進場過渡到退場的時候,Icon 會發生跳躍,

原始碼通過 windowInsets API 獲取狀態欄和導航欄的高度,取差值的一半交由 IconView 去移動到 window 中間,
private class Impl23(activity: Activity) : Impl(activity) {
override fun adjustInsets( ... ) {
// Offset the icon if the insets have changed
val rootWindowInsets = view.rootWindowInsets
val ty = rootWindowInsets.systemWindowInsetTop
- rootWindowInsets.systemWindowInsetBottom
splashScreenViewProvider.iconView.translationY = -ty.toFloat() / 2f
}
}
結語
到這里我們探討了啟影片面的必要性、回顧了啟影片面打造的常規做法、介紹了 Android 12 上 SplashScreen API、以及詳細了解了 Jetpack SplashScreen 庫的目的、使用細節和實作原理!
可以看到 SplashScreen 庫簡單又清晰,可以幫助我們靈活、高效地重塑啟影片面,主要體現在這么幾個方面:
-
配置圖示影片、圖示背景、品牌 Logo 等新元素,打造豐富的進場效果
-
適當地調節啟影片面的展示時間,以配合后臺的加載
-
針對整體或 Icon 視圖,靈活打造無縫銜接的退場效果
-
靈活控制退場影片的有無和時長,自然地過渡到目標內容
值得提醒的是:啟影片面只是過渡,影片效果避免突兀,更不要過多占用用戶時間!
參考資料&資源分享
主要分享一下使用到的參考資料以及分享不錯的 DEMO,大家可以通過這些資料和 DEMO 切實感受和實踐下 SplashScreen 庫的玩法!
| 名稱 | 地址 |
|---|---|
| Splash Screen API 的官方介紹 | https://developer.android.google.cn/about/versions/12/features/splash-screen |
| Jetpack SplashScreen 庫的地址 | https://developer.android.google.cn/jetpack/androidx/releases/core?hl=zh-cn#core_splashscreen_version_100_2 |
| 本文原始碼公開后的 SplashScreen 專案 | https://github.com/ellisonchan/SplashScreen |
| ComposeBird 專案 | https://github.com/ellisonchan/ComposeBird |
最后一個著重說一下,這是我之前采用 Jetpack Compose 寫的 Flappy Bird 小游戲,我抽空給它適配了 SplashScreen 庫的功能,可以看到游戲啟動的時候小鳥漸漸飛進來,之后小鳥向上淡出到游戲界面的效果,
FAQ
| 問題 | 回答 |
|---|---|
| 1. 不知道有沒有解決多語言適配的問題 多螢屏適配問題 | 不顯示文字,不存在語言問題;Icon 按照 Adaptive Icon 規格提供即可,尺寸及居中的問題,SplashWindow 功能會處理 |
| 2. 這樣等于固定了樣式,請問產品能答應嗎,到頭來還不如就設定一張圖片的好,感覺沒有用武之地,而且ios沒有這玩意,無法同步,注定是個雞肋 | 這個 API 在設定靜態背景之外可以設定影片圖示,品牌圖示,退場效果等,可以給需要豐富啟動效果的 App 提供便利,iOS 的話我想肯定有同樣的辦法做到,只不過沒 Android 方便, |
| 3. 了解確實可以,但這東西在國內似乎沒啥用?國內啥 APP不放點廣告,有能耐的自己做廣告宣傳 沒能耐的接穿山甲,接優量匯, | 其實不影響廣告界面的展示,因為一般廣告展示前還有個展示 Logo 的啟影片面,可以把這個畫面用 SplashScreen 實作, |
| 4. 站在用戶的角度也站在我急躁性格的我,在用一個 app的時侯我一秒了也不想看到Splash頁面的存面. | 是的,SplashScreen 不能占用過長的時間,所以一般 Icon 影片控制在 1s 內,而退場影片的時長可以盡量縮短,或者榷訓退場效果, |
| 5. SplashScreen和目前設定啟動背景有什么差異啊,是否就是比現在的多了可以設定啟影片面的影片, | 除了背景還可以設定icon進場影片和品牌logo,除此之外可以便捷地控制啟影片面的時長,還可以定制退場影片,總結起來講,比以前定制的空間更大,但API并不復雜, |
| 6. 如果描畫的時候進場影片沒有執行完畢就消失,體驗會不會不好? | 描畫很快第一幀很早的話,確實可能發生進場影片進行程序中突然消失的現象, 但進場影片的時長最長只能設定為 1s,第一幀開始描畫且 1s 影片還沒執行完畢的情況很少發生, 一旦發生的話,可以考慮將剩余時間交給退場影片來優化一下,這樣子能夠過渡一下再退出,而不是直接消失, |
| 7. 如果延長條件一直保持會怎么樣?啟動影片會怎么樣? | 第一幀的描畫一直被掛起,啟影片面 Window 一直殘留,保持著在進場影片最后一幀,無法消失, |
| 8. Activity 指定的 Theme 和 postSplashScreenTheme 的區別是? | 前者專門為展示啟影片面準備的,后者則是 Activity 的最終主題,目的避免使用啟影片面主題影響到實際的顯示, |
| 9. installSplashScreen 的準確作用?不呼叫的話會怎么樣? | installSplashScreen 只是初始化一下定制入口,以及獲取設定資源和設定主題,看不到退場效果, 如果不呼叫的話,仍然可以看到進場畫面,但無法定制退場效果和更新 Activity 主題, |
| 10. 為什么 SplashScreen 庫不設計成低版本也支持 Brand Icon 和 影片 Icon? | Brand Icon 不像 App Icon,尺寸和形狀不一,利用現有的 Background Drawable 擔心有尺寸和顯示的問題,Icon 影片需要拿到影片 Drawable 并手動執行,單單利用 WindowBackground 屬性無法做到支持, |
| 11. App 開始 draw 的時候啟動 Window 便消失,那之后的屬性影片為什么還可以執行? | 12 的時候雖然 Window 退出了,但內部的視圖傳遞了過來放在我們的 DecorView 上,而 12 之前則是自定義的 FrameLayout 添加到了我們的 ContentView 上, 退場的時候我們執行影片的 View 本質上都是我們自己的 View,所以即便 SplashScreenWindow 消失了也沒關系, |
| 12. 為什么 Android 12 是將視圖添加到 DecorView,而 Jetpack 是添加到 ContentView? | 覆寫到 DecorView 上去,會和系統欄的顯示產生沖突,猜測是 Jetpack 無法解決一些諸如 StatusBar,NavigationBar 的顯示問題,而 Android 12 是系統級別的,可以更高權限地解決這些細節, |
| 13. SplashScreen 功能和 Activity 的 transition 影片的關系? | transition 包括 windowIsTranslucent,是針對 Activity window 而言的,和 SplashScreen 的啟影片面專用屬性是不一樣的,應用了 SplashScreen 特性的話,入口 Actvitiy 的影片就不需要了, |
| 14. 退場影片支持共享元素影片嗎? | SplashScreenView 不支持設定共享元素在畫面之間的 Transition 影片, |
| 15. 圖示影片的要求? | 將 SVG 轉成 AnimatedVectorDrawable 的檔案即可,內部通過屬性影片的標簽實作諸如 Path、位移、透明度等影片效果, |
推薦閱讀
之前針對 Android 12 的 SplashScreen API 和 Jetpack SplashScreen 庫分別寫過更為詳細的解讀文章,感興趣的朋友可補充食用~
- Android 12上全新的應用啟影片面,還不適配一下?
- Jetpack新成員SplashScreen:打造全新的App啟影片面
同時在 GDG 社區說 活動上也分享過本文的話題,可以到 B站 上觀看視頻回放:
「社區說」《使用 Jetpack SplashScreen 打造全新的應用啟動效果》
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/352262.html
標籤:其他
下一篇:【Android 逆向】Android 逆向通用工具開發 ( 靜態庫專案中的網路操作核心類 CNetwork 分析 )
