In the early days, the startup speed of App on Android was often criticized, and now the startup performance is not inferior to iOS. Google's continuous optimization of the system is absolutely indispensable, from SplashWindow independent of 8.0 to the new SplashScreen launched on 12.
Before the main content of the App is displayed, according to different needs, these pictures will be displayed more or less first.
frame | purpose |
---|---|
Splash Screen | Display brand Logo or Slogan |
Advertisement Screen | Display festival activities or daily advertisements |
Guide Screen | Demonstrate key functions, usually only once |
1 Preface
We often spend energy to create a guide picture or advertising picture, but the starting picture as the first impression is easy to be ignored. Think back to how you handled this picture before:
-
Generally, the startup diagram provided by the UI is displayed by setting the windowssplashscreencontent property, and the system will create a special Window for it
-
If you forget to set this property, the default white background will cause a white screen to flash during startup
-
To get rid of this abrupt white picture, you can't simply set the Background to null, otherwise the flash will turn into a black picture
-
Finally, it is found that the windowDisablePreview property can completely close the screen, so that there is no sudden screen flash
However, this will bring the side effect of "slowing down" in startup, because after the startup screen used for transition is turned off, the screen before App drawing hardly changes. Even if the App performance does not deteriorate, in order to retain users, we still have to take good care of this startup screen.
However, the space available for customization of the existing windows splash screen content is really limited. Perhaps the official also noticed this, so they carefully designed the Splash Screen API and launched it in Android 12.
With the help of this new feature, the customization of the startup screen will be more free and convenient. Let's take a look at the startup effect of rapid customization using SplashScreen API.
The following will step by step demonstrate all aspects of the new SplashScreen that can be customized.
2. Customized entry effect
Using xml, you can quickly customize various entry effects.
2.1 default startup effect
By default, the startup screen will display the white background and Adaptive Icon on the Launcher. It is also good, which is much better than the previous white screen.
2.2 custom static Icon
Replace Icon with Adaptive Icon, and fine tune the background color to beige.
<item name="android:windowSplashScreenBackground">@color/newSplashScreenColor</item> <item name="android:windowSplashScreenAnimatableIcon">@drawable/ic_kotlin_hero_new</item>
2.3 custom Icon background
If the contrast between Icon tone and picture background color is not obvious enough, Icon background color can be added to enhance recognition.
<item name="android:windowSplashScreenIconBackground">@color/newSplashIconMaskColor</item>
2.4 user defined brand Logo
Adding a brand Logo can display the corporate image or Slogan, making the startup screen more complete and detailed.
<item name="android:windowSplashScreenBrandingImage">@drawable/ic_tm_brand_newer</item>
2.5 custom animation Icon
Icon in the form of animation can add design and creativity, making the startup process more smooth and interesting.
<item name="android:windowSplashScreenAnimatableIcon">@drawable/ic_kotlin_hero_new_animated_rotate</item> <item name="android:windowSplashScreenAnimationDuration">@integer/icon_animator_duration</item>
For example, rotate the robot icon.
Another example is to let the robot slide sideways on Kotlin.
Or let the geometric pattern piece together the letter K and merge with the robot, symbolizing the strong combination of Android and Kotlin.
be careful:
- The maximum duration of animation Icon is 1000ms.
- The entry animation of the icon can be customized, but it is controlled by the system and cannot be monitored and processed additionally.
2.6 extended start screen
The splash screen is dismissed as soon as your app draws its first frame. If you need to load a small amount of data such as in-app theme settings from a local disk asynchronously, you can use ViewTreeObserver.OnPreDrawListener to suspend the app to draw its first frame.
The loading of background data is inevitably time-consuming. The experience is not very good if the main content is not loaded after the start-up screen is finished. Just be able to control the duration of the startup screen.
The OnPreDrawListener callback of the existing ViewTreeObserver can suspend the drawing. If we release the drawing after the data is ready, we can indirectly extend the display of the startup screen.
For example, the Activity will not release the drawing until 2s after initialization.
class SplashActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... keepSplashScreenLonger() } private fun keepSplashScreenLonger() { // Monitor the drawing timing of Content View val content: View = findViewById(android.R.id.content) content.viewTreeObserver.addOnPreDrawListener( object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { // When ready, draw and release, otherwise hang return if (viewModel.isDataReady()) { content.viewTreeObserver.removeOnPreDrawListener(this) true } else { false } } } ) } } class MyViewModel(application: Application): AndroidViewModel(application) { companion object { const val WORK_DURATION = 2000L } private val initTime = SystemClock.uptimeMillis() fun isDataReady() = SystemClock.uptimeMillis() - initTime > WORK_DURATION }
Take a look at the effect and find that the display time of the startup screen has indeed become longer.
3. Customized exit effect
When the first frame of the App starts drawing, SplashScreen will exit the display. In order to enrich the experience of exit, the system also opens the corresponding entrance, that is, the callback of screen exit. In this callback, you can start to customize the exit effect, including the overall exit animation and icon exit animation.
3.1 exit of monitoring startup screen
Register OnExitAnimationListener interface with SplashScreen to monitor the exit of the startup screen.
override fun onCreate(savedInstanceState: Bundle?) { ... customizeSplashScreenExit() } private fun customizeSplashScreenExit() { splashScreen.setOnExitAnimationListener { splashScreenView -> Log.d("Splash", "SplashScreen#onSplashScreenExit view:$splashScreenView") sleep(1000) Log.d("Splash", "SplashScreen#remove after sleeping") splashScreenView.remove() } }
You can see that after the startup screen is displayed, it will disappear again in full screen by default without customization.
The log is as follows:
Splash : Activity:com.example.splash.MainActivity@f70c0d0 Activity:com.example.splash.MainActivity@f70c0d0 onCreate Splash : Activity:com.example.splash.MainActivity@f70c0d0 onStart Splash : Activity:com.example.splash.MainActivity@f70c0d0 onResume Splash : SplashScreen#onSplashScreenExit view:android.window.SplashScreenView{18339d5 V.E...... ........ 0,0-1080,2280} Splash : SplashScreen#remove after sleeping
Remember to call remove to remove the startup screen in time, otherwise SplashScreen will cover the main screen for a long time, about 5s.
In addition, the callback registration needs to be placed in front of the Activity#onResume, otherwise it cannot be monitored.
3.2 customize the overall exit animation
Various animations such as TRANSLATE, SCALE, ROTATE and ALPHA can be set for the whole startup screen to make the exit more natural.
For example, add an animation to splash screen to reduce the screen.
private fun customizeSplashScreenExit() { splashScreen.setOnExitAnimationListener { splashScreenView -> showSplashExitAnimator(splashScreenView) } } private fun showSplashExitAnimator(splashScreenView: SplashScreenView) { val path = Path() path.moveTo(1.0f, 1.0f) path.lineTo(0f, 0f) val scaleOut = ObjectAnimator.ofFloat( splashScreenView, View.SCALE_X, View.SCALE_Y, path ) ... scaleOut.doOnEnd { splashScreenView.remove() } scaleOut.start() }
Or pan the animation of the screen from above.
private fun showSplashExitAnimator(splashScreenView: SplashScreenView) { val slideUp = ObjectAnimator.ofFloat( splashScreenView, View.TRANSLATION_Y, 0f, -splashScreenView.height.toFloat() ) ... slideUp.start() }
3.3 exit animation of customized Icon
Of course, you can also animate the Icon separately, such as sliding the Icon up.
private fun customizeSplashScreenExit() { splashScreen.setOnExitAnimationListener { splashScreenView -> showSplashIconExitAnimator(splashScreenView) } } private fun showSplashIconExitAnimator(splashScreenView: SplashScreenView) { val iconView = splashScreenView.iconView ?: return val slideUp = ObjectAnimator.ofFloat( splashScreenView.iconView, View.TRANSLATION_Y, 0f, -iconView.height * 2.toFloat() ) ... slideUp.start() }
3.4 appropriate length of time to exit animation
There is a supplementary explanation for the customization of exit animation.
By the start of this callback, the animated vector drawable on the splash screen has begun. Depending on the duration of the app launch, the drawable might be in the middle of its animation. Use SplashScreenView.getIconAnimationStart to know when the animation started. You can calculate the remaining duration of the icon animation.
In short, the Icon animation may be halfway through when exiting the screen callback. It's best to calculate the remaining duration of the Icon animation to execute the exit animation.
The reason is that the device performance will affect the time of App drawing, and the above exit callback will be executed when drawing the first frame. In other words, the performance will affect the callback timing of the exit of the startup screen.
- If the performance is good, the callback of screen exit is earlier. At this time, Icon animation is still in progress. You can hand over the remaining time of the preset duration of Icon animation to the exit effect for execution
- If the performance is poor, the callback of screen exit is later. Icon animation has long ended. In order to let users see the content of the screen as soon as possible, they should no longer execute the exit effect, but exit directly
You can't keep users waiting to show the effect, otherwise you will be self defeating.
With the help of SplashScreenView's iconAnimationStartMillis and iconAnimationDurationMillis methods, the remaining duration of Icon animation can be calculated.
*For the reason of running on the simulator, most of the time when my Demo exits the startup screen, the Icon animation ends. In a few cases, the animation still has a little time left. The situation of the real machine may be different.
private fun showSplashIconExitAnimator(splashScreenView: SplashScreenView) { slideUp.duration = getRemainingDuration(splashScreenView) ... } fun getRemainingDuration(splashScreenView: SplashScreenView): Long { // Get the duration of Icon animation val animationDuration = splashScreenView.iconAnimationDurationMillis // Get the start time of Icon animation val animationStart = splashScreenView.iconAnimationStartMillis // Then calculate the remaining duration of Icon animation combined with the current time // 1. If the duration is negative, it will be fixed to 0ms, i.e. exit directly // 2. The duration is regular, which is used to execute the exit animation return if (animationDuration != null && animationStart != null) { (animationDuration - SystemClock.uptimeMillis() + animationStart) .coerceAtLeast(0L) } else { 0L } }
4 SplashScreen related API s
4.1 class and interface
Class / interface | effect |
---|---|
SplashScreen | Start the screen management interface and get it through Activity#getSplashScreen |
OnExitAnimationListener | The callback interface for the exit of the startup screen is registered through SplashScreen#setOnExitAnimationListener |
SplashScreenView | The startup screen contains views to customize the exit animation of the whole or Icon |
4.2 properties
attr | effect | remarks |
---|---|---|
splashScreenTheme | Specifies the Style associated with SplashScreen | There are some problems. For example, the brand image will not be displayed |
windowSplashScreenBackground | Customize the background of the splash screen | By default, it is read from the windowBackground |
windowSplashScreenBrandingImage | Specifies the brand icon at the bottom of the splash screen | - |
windowSplashScreenAnimatedIcon | Specify Icon and support static or animated Drawable | - |
windowSplashScreenAnimationDuration | Specifies the animation Icon duration | Upper limit 1000ms |
windowSplashScreenIconBackgroundColor | Supplementary Icon background color | - |
Note: windowssplashscreencontent is the attribute of customized startup screen added in version 8.0. It has been abandoned since December, and is replaced by windowssplashscreenanimated icon
4.3 composition of splashScreen
5 attention
If you need to try SplashScreen, you need to develop it on Android 12 and make the following necessary configurations.
-
compileSdkVersion and targetSdkVersion are declared as S
-
android:exported="true", explicitly declare the visibility of the startup screen, otherwise the installation will fail
In addition, the Icon on the startup page, whether static or animated, should follow the specification of Adaptive Icon, otherwise the Icon will be deformed.
6 Conclusion
The new SplashScreen API on Android 12 is very simple and clear, and the whole customization process is very smooth!
I believe that with the new API blessing, the startup screen of APP can burst out more distinctive and fun ideas.
Try it quickly and make a good first impression on your users~
This article DEMO
https://github.com/ellisonchan/SplashScreen
reference material
Welcome to Android 12 developer preview 3
Official documentation for SplashScreen
Recommended reading
Full recovery of Backup function easily ignored by Android developers