31
loading...
This website collects cookies to deliver better user experience
'Empty Activity Project'
in Android Studio, the main activity layout was adjusted to have the same design as the start screen reference. Nothing was made regarding the splash screen.onCreate()
method and it's views starts being rendered./res/values/themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.AnimatedSplashScreen"
parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Drawable to be rendered in window's background
while the activity is being loaded -->
<item name="android:windowBackground">
@drawable/your_splashscreen_drawable
</item>
</style>
</resources>
LayerDrawable
, that allows us to specify a list of drawables that is drawn in the order they're declared. In this example, we have a flat colored background with the logo centered in the screen. The use of android:gravity
informs the platform to center the second drawable in the middle of the screen./res/drawable/splash_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/splash_background"/>
<item android:gravity="center"
android:drawable="@drawable/splash_logo" />
</layer-list>
/res/drawable/splash_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/blue" />
</shape>
TransitionDrawable
. A transition drawable allows us to define two drawable layers and easily cross-fade between them using the startTransition(int)
method./res/drawable/splash_transition.xml
<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/splash_screen" />
<item android:drawable="@drawable/splash_background" />
</transition>
MainActivity.kt
class MainActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Checks if the splash screen was displayed before
// ->SavedInstanceState is not null after recreation!
val splashWasDisplayed = savedInstanceState != null
if(!splashWasDisplayed){
// 1 - Start fading out the logo
(window.decorView.background
as TransitionDrawable).startTransition(
logoCrossFadeDurationMillis
)
// 2 = As we can't register a listener to be
// notified when the transition drawable finishes,
// launches a coroutine that blocks while animation
// is being performed and sets the content view
lifecycleScope.launch {
// Time between the animations
delay(logoCrossFadeDurationMillis.toLong()
+ spacingAfterFadeDurationMillis)
window.decorView.background =
AppCompatResources.getDrawable(
this@MainActivity,
R.drawable.splash_background
)
setContentView(R.layout.activity_main)
}
}else{
// Splash was shown before, no need to animate it.
// 1 - Updates the window background (if needed)
window.decorView.background =
AppCompatResources.getDrawable(
this,R.drawable.splash_background
)
// 2 - Sets the content view instantly
setContentView(R.layout.activity_main)
}
}
...
themes.xml
...
<style name="Theme.AppSplash" parent="Theme.SplashScreen">
</style>
themes.xml
...
<style name="Theme.AppSplash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@drawable/your_background_drawable</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/your_icon_drawable</item>
</style>
themes.xml
...
<style name="Theme.AppSplash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@drawable/your_background_drawable</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/your_icon_drawable</item>
<item name="postSplashScreenTheme">@style/your_activity_theme</item>
</style>
build.gradle
...
android {
compileSdkVersion "android-S"
...
}
...
dependencies {
...
implementation 'androidx.core:core-splashscreen:1.0.0-alpha01'
}
installSplashScreen()
before setContentView()
MainActivity.kt
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
installSplashScreen()
setContentView(R.layout.activity_main)
}
}
AnimationDrawable
or AnimatedVector
. The AnimationDrawable
works similar to a classical animation which you have to represent AnimatedVectorDrawable
let's you describe your animation that will be interpolated by the framework.MainActivity.kt
class MainActivity : AppCompatActivity() {
companion object{
const val splashFadeDurationMillis = 300
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val splashWasDisplayed = savedInstanceState != null
if(!splashWasDisplayed){
val splashScreen = installSplashScreen()
splashScreen.setOnExitAnimationListener {
splashScreenViewProvider ->
// Get logo and start a fade out animation
splashScreenViewProvider.iconView
.animate()
.setDuration(
splashFadeDurationMillis.toLong()
)
.alpha(0f)
.withEndAction {
// After the fade out, remove the
// splash and set content view
splashScreenViewProvider.remove()
setContentView(R.layout.activity_main)
}.start()
}
}else{
setTheme(R.style.Theme_AnimatedSplashScreen)
setContentView(R.layout.activity_main)
}
}
}
setContent{}
instead of setContentView(int)
. That's it.MainActivity.kt
fun StartScreen() {
var visible by remember { mutableStateOf(false) }
Scaffold(
content = {
Box(
modifier = Modifier
.background(
colorResource(id = R.color.blue)
)
.fillMaxSize(),
) {
AnimatedVisibility(
visible = visible,
enter = slideInVertically(
initialOffsetY = {
// Slide in from top
-it
},
animationSpec = tween(
durationMillis =
MainActivity.splashFadeDurationMillis,
easing = LinearEasing
)
),
) {
Column(
verticalArrangement =
Arrangement.Center,
horizontalAlignment =
Alignment.CenterHorizontally,
modifier = Modifier
.padding(
0.dp,
0.dp,
0.dp,
0.dp
)
.background(
colorResource(
id = R.color.blue
)
)
.fillMaxSize()
) {
Text(
stringResource(
id = R.string.start_screen_title
),
fontSize = 36.sp,
modifier = Modifier.padding(
bottom =
dimensionResource(
R.dimen.start_content_title_margin_bottom
)
),
color = Color.White,
fontWeight = FontWeight.Bold
)
Box(
modifier = Modifier
.height(
dimensionResource(
R.dimen.start_content_size
)
)
.width(dimensionResource(
R.dimen.start_content_size
)
)
.clip(
RoundedCornerShape(
8.dp
)
)
.background(color = Color.White)
)
}
}
}
LaunchedEffect(true) {
visible = true
}
}
)
}