😎

Android 12 Splash screen

2021/10/19に公開

last update 2021/10/20 (継続更新中)

OverView

Android 12からアプリの起動時にsplash screenが強制的に挿入されるようになりまりました。
本記事ではこのsplash screenの振る舞いとカスタマイズ方法について記します。

How the splach screen works

Splash screenが表示されるケース

  • アプリのプロセスが実行されていない状態での起動(cold start)
  • アプリのプロセスは実行されているがActivityが作られていない状態での起動(warm start)

Mechanics of the Splash screen

Contents

① アイコン

デフォルトでは、ランチャーアイコンが使用される。
またはVector drawableで描画可能なものを指定可能。
静止画でもアニメーションでもOK。
アニメーションの継続時間は無制限だが、1秒を超えないことを推奨されている。

② アイコン背景

アイコン背景領域。円形のアイコン設定の場合この領域も円形になる。
カスタム可能だが、アダプティブアイコンを設定している場合、そこで指定している背景が優先される。

③ アイコンの領域

アイコンが配置される領域。
アダプティブアイコン同様1/3がマスクされている

④ 背景

不透明な単色で描画される。
カスタム可能。
特に指定がない場合はウィンドウの背景色が適用される。

⑤ ブランディングイメージ

画面下部に表示される静止画。
カスタマイズできるように用意されて入るが、Googleが用意したデザインのガイドライン的には利用はオススメしないとのこと。
サイズは縦横80dp*200dpで確保される(深くおってないけど画面サイズに応じてリサイズされる場合がありそう?)

表示位置は画面下部から60dpの位置
test

Enter/Exit Animation

splash screenは開始アニメーションと終了アニメーションがシステムによって組み込まれています

開始アニメーション

splash screenを表示する際のアニメーション。
画面のfadeやアイコンの領域の位置変更など。
カスタマイズは不可

終了アニメーション

splash screenが終了する際のアニメーション。
カスタマイズは可能
変化、透明度、色を設定し、任意のアニメーションを実行することができます。
ただしカスタマイズした場合はsplash screenの終了タイミングも自身で実装する必要があります。

How to customize

Custamazable feature

  1. アイコン
  2. アイコン背景の色
  3. 背景の色
  4. splash screenの表示時間
  5. splash screenの終了アニメーション
  6. ブランディングイメージ

事前準備

Compile SDKを31にする
Jetpack SplashScreenを利用する(2021/10/19時点では1.0.0-alpha02が最新)

android {
   compileSdkVersion 31
   ...
}
dependencies {
   ...
   implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
}

1. splash screenのアイコン

App or Activityに適用されているthemeから以下の様に指定可能。
vector animationなどもOK。

<item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item>
Before After
TBD

2. アイコン背景の色

App or Activityに適用されるthemeから以下の様にcolor指定可能。
ただしこの設定を適用する場合はthemeのparentをTheme.SplashScreen.IconBackgroundにする必要があります。
windowSplashScreenAnimatedIconで設定されたdrawableの背景に対して適用されます。
よって、windowSplashScreenAnimatedIconが指定されていない場合はこの設定は適用されません。

<item name="android:windowSplashScreenIconBackgroundColor">@color/...</item>
Before After
TBD

3. 背景の色

App or Activityに適用されるthemeから以下の様にcolor指定可能。
不透明な色でカスタムできます。

<item name="android:windowSplashScreenBackground">@color/...</item>
Before After

4. splash screenの表示時間

splash screenの表示時間は変更可能です(制限なし)
ただし、Googleの推奨している時間は1000msです。

Before After
TBD
シーンによって以下のやり方があります。

アプリを起動にする当たっての準備が済んでいない場合

以下のようにaddOnPreDrawListenerを実装して表示準備が完了した後にOnPreDrawListenerでtrueを返すようにする。
trueが返却されるまではsplash screenが表示されたままになる。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)

    val content: View = findViewById(android.R.id.content)
    content.viewTreeObserver.addOnPreDrawListener(
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                // Check if the initial data is ready.
                return if (viewModel.isReady) {
                    // The content is ready; start drawing.
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    true
                } else {
                    // The content is not ready; suspend.
                    false
                }
            }
        }
    )
}

splash screenアニメーション終了を待つ場合

アニメーションの終了を待つ場合は、
Activityに適用されるthemeへ以下のように設定します。
この設定値はSplashScreenView.getIconAnimationDurationで取得ができます。
※ここで設定した時間分splash screenの表示時間が伸びるわけではありません。

<item name="android:windowSplashScreenAnimationDuration">1000</item>

ActivityでSplashScreenにOnExitAnimationListenerを登録し、
SplashScreenViewから取得できるアニメーション開始時刻(animationStart)と上記設定時間(iconAnimationDuration)から残時間を計算し、その分delayさせることでsplash screenの表示時間を適切に伸ばすことができます。

splashScreen.setOnExitAnimationListener { ssv ->
    val animationDuration = ssv.iconAnimationDuration
    val animationStart = ssv.iconAnimationStart
    val remainingDuration = if (animationDuration != null && animationStart != null) {
        (animationDuration - Duration.between(animationStart, Instant.now()))
            .toMillis()
            .coerceAtLeast(0L)
    } else {
        0L
    }            
    lifecycleScope.launch {
        delay(remainingDuration)
        ssv.remove()
    }
}

5. splash screenの終了アニメーション

以下の様にActivityでSplashScreenにOnExitAnimationListenerを登録し、
SplashScreenView(アイコン)に対してコード上からもAnimationを適用する事ができます。

Before After
TBD
やれることはAndroidのアニメーションに対してできること
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...

    // Add a callback that's called when the splash screen is animating to
    // the app content.
    splashScreen.setOnExitAnimationListener { splashScreenView ->
        // Create your custom animation.
        val slideUp = ObjectAnimator.ofFloat(
            splashScreenView,
            View.TRANSLATION_Y,
            0f,
            -splashScreenView.height.toFloat()
        )
        slideUp.interpolator = AnticipateInterpolator()
        slideUp.duration = 200L

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.doOnEnd { splashScreenView.remove() }

        // Run your animation.
        slideUp.start()
    }
}

6. ブランディングイメージ

App or Activityに適用されるthemeから以下の様に指定可能。
静止画のみ。画面下部に表示される
指定してない場合は何も表示されない。

<item name="android:windowSplashScreenBrandingImage">@drawable/...</item>

Discussion