1. 程式人生 > 其它 >Android 12 適配指南——SplashScreen

Android 12 適配指南——SplashScreen

Android 12(API 31)引入了 SplashScreen 相關API,用於開發Android應用的啟動頁。

  • 影響在Andorid 12裝置上執行的所有應用:
    SplashScreen相關API的引入影響在Andorid 12裝置上執行的所有應用。這一點對於應用開發者來說,無論你的應用targetSdkVersion 版本是多少,均需要進行SplashScreen的適配工作。

  • 必須進行SplashScreen的適配工作:
    若開發者未進行SplashScreen的適配工作,當應用運行於Android 12及以上版本的裝置,在應用的冷啟動 或 溫啟動時,Android系統都會構造一個預設啟動動畫(預設啟動動畫由應用ICON

    + 應用主題的windowBackground內容構成)。
    因此,對於未進行SplashScreen API適配工作的應用,在冷啟動和溫啟動時,可能會呈現兩個啟動頁先後出現的情況(Android SplashScreen啟動頁 + Android應用自定義開發的啟動頁或引導頁)。

先看一下Andorid官方給出的SplashScreen啟動頁執行效果。

  • SplashScreen 使用方式
  • SplashScreen 啟動頁構成
  • SplashScreen 使用舉例原始碼下載

一、使用方式

按照官方相關遷移文件,我開發了以下啟動頁的執行效果。

下面以我開發的這個案例效果為例,舉例說明SplashScreen相關API的使用方式:

  • build.gradle 新增相關依賴;
  • 自定義SplashScreen主題;
  • 自定義啟動頁Activity;

1.1 build.gradle

build.gradle 中:

  • 更改 compileSdkVersion 的版本;
  • 引入 splashscreen 相關依賴 ;
android {  
 // 更改 compileSdkVersion 的版本
 compileSdk 31  
}  
  
dependencies {  
 // 引入 splashscreen 相關依賴  
 implementation "androidx.core:core-splashscreen:1.0.0-alpha02"  
}

1.2 SplashScreen主題

建立一個父級為 Theme.SplashScreen 的主題,並將 對應的主題設定到啟動頁 Activity 應用。

  • 建立自定義的 SplashScreen 主題;
  • SplashScreen 主題應用到對應的Activity;

建立 SplashScreen 主題:

直接給出style的程式碼舉例,主題中各屬性均給出了明確的註釋說明,不再進行重複說明。
這裡特別強調一下,windowSplashScreenAnimatedIcon 這個屬性,可以是一個 圖片、幀動畫、animated-vector動畫 等。

<!-- Splash啟動頁Style -->
<style name="Theme.SplashScreen.Demo" parent="Theme.SplashScreen">
    <!--啟動畫面背景顏色-->
    <item name="windowSplashScreenBackground">@color/splashscreen_bg</item>
    <!-- 啟動畫面icon圖示:這裡可以是圖片、幀動畫等-->
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_anim_icon</item>
    <item name="windowSplashScreenIconBackgroundColor">@color/splashscreen_icon_bg</item>
    <!-- icon動畫在關閉之前顯示的時長:最長時間為1000毫秒-->
    <item name="windowSplashScreenAnimationDuration">1000</item>
    <!-- 啟動畫面底部的 Brand 圖片-->
    <item name="android:windowSplashScreenBrandingImage">@drawable/brand_img</item>
    <!-- Splash退出後的主題-->
    <item name="postSplashScreenTheme">@style/Theme.Android12_Splash</item>
</style>

SplashScreen 主題應用到啟動頁Activity

這個啟動頁我自定義為 SplashActivity

<activity
    android:name=".SplashActivity"
    android:exported="true"
    android:theme="@style/Theme.SplashScreen.Demo">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

1.3 啟動頁Activity

上文提到,這個啟動頁的Activity,我自定定義為 SplashActivity,原始碼如下:

class SplashActivity : AppCompatActivity() {
    val TAG: String = "CoroutineScope"

    // 協程( 瞭解協程的使用,可參考:https://xiaxl.blog.csdn.net/article/details/123383727 )
    lateinit var mCoroutineScope: CoroutineScope

    // 資料
    private var mKeepOnAtomicBool = AtomicBoolean(true)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "----onCreate----")

        // 初始化操作(必須放在setContentView()之前)
        val mSplashScreen = installSplashScreen()
        // setContentView(可以省略)
        setContentView(R.layout.activity_splash)

        // 每次UI繪製前,會判斷 Splash 是否有必要繼續展示在螢幕上;直到不再滿足條件時,隱藏Splash。
        mSplashScreen!!.setKeepVisibleCondition(object : SplashScreen.KeepOnScreenCondition {
            override fun shouldKeepOnScreen(): Boolean {
                return mKeepOnAtomicBool.get()
            }
        })

        // Splash展示完畢的監聽方法
        mSplashScreen!!.setOnExitAnimationListener(object : SplashScreen.OnExitAnimationListener {
            override fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
                startSplashScreenExit(splashScreenViewProvider)
            }
        })

        // 建立 CoroutineScope (用於管理CoroutineScope中的所有協程)
        mCoroutineScope = CoroutineScope(Job() + Dispatchers.Main)
        mCoroutineScope.launch(Dispatchers.IO) {
            Log.d(TAG, "----launch----")
            // TODO 非同步執行緒
            // Splash展示2秒鐘
            delay(2000)
            // Splash 展示完畢
            mKeepOnAtomicBool.compareAndSet(true, false)
        }
    }

    /**
     * onDestroy
     */
    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "----onDestroy----")
        // 當 Activity 銷燬的時候取消該 Scope 管理的所有協程。
        mCoroutineScope.cancel()
    }

    /**
     * SplashScreen 退出時執行
     */
    private fun startSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
        Log.d(TAG, "----onSplashScreenExit----")
        // splashScreenView
        val splashScreenView = splashScreenViewProvider.view
        // splashIconView
        val iconView = splashScreenViewProvider.iconView

        /**
         * ScreenView alpha 動畫
         */
        val splashAlphaAnim = ObjectAnimator.ofFloat(splashScreenView, View.ALPHA, 1f, 0f)
        splashAlphaAnim.duration = 500
        splashAlphaAnim.interpolator = FastOutLinearInInterpolator()

        /**
         * iconView 向下移動的動畫
         */
        val translationY = ObjectAnimator.ofFloat(
            iconView,
            View.TRANSLATION_Y,
            iconView.translationY,
            splashScreenView.height.toFloat()
        )
        translationY.duration = 500
        translationY.interpolator = FastOutLinearInInterpolator()

        // 合併漸變動畫 & 下移動畫
        val animatorSet = AnimatorSet()
        animatorSet.playTogether(translationY, splashAlphaAnim)
        // 動畫結束時呼叫的方法
        animatorSet.doOnEnd { onAnimEnd(splashScreenViewProvider) }
        // 開啟動畫
        animatorSet.start()
    }

    /**
     * 當動畫結束
     */
    private fun onAnimEnd(splashScreenViewProvider: SplashScreenViewProvider) {
        //移除監聽
        splashScreenViewProvider.remove()
        //跳轉下個頁面
        // 進入主介面
        Log.d(TAG, "----startActivity MainActivity----")
        startActivity(Intent(this@SplashActivity, MainActivity::class.java))
        [email protected]()
        Log.d(TAG, "----SplashActivity finish----")
        // Activity 退場動畫
        overridePendingTransition(0, R.anim.activity_out)
    }
}

二、SplashScreen構成

仍然以本案例的程式碼效果進行舉例說明。

  • SplashScreen 構成
  • SplashScreen 中心ICON的大小

SplashScreen 構成

前邊介紹SplashScreen主題程式碼時,提到過我自定的Theme.SplashScreen.Demo主題:

<!-- Splash啟動頁Style -->
<style name="Theme.SplashScreen.Demo" parent="Theme.SplashScreen">
    <!--啟動畫面背景顏色-->
    <item name="windowSplashScreenBackground">@color/splashscreen_bg</item>
    <!-- 啟動畫面icon圖示:這裡可以是圖片、幀動畫等-->
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_anim_icon</item>
    <item name="windowSplashScreenIconBackgroundColor">@color/splashscreen_icon_bg</item>
    <!-- icon動畫在關閉之前顯示的時長:最長時間為1000毫秒-->
    <item name="windowSplashScreenAnimationDuration">1000</item>
    <!-- 啟動畫面底部的 Brand 圖片-->
    <item name="android:windowSplashScreenBrandingImage">@drawable/brand_img</item>
    <!-- Splash退出後的主題-->
    <item name="postSplashScreenTheme">@style/Theme.Android12_Splash</item>
</style>

其對應的屬性位置如下圖所示:

SplashScreen 中心ICON大小

關於 SplashScreen 中心ICON的dp大小,我們需檢視Android X的對應原始碼:

三、案例原始碼

本案例中SplashScreen案例原始碼下載地址如下:
https://download.csdn.net/download/aiwusheng/84992053

參考

Android將啟動畫面遷移到SplashScreen:
https://developer.android.google.cn/guide/topics/ui/splash-screen/migrate

Android12 SplashScreen:
https://developer.android.google.cn/about/versions/12/features/splash-screen

= THE END =

文章首發於公眾號”CODING技術小館“,如果文章對您有幫助,歡迎關注我的公眾號。