Ir al contenido

Splash / Loading

Arrancar la app pasa por dos pantallas de splash distintas, no una: el splash del sistema (obligatorio en Android 12+) y una pantalla de carga propia en Compose.

Wordmark RACING CARDS

1. Splash del sistema (Theme.Act4RacingCards.Starting)

Sección titulada «1. Splash del sistema (Theme.Act4RacingCards.Starting)»
<style name="Theme.Act4RacingCards.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/splash_background</item>
<item name="postSplashScreenTheme">@style/Theme.Act4RacingCards</item>
</style>

Se mantiene deliberadamente mínimo: sólo el color de fondo de marca + el ícono por defecto de la app (sin windowSplashScreenAnimatedIcon personalizado). Es la pantalla que Android dibuja él mismo entre el tap en el ícono y el primer frame de Compose — no se puede eliminar desde Android 12 en adelante, así que se opta por no pelear contra ella.

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
enableEdgeToEdge()
var appReady by mutableStateOf(false)
splashScreen.setKeepOnScreenCondition { !appReady }
// ...
}
}

En cuanto Compose puede dibujar su primer frame, appReady = true libera el splash del sistema y aparece LoadingScreen: el wordmark “RACING CARDS” centrado sobre el mismo color de fondo, durante LOADING_MILLIS = 1100L.

private const val LOADING_MILLIS = 1100L
setContent {
Act4RacingCardsTheme {
var showLoader by remember { mutableStateOf(true) }
LaunchedEffect(Unit) {
appReady = true // entrega el control del splash del sistema
delay(LOADING_MILLIS)
showLoader = false
}
if (showLoader) LoadingScreen() else RacingCardsApp()
}
}
@Composable
fun LoadingScreen(modifier: Modifier = Modifier) {
Box(
modifier = modifier.fillMaxSize().background(colorResource(R.color.splash_background)),
contentAlignment = Alignment.Center,
) {
Image(
painter = painterResource(R.drawable.splash_wordmark),
contentDescription = "Racing Cards",
contentScale = ContentScale.Fit,
modifier = Modifier.fillMaxWidth(0.72f),
)
}
}

R.color.splash_background (#01090D) es la única fuente de verdad para el color de fondo tanto del splash del sistema como de LoadingScreen — cambiar ese único recurso recolorea las dos pantallas a la vez, evitando que se desincronicen visualmente.

Secuencia de arranque

sequenceDiagram
  participant OS as Android (SplashScreen API)
  participant MA as MainActivity
  participant LS as LoadingScreen (Compose)
  participant App as RacingCardsApp

  OS->>MA: tap en el ícono
  OS->>OS: dibuja splash nativo (ic_launcher sobre #01090D)
  MA->>MA: installSplashScreen() + setKeepOnScreenCondition
  MA->>MA: setContent { ... }
  MA->>OS: appReady = true
  OS->>LS: libera el splash nativo, entra LoadingScreen
  LS->>LS: muestra splash_wordmark sobre #01090D (1100ms)
  LS->>App: showLoader = false
  App-->>MA: Gallery visible
Ícono de la app (RC)