咱们的app开发时,都会有一个splash页面,用于提升用户体会。
原因是android app在启动时,因为application初始化等原因会有一个短暂的延迟,导致点击launcher后不能立刻启动activity并烘托。通常咱们运用的计划是增加SplashActivity,并且将windowbackground设置成app品牌图标等方式可以让用户点击launcher后快速相应并展示,提升用户体会。
但是在android 12版别今后,咱们发现点击launcher后,会显现一个运用Icon的图标一闪而过,然后才显现咱们的Splash页面,没错,官方Splash,他来了~那么咱们今天就适配官方splash吧。
官方适配文档,咱们看到,这个splash其实是无法防止的,也就是说咱们只能接受。
官方给出的建议是,撤销本来的splash,直接运用MainActivity作为程序进口,适配SplashScreen充任本来的SplashActivity页面。但是因为种种原因,原有的Splash可能有一定功用并不能很好的移植到MainActivity中,例如:deeplink的路由功用、程序初始化装备进口、通知栏路由等。
所以今天咱们就来适配老项目的Splash吧~
老规矩~先看作用
android12以上版别:
android12以下版别:
首先接入SplashCompat库,这是为了兼容android 12以下的版别。
implementation "androidx.core:core-splashscreen:1.0.0"
然后装备Splash的样式,这儿要注意~android 12以下和android 12以上要分隔装备,android 12以下的splash并不支撑动画作用,而android 12及以上是支撑动画作用的,并且支撑gif动画播放及splash结束的消失动画。
因而咱们的通用style装备如下:
<style name="SplashTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@null</item>
</style>
<style name="Theme.App.Launcher" parent="Theme.SplashScreen">
<item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher_round</item> 显现的图片资源,android 12以下不支撑动画
<item name="postSplashScreenTheme">@style/SplashTheme</item>
</style>
而values-31中装备android 12的主题如下。
<style name="Theme.App.Launcher" parent="Theme.MaterialComponents.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@color/black</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/gif_splash</item> 显现的图片资源,android 12以上支撑vector或gif资源
<item name="android:windowSplashScreenAnimationDuration">1000</item>
<item name="android:windowSplashScreenBackground">@color/black</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@null</item>
</style>
接下来咱们看SplashAct中如何兼容版别
首先是初始化显现:
override fun onCreate(savedInstanceState: Bundle?) {
注意,这儿的初始化要放到super.onCreate之前。
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
确保android 12以下版别可以不直接毁掉splashScreen
splashScreen.setKeepOnScreenCondition { true }
确保android 12以上版别可以不直接毁掉splashScreen
setupSplashScreen(splashScreen)
setupExitSplashScreenAnim(splashScreen)
mViewModel.init()
}
这段代码在android 12以下其实是不生效的,12以上会让splash一直显现,直到Splash中咱们的自定义操作执行完结,预备跳转。
原因是splashScreen组件会在当前Activity烘托榜首帧时主动移除,而咱们为了不显现两个Splash,就让体系的Splash多显现一会吧~
private fun setupSplashScreen(splashScreen: SplashScreen) {
val contentView: View = findViewById(android.R.id.content)
contentView.viewTreeObserver.addOnPreDrawListener(object :
ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (mViewModel.isReady) {
这儿是适配12以下体系,让其毁掉。
splashScreen.setKeepOnScreenCondition { false }
contentView.viewTreeObserver.removeOnPreDrawListener(this)
}
这个return值如果使true,则12以上体系毁掉splashScreen
return mViewModel.isReady
}
})
}
splashScreen毁掉时的动画,这儿支撑任何多种动画,我随便写了一个晃动。
private fun exitSplashScreen(splashScreen: SplashScreen) {
splashScreen.setOnExitAnimationListener { provider ->
val splashScreenView = provider.view
val springAnim = SpringAnimation(
splashScreenView,
SpringAnimation.TRANSLATION_X,
splashScreenView.x
)
springAnim.spring.stiffness = SpringForce.STIFFNESS_MEDIUM
springAnim.setStartVelocity(-2000f)
springAnim.setStartValue(splashScreenView.x)
springAnim.spring.dampingRatio = SpringForce.DAMPING_RATIO_HIGH_BOUNCY
springAnim.start()
springAnim.addEndListener { _, _, _, _ ->
动画结束后,跳转页面
jumpToMain()
provider.remove()
}
}
}
之后,咱们调用咱们自己的初始化办法~这儿我delay了5秒,模仿初始化耗时操作。 代码如下:
var isReady = false
fun init() {
viewModelScope.launch {
//do something init
//模仿初始化
delay(5000)
isReady = true
}
}
至此,咱们已经完结了官方的splash适配作用~
完好项目地址:传送门