What You Will Build
A branded splash screen with a deep gradient background, a pulsing and rotating radial glow ring behind the logo, and fading text. The animation uses three independent infinite transitions for scale, alpha, and rotation. This is the app launch experience pattern used by premium apps.
Why This Pattern Matters
Splash screens set the tone for an app. While the Android 12+ SplashScreen API handles the initial launch, custom animated splash screens are still used for loading states, onboarding entry points, and branded transitions between major app sections.
Step 1: Three Infinite Transitions
val infiniteTransition = rememberInfiniteTransition(label = "splash")
val scale by infiniteTransition.animateFloat(
0.8f, 1.2f,
infiniteRepeatable(tween(2000), RepeatMode.Reverse),
label = "sc"
)
val alpha by infiniteTransition.animateFloat(
0.5f, 1f,
infiniteRepeatable(tween(1500), RepeatMode.Reverse),
label = "al"
)
val rotation by infiniteTransition.animateFloat(
0f, 360f,
infiniteRepeatable(tween(8000, easing = LinearEasing)),
label = "rot"
)
Step 2: Gradient Background and Glow Ring
Box(
Modifier.fillMaxSize().background(
Brush.verticalGradient(listOf(
Color(0xFF1A1A2E),
Color(0xFF16213E),
Color(0xFF0F3460)
))
),
contentAlignment = Alignment.Center
) {
// Rotating, pulsing glow ring
Box(
Modifier.size(180.dp)
.scale(scale)
.graphicsLayer(rotationZ = rotation)
.clip(CircleShape)
.background(
Brush.radialGradient(listOf(
Color(0xFF4ECDC4).copy(alpha = 0.3f),
Color.Transparent
))
)
)
// Logo text
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("BD", fontSize = 64.sp,
fontWeight = FontWeight.Bold,
color = Color.White.copy(alpha = alpha))
Spacer(Modifier.height(8.dp))
Text("Beautiful Design",
color = Color.White.copy(alpha = alpha * 0.7f),
style = MaterialTheme.typography.bodyLarge)
}
}
Tips and Pitfalls
- graphicsLayer(rotationZ = ...) applies rotation without triggering re-layout. It operates at the drawing layer, which is more efficient than rotationEffect.
- Different tween durations (2000, 1500, 8000) desynchronize the animations so the effect never looks repetitive.
- Brush.radialGradient fading to Transparent creates the soft glow edge. A solid circle would look harsh.
- For production: Add a LaunchedEffect with delay() to navigate away after 2-3 seconds, or tie it to a loading state with collectAsState().
Min SDK: 21 | Compose BOM: 2024.01.00+