Android12のアップデートがそろそろとなっている中、今更ながらにAndroid12(targetSDKVersion31)から利用できるSplashScreenAPIを触ってみました。
SplashScreenとは?
アプリが実行されていない時(コールドスタート)にSplash画面が表示される。 デフォルトではアダプティブアイコンの設定が引き回されるので、何も設定しなくてもアイコンがちゃんと設定されていれば表示はされる。 背景色に関してはandroid:windowBackgroundの属性を設定していればそちらの色設定で表示される。 別Activityを作成してSplashを作成していなければ、特に問題にはならなさそうです。
どんなカスタマイズができるか?
targetSDKVersionを31にすると下記の要素が設定できるようになります。xmlのテーマで設定できる項目
1.アイコンの変更 2.アイコンの背景変更 3.スクリーンの背景変更 4.ブランディングアイコンの追加 5.スクリーンの表示時間調整v31/themes.xml
<!-- 1.アイコンの変更 アダプティブアイコンの使用と同等なのでサイズに注意 -->
<item name="android:windowSplashScreenAnimatedIcon">@drawable/obake</item>
<!-- 2.アイコンの範囲の色設定 -->
<item name="android:windowSplashScreenIconBackgroundColor">@color/black</item>
<!-- 3.スクリーンの背景色-->
<item name="android:windowSplashScreenBackground">#ffff00</item>
<!-- 4.ブランディングアイコン -->
<item name="android:windowSplashScreenBrandingImage">@drawable/branding_icon</item>
<!-- 5.表示時間 -->
<item name="android:windowSplashScreenAnimationDuration">1000</item>
ブランディングアイコンについては公式のURLで非推奨との記載があるので、使わない方がいいかもしれません。
表示時間に関しては最大1000msまで。それ以上を設定したとしても、意味なしです。
プログラム上で設定できる項目
1.splash画面の表示時間調整
2.splash画面のアニメーション設定
1.splash画面の表示時間調整
起動時のActivityで任意のタイミングまで処理を止める形での対応です。onPreDrawListenerを設定して、消すタイミングまでListenerを設定しておく感じみたいです。ちょっと、無理矢理な感じは否めないのですが。。。 今回サンプルとしてわかりやすく、Activity内でフラグを持たせてますが、実際に適応する場合はviewModelにフラグを持たせておいて、終わったタイミングでフラグを更新する方が良さそうです。実際のGoogle側のサンプルコードもそうなっています。起動するActivityのファイル
class MainActivity : AppCompatActivity() {
private var isReady = false
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.
Log.d("TEST", " waiting splash !! ")
return if (isReady) {
Log.d("TEST", " show splash !! ")
content.viewTreeObserver.removeOnPreDrawListener(this)
true
} else {
waitSplash()
false
}
}
}
)
private fun waitSplash() {
lifecycleScope.launch(Dispatchers.Default) {
sleep(5000)
isReady = true
}
}
}
2.splash画面のアニメーション設定
splashScreenのviewを取得出来るようになっているので、onCreateなどで取得してアニメーションを追加します。起動するActivityのファイル
class MainActivity : AppCompatActivity() {
private var isReady = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (Build.VERSION.SDK_INT >= 31) {
splashScreen.setOnExitAnimationListener { splashScreenView ->
val turn = turnAnim(splashScreenView)
val slideUp = slideUpAnim(splashScreenView)
val animation = AnimatorSet()
animation.playSequentially(turn,slideUp)
animation.doOnEnd { splashScreenView.remove() }
// Run your animation.
animation.start()
}
}
}
private fun slideUpAnim(view: View): ObjectAnimator {
val animationObj = ObjectAnimator.ofFloat(
view,
View.TRANSLATION_Y,
0f,
-view.height.toFloat()
)
animationObj.interpolator = AnticipateInterpolator()
animationObj.duration = 500L
return animationObj
}
private fun turnAnim(view: View): ObjectAnimator {
val animationObj = ObjectAnimator.ofFloat(
view,
View.ROTATION_Y,
360f
)
animationObj.interpolator = AccelerateDecelerateInterpolator()
animationObj.duration = 1000L
return animationObj
}
}