Pantalla de Inicio e Íconos de Aplicación en iOS para Flutter
Patrón probado en batalla para aplicaciones Flutter: logotipo de inicio nativo en el primer fotograma, más íconos de pantalla de inicio que siguen Personalizar → Default / Dark / Clear / Tinted en iOS.
Cuándo usarlo
- El arranque en frío muestra una pantalla blanca / marfil vacía antes de que Flutter cargue.
- Se necesitan logotipos de inicio claro + oscuro que sigan la apariencia del sistema (no el ThemeCubit de la app).
- Se necesitan variantes de ícono de aplicación Dark / Tinted / Clear en iOS 18+.
Cuándo no usarlo
- Solo splash de Android / pantalla de inicio dentro de Flutter.
- Cambiar el tema de la app mediante un toggle (HydratedBloc) — eso no controla la pantalla de inicio ni los íconos de SpringBoard.
Reglas críticas (no omitir)
- Los logotipos de inicio deben ser PNG sueltos en el bundle de la aplicación, no en conjuntos de imágenes del catálogo de assets. SplashBoard a menudo falla al cargar
UIImage imageNameddesde Assets.car en la primera instantánea → lienzo blanco durante 2–3 segundos. - No pongas BrandLogo en Assets.xcassets si el mismo nombre base existe como archivo suelto — el catálogo gana y la carga falla.
- Los colores de fondo en LaunchScreen deben ser sRGB explícitos en el storyboard. Los colores nombrados (ej.
LaunchBackground) a menudo fallan al cambiar en la instantánea de inicio. - La clave de variación por rasgo es
userInterfaceStyle=dark(nointerfaceStyle, noluminosity=dark). - Nunca verifiques el inicio copiando un storyboardc independiente de
ibtoolen un.appya construido — eso produce un flash negro. Siempre hazflutter build ios --simulator(o dispositivo) y luego desinstala + reinstala. - No ejecutes
flutter_launcher_iconsdespués de agregar Dark/Tinted — sobrescribeContents.jsony elimina las apariencias. - El ícono de inicio sigue la apariencia del iPhone / Personalizar, no el tema de Flutter. Clear se deriva de Tinted; no hay una ranura Clear separada.
Lista de verificación del flujo de trabajo
Progreso:
- [ ] 1. Generar PNG de inicio claro + nocturno (@1x/@2x/@3x)
- [ ] 2. Copiarlos en ios/Runner/ y agregarlos a Copy Bundle Resources (pbxproj)
- [ ] 3. Eliminar cualquier BrandLogo*.imageset de Assets.xcassets
- [ ] 4. Actualizar LaunchScreen.storyboard (nombres de imagen sueltos + colores explícitos)
- [ ] 5. Opcional: LaunchBackground.colorset solo para traspaso a Main.storyboard / SceneDelegate
- [ ] 6. Generar AppIcon oscuro + tintado 1024 (y tamaños de inicio si se conservan entradas heredadas)
- [ ] 7. Actualizar AppIcon.appiconset/Contents.json con luminosity dark + tinted
- [ ] 8. flutter build ios --simulator --debug
- [ ] 9. simctl uninstall + install; verificar inicio <0.5 s y apariencias de ícono en Assets.car
Paso 1 — Generar logotipos de inicio
Usa scripts/generate_launch_logos.py.
Entradas:
- Logotipo fuente con fondo de estudio oscuro (típicamente
assets/logo/logo.png). - Claro: fondo recortado (knockout) negro → colores de marca de dos tonos preservados.
- Oscuro: misma máscara alfa, dorado sólido
#E0B45D(o primario del proyecto). - Tamaños: 400×363 @1x, 800×727 @2x, 1200×1090 @3x (ajusta la relación de aspecto a tu logotipo).
Fórmula de recorte (coincide con SplashLogo de Flutter si existe):
alpha_out = min(255, 4 * (R + G + B), source_alpha)
Archivos de salida en ios/Runner/:
BrandLogo.png,[email protected],[email protected]BrandLogoNight.png,[email protected],[email protected]
Paso 2 — Recursos del bundle
En ios/Runner.xcodeproj/project.pbxproj:
- Agrega
PBXFileReference+PBXBuildFilepara los seis PNG. - Enlístalos en el grupo Runner y en Copy Bundle Resources.
lastKnownFileType = image.png; entrecomilla las rutas@2x/@3x.
Elimina ios/Runner/Assets.xcassets/BrandLogo.imageset y BrandLogoNight.imageset si existen.
Después de la compilación, confirma:
# BrandLogo NO debe estar en Assets.car; los PNG deben existir en Runner.app
find build/ios/iphonesimulator/Runner.app -name 'BrandLogo*.png'
xcrun assetutil --info build/ios/iphonesimulator/Runner.app/Assets.car | grep -i BrandLogo || true
Paso 3 — LaunchScreen.storyboard
Usa formato IB moderno (toolsVersion ≥ 21701, useTraitCollections, capacidad “documentos guardados en formato Xcode 8”).
Patrón (plantilla completa: references/launch-storyboard.md):
UIImageViewcontentMode="scaleAspectFit", imageBrandLogo.- Variación:
key="userInterfaceStyle=dark" image="BrandLogoNight". - Ancho ≈
0.28–0.40del superview (comienza ~0.32); alto = ancho × relación de aspecto del logotipo. - Restricciones de centro X/Y.
- Fondo claro sRGB explícito (ej. marfil
#FFFCF7). - Variación de fondo oscuro sRGB explícito (ej.
#17120E). <resources>debe declarar ambos nombres de imagen con tamaños intrínsecos.
Info.plist: UILaunchStoryboardName = LaunchScreen.
Paso 4 — Traspaso de Flutter (opcional pero recomendado)
Evita el flash blanco cuando Flutter toma el control:
LaunchBackground.colorsetcon luminosidad claro + oscuro (válido para UI que no es de inicio).- Fondo del VC en Main.storyboard → nombrado
LaunchBackground. - SceneDelegate /
FlutterViewControllerpersonalizado: estableceview.backgroundColorywindow.backgroundColordesdeUIColor(named: "LaunchBackground")enviewDidLoad/viewDidLayoutSubviews.
Paso 5 — Apariencias del ícono de aplicación (iOS 18+)
Genera con scripts/generate_app_icon_variants.py a partir del ícono de marketing 1024 (fondo crema + logotipo).
| Apariencia | Arte |
|---|---|
| Default (Cualquiera) | Ícono claro existente |
| Dark | Logotipo dorado sobre placa oscura (#17120E) o fondo transparente según HIG de Apple |
| Tinted | Escala de grises: logotipo blanco/gris sobre negro (el sistema aplica el tinte) |
| Clear | Derivado automáticamente de Tinted — sin entrada en Contents.json |
Actualiza AppIcon.appiconset/Contents.json — consulta references/appicon-contents.md.
Preferimos entradas universales de tamaño único 1024 con:
"appearances": [{ "appearance": "luminosity", "value": "dark" }]
"appearances": [{ "appearance": "luminosity", "value": "tinted" }]
Conserva las entradas heredadas por tamaño de iPhone si el proyecto aún las usa; agrega oscuro/tintado para 60pt @2x/@3x + marketing 1024 como mínimo.
Validación:
xcrun actool ios/Runner/Assets.xcassets --compile /tmp/icons \
--platform iphonesimulator --minimum-deployment-target 15.0 \
--app-icon AppIcon --output-partial-info-plist /tmp/icon-partial.plist
xcrun assetutil --info /tmp/icons/Assets.car | grep -E 'UIAppearanceDark|ISAppearanceTintable'
La aplicación compilada debe listar AppIcon con UIAppearanceDark e ISAppearanceTintable.
Paso 6 — Verificar en el simulador
flutter build ios --simulator --debug
xcrun simctl uninstall booted <bundle.id>
xcrun simctl install booted build/ios/iphonesimulator/Runner.app
# Iniciar: esperar logotipo alrededor de 0.4–0.5 s (no varios segundos en blanco)
# Ícono: Personalizar → Dark / Tinted; puede necesitar eliminar+reinstalar para el caché de SpringBoard
simctl necesita permisos completos en entornos de agente restringidos.
No hagas rm -rf de los cachés de SplashBoard; desinstalar + reinstalar limpia las instantáneas de inicio.
Valores predeterminados de la marca (anular por proyecto)
| Token | Predeterminado |
|---|---|
| Fondo de inicio claro | #FFFCF7 |
| Fondo de inicio oscuro | #17120E |
| Dorado del logotipo oscuro | #E0B45D |
| Ancho del logotipo de inicio | 32% de la pantalla |
| Placa del ícono oscuro | #17120E |
Pregunta al usuario por los valores hexadecimales de la marca cuando el proyecto difiera.
Recursos adicionales
- Plantilla XML del storyboard: references/launch-storyboard.md
- Formas de Contents.json del AppIcon: references/appicon-contents.md
- Script del logotipo de inicio: scripts/generate_launch_logos.py
- Script de variantes de ícono: scripts/generate_app_icon_variants.py