Android 12 以降、SplashScreen
API により、アプリの起動時にアニメーション(起動時のアプリ行きの動き、アプリアイコンを表示するスプラッシュ画面、アプリ本体への遷移など)を表示できます。SplashScreen
は Window
であるため、Activity
が対象となります。
スプラッシュ画面のエクスペリエンスでは、アプリを起動するたびに標準のデザイン要素が提供されますが、カスタマイズもできるため、アプリ独自のブランディングを維持できます。
SplashScreen
プラットフォーム API を使用するだけでなく、SplashScreen
API をラップする SplashScreen
互換性ライブラリを使用することもできます。
スプラッシュ画面の仕組み
アプリのプロセスが実行されていないとき(コールド スタート)または Activity
が作成されていないとき(ウォーム スタート)にユーザーがアプリを起動すると、次のイベントが発生します。
定義したテーマとアニメーションを使用してスプラッシュ画面が表示されます。
アプリの準備が整うと、スプラッシュ画面が閉じてアプリが表示されます。
ホットスタート時にスプラッシュ画面が表示されることはありません。
スプラッシュ画面の要素とメカニズム
スプラッシュ画面の要素は、Android マニフェスト ファイル内の XML リソース ファイルで定義されます。要素ごとにライトモードとダークモードのバージョンがあります。
スプラッシュ画面のカスタマイズ可能な要素は、アプリアイコン、アイコン背景、ウィンドウ背景で構成されます。
図 2 に示す次の要素について考えてみましょう。
1 アプリアイコンはベクター型ドローアブルにする必要があります。静止画像またはアニメーションにすることができます。アニメーションの継続時間に制限はありませんが、1,000 ミリ秒以下にすることをおすすめします。デフォルトはランチャー アイコンです。
2 アイコン背景は省略可能です。アイコンとウィンドウ背景とのコントラストを上げる必要がある場合に便利です。アダプティブ アイコンを使用する場合、ウィンドウ背景とのコントラストが十分あれば、背景が表示されます。
3 アダプティブ アイコンと同様に、フォアグラウンドの 3 分の 1 がマスクされています。
4 ウィンドウ背景は、不透明な単色で構成されています。ウィンドウ背景が設定され、無地の色である場合、この属性が設定されていなければ、その背景がデフォルトで使用されます。
スプラッシュ画面のサイズ
スプラッシュ画面のアイコンの仕様は、次のようにアダプティブ アイコンと同じです。
- ブランド イメージ: 200 × 80 dp にする必要があります。
- アイコンの背景があるアプリアイコン: 240 x 240 dp とし、直径 160 dp の円内に収まる必要があります。
- 背景がないアプリアイコン: 直径が 192 dp の円に収まる 288 x 288 dp にする必要があります。
たとえば、画像の合計サイズが 300 x 300 dp の場合、アイコンを直径 200 dp の円内に収める必要があります。円の外側にあるものはすべて非表示になります(マスクされます)。
スプラッシュ画面のアニメーションと起動シーケンス
レイテンシの増加は一般に、コールド スタートでのアプリの起動に関連します。スプラッシュ画面にアニメーション アイコンを追加すると、自然に美しさに目が向き、エクスペリエンスを高めることができます。ユーザー調査によると、アニメーションを表示した場合は起動時間が認識されにくいというメリットもあります。
スプラッシュ画面のアニメーションは、図 4 に示すように、起動シーケンス コンポーネントに埋め込まれます。
開始アニメーション: システムビューからスプラッシュ画面までです。これはシステムによって制御され、カスタマイズできません。
スプラッシュ画面(シーケンスの「待機」部分に表示): スプラッシュ画面はカスタマイズでき、独自のロゴのアニメーションやブランディングの提示に利用できます。適切に動作するためには、このページに記載されている要件を遵守する必要があります。
終了アニメーション: スプラッシュ画面を非表示にするアニメーションです。カスタマイズする場合は、
SplashScreenView
とそのアイコンを使用します。変換、不透明度、色を設定して任意のアニメーションを実行できます。この場合、アニメーションが終了したらスプラッシュ画面を手動で削除します。
アイコンのアニメーションを実行すると、アプリの起動により、アプリの準備が早く整った場合にシーケンスをスキップするためのオプションが表示されます。アプリが onResume()
をトリガーするか、スプラッシュ画面が自動的にタイムアウトするため、モーションを安心してスキップできることをご確認ください。スプラッシュ画面が onResume()
で閉じるのは、アプリが表示の観点で安定している場合のみであるため、スピナーの追加は必要ありません。導入するインターフェースが不完全であると、ユーザーに不快感をもたらす可能性があるだけでなく、予測できないという印象や洗練さに欠けるという印象を与えかねません。
スプラッシュ画面のアニメーションの要件
スプラッシュ画面は次の仕様に遵守する必要があります。
ウィンドウ背景を単色で透明度なしに設定します。日中モードと夜間モードは、
SplashScreen
互換ライブラリでサポートされています。アニメーション アイコンが次の仕様を遵守していることを確認します。
- 形式: アイコンは AnimatedVectorDrawable(AVD)の XML にする必要があります。
- サイズ: AVD アイコンは、次のように、アダプティブ アイコンのサイズの 4 倍にする必要があります。
- アイコンの領域は 432 dp(つまり、アダプティブ アイコンのマスクされない領域である 108 dp の 4 倍)にする必要があります。
- 画像の内側の 2/3 がランチャー アイコンに表示され、288 dp(つまり、アダプティブ アイコンの内側のマスクされる領域である 72 dp の 4 倍)にする必要があります。
- 継続時間: スマートフォンでは 1,000 ミリ秒を超えないようにすることをおすすめします。遅延スタートを使用することもできますが、166 ミリ秒以下にする必要があります。アプリの起動時間が 1,000 ミリ秒を超える場合は、ループ アニメーションをご検討ください。
スプラッシュ画面を閉じる適切なタイミングを設定します。このタイミングで、アプリは最初のフレームを表示します。この設定は、スプラッシュ画面を長時間表示するに記載されているように、さらにカスタマイズできます。
スプラッシュ画面のリソース
スターター キットの例をダウンロードします。このキットでは、アニメーションの作成、フォーマット、AVD へのエクスポートを行う方法を確認できます。次のツールが含まれています。
- アニメーションの Adobe After Effects プロジェクト ファイル。
- 最終的にエクスポートされる AVD XML ファイル。
- アニメーションの GIF の例。
上記のファイルをダウンロードすると、Google 利用規約に同意したことになります。
このサービスでのデータの取り扱いについては、Google プライバシー ポリシーに記載されています。
アプリのスプラッシュ画面をカスタマイズする
windowBackground
が単色の場合、SplashScreen
はデフォルトでテーマの windowBackground
を使用します。スプラッシュ画面をカスタマイズするには、アプリのテーマに属性を追加します。
アプリのスプラッシュ画面は、次のいずれかの方法でカスタマイズできます。
外観を変更するにはテーマ属性を設定します。
長時間表示する。
スプラッシュ画面を閉じるためのアニメーションをカスタマイズします。
始める
コア SplashScreen
ライブラリにより、API 23 からすべてのデバイスに Android 12 スプラッシュ画面が導入されます。プロジェクトに追加するには、build.gradle
ファイルに次のスニペットを追加します。
Groovy
dependencies { implementation "androidx.core:core-splashscreen:1.0.0" }
Kotlin
dependencies { implementation("androidx.core:core-splashscreen:1.0.0") }
スプラッシュ画面のテーマを設定して外観を変更する
アプリのスプラッシュ画面をカスタマイズするには、Activity
テーマに以下の属性を指定します。android:windowBackground
のような属性を使用する以前のスプラッシュ画面実装がある場合は、Android 12 以降用の代替リソース ファイルを提供することをご検討ください。
背景を特定の単色で塗りつぶすには、
windowSplashScreenBackground
を使用します。<item name="android:windowSplashScreenBackground">@color/...</item>
windowSplashScreenAnimatedIcon
を使用して、開始ウィンドウの中央のアイコンを置き換えます。Android 12(API レベル 32)のみをターゲットとするアプリの場合は、次の操作を行います。
AnimationDrawable
とAnimatedVectorDrawable
でオブジェクトのアニメーション化と描画が可能な場合は、開始ウィンドウを表示しつつアニメーションを再生するようにwindowSplashScreenAnimationDuration
を設定します。Android 13 では、所要時間がAnimatedVectorDrawable
から直接推定されるため、この操作は必要ありません。<item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item>
スプラッシュ画面のアイコン アニメーションの継続時間を指定するには、
windowSplashScreenAnimationDuration
を使用します。これを設定しても、スプラッシュ画面が表示される実際の時間には影響しませんが、SplashScreenView.getIconAnimationDuration
を使用してスプラッシュ画面の終了アニメーションをカスタマイズするときに取得できます。詳しくは、次のセクションのスプラッシュ画面を長時間表示するをご覧ください。<item name="android:windowSplashScreenAnimationDuration">1000</item>
スプラッシュ画面のアイコンの背景を設定するには、
windowSplashScreenIconBackgroundColor
を使用します。これは、ウィンドウの背景とアイコンのコントラストが不十分な場合に役立ちます。<item name="android:windowSplashScreenIconBackgroundColor">@color/...</item>
windowSplashScreenBrandingImage
を使用すると、スプラッシュ画面の下部に表示する画像を設定できます。ただし、デザイン ガイドラインでは、ブランド画像の使用はおすすめしません。<item name="android:windowSplashScreenBrandingImage">@drawable/...</item>
Android 13 以降では、
windowSplashScreenBehavior
を使用して、スプラッシュ画面にアイコンを常に表示するかどうかを指定できます。デフォルト値は 0 です。起動アクティビティがsplashScreenStyle
をSPLASH_SCREEN_STYLE_ICON
に設定した場合はスプラッシュ画面にアイコンが表示され、起動アクティビティがスタイルを指定していない場合はシステムの動作に従います。空のスプラッシュ画面を表示せず、常にアニメーション アイコンを表示する場合は、この値をicon_preferred
に設定します。<item name="android:windowSplashScreenBehavior">icon_preferred</item>
スプラッシュ画面を長時間表示する
スプラッシュ画面は、アプリが最初のフレームを描画するとすぐに閉じます。アプリ内の設定など、少量のデータをローカル ディスクから非同期で読み込む必要がある場合は、ViewTreeObserver.OnPreDrawListener
を使用して、最初のフレームを描画しないようアプリを一時停止します。
開始アクティビティが描画前に終了する場合(たとえば、コンテンツ ビューを設定せず、onResume
の前に終了する場合など)は、描画前リスナーは必要ありません。
Kotlin
// Create a new event for the activity. override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Set the layout for the content view. setContentView(R.layout.main_activity) // Set up an OnPreDrawListener to the root view. val content: View = findViewById(android.R.id.content) content.viewTreeObserver.addOnPreDrawListener( object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { // Check whether the initial data is ready. return if (viewModel.isReady) { // The content is ready. Start drawing. content.viewTreeObserver.removeOnPreDrawListener(this) true } else { // The content isn't ready. Suspend. false } } } ) }
Java
// Create a new event for the activity. @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set the layout for the content view. setContentView(R.layout.main_activity); // Set up an OnPreDrawListener to the root view. final View content = findViewById(android.R.id.content); content.getViewTreeObserver().addOnPreDrawListener( new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { // Check whether the initial data is ready. if (mViewModel.isReady()) { // The content is ready. Start drawing. content.getViewTreeObserver().removeOnPreDrawListener(this); return true; } else { // The content isn't ready. Suspend. return false; } } }); }
スプラッシュ画面を閉じるためのアニメーションをカスタマイズする
Activity.getSplashScreen()
を使用すると、スプラッシュ画面のアニメーションをさらにカスタマイズできます。
Kotlin
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() } }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... // Add a callback that's called when the splash screen is animating to the // app content. getSplashScreen().setOnExitAnimationListener(splashScreenView -> { final ObjectAnimator slideUp = ObjectAnimator.ofFloat( splashScreenView, View.TRANSLATION_Y, 0f, -splashScreenView.getHeight() ); slideUp.setInterpolator(new AnticipateInterpolator()); slideUp.setDuration(200L); // Call SplashScreenView.remove at the end of your custom animation. slideUp.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { splashScreenView.remove(); } }); // Run your animation. slideUp.start(); }); }
このコールバックの開始時、スプラッシュ画面のアニメーション化ベクター型ドローアブルは開始します。アプリの起動にかかる時間によっては、ドローアブルがアニメーションの中ほどにある場合があります。SplashScreenView.getIconAnimationStart
を使用して、アニメーションがいつ開始されたのかを把握します。アイコン アニメーションの残りの時間は次のように計算できます。
Kotlin
// Get the duration of the animated vector drawable. val animationDuration = splashScreenView.iconAnimationDuration // Get the start time of the animation. val animationStart = splashScreenView.iconAnimationStart // Calculate the remaining duration of the animation. val remainingDuration = if (animationDuration != null && animationStart != null) { (animationDuration - Duration.between(animationStart, Instant.now())) .toMillis() .coerceAtLeast(0L) } else { 0L }
Java
// Get the duration of the animated vector drawable. Duration animationDuration = splashScreenView.getIconAnimationDuration(); // Get the start time of the animation. Instant animationStart = splashScreenView.getIconAnimationStart(); // Calculate the remaining duration of the animation. long remainingDuration; if (animationDuration != null && animationStart != null) { remainingDuration = animationDuration.minus( Duration.between(animationStart, Instant.now()) ).toMillis(); remainingDuration = Math.max(remainingDuration, 0L); } else { remainingDuration = 0L; }
参考情報
- 既存のスプラッシュ画面の実装を Android 12 以降に移行する
- スプラッシュ画面の実際の実装を示す Now in Android アプリ