Capturas de pantalla para la tienda
Propósito
Capturas de pantalla que convierten, son fieles a la aplicación y encajan en cada espacio requerido por las tiendas, producidas mediante un script para que puedan regenerarse en minutos cuando cambia la interfaz.
Requisitos previos
- Una compilación cuya interfaz esté definitiva para esta versión.
- Un harness de captura en la aplicación (pruebas golden/integración de Flutter, XCUITest, pruebas de captura de pantalla de Espresso/Compose o snapshot de Fastlane) que pueda renderizar pantallas con datos de demostración deterministas.
- Node.js 18+ y Chrome/Chromium para el renderizado (
npm ienscripts/). - Credenciales de API (
accounts-and-tax) para la subida.
Principios
- Capturas reales, no maquetas. Cada pantalla de teléfono dentro de un marco es una captura de la aplicación publicada. La interfaz redibujada o "mejorada" engaña (directriz 2.3) y se desactualiza.
- Los números deben coincidir con la aplicación. Si un marco muestra "1.850 pasos" o "12 min", la aplicación debe producir exactamente eso para los datos de demostración. Genera los datos de demostración en el harness y verifícalos en la misma prueba.
- Si una captura muestra algo que la aplicación no hace, corrige uno de los dos. O construye la funcionalidad o cambia el marco. Nunca publiques la discrepancia.
- Ninguna otra plataforma en los marcos. Sin barras de estado/navegación de Android en iOS, sin interfaz de Apple ni "App Store" en Play (2.3.10).
- Mantén el mismo orden de marcos en cada idioma y en cada dispositivo.
Matriz de dispositivos
Tabla completa con tamaños lógicos e identificadores de API: references/device-matrix.md. Resumen (verifica en especificaciones de capturas de Apple y recursos de vista previa de Play):
| Ranura | Píxeles (retrato) | ¿Obligatorio? |
|---|---|---|
| iPhone Dynamic Island grande (6.9") | 1320×2868 (también 1290×2796, 1260×2736) | Conjunto principal recomendado |
| iPhone Dynamic Island mediano | 1206×2622 o 1179×2556 | Al menos una captura obligatoria |
| iPhone Duo pantalla externa | 1398×2034 | Obligatorio a partir de abril de 2027 para aplicaciones compiladas con el SDK de iOS 27.1 o posterior; agrega la insignia "optimizado para iPhone Duo" |
| iPhone Duo pantalla interna | 2007×2853 | Mismo que externa |
| iPad 13" | 2064×2752 (o 2048×2732) | Obligatorio solo si la aplicación se ejecuta en iPad (no para aplicaciones solo iPhone) |
| Play teléfono | ej. 1080×1920 o 1080×2160 (lados 320–3840 px, lado largo ≤ 2× lado corto) | ≥ 2 capturas para publicar; ≥ 4 a ≥ 1080 px recomendado |
| Play tableta 7" y 10" | 1080–7680 px, 9:16 o 16:9 | Recomendado si la aplicación admite tabletas |
| Play gráfico promocional | 1024×500 | Obligatorio |
| Play icono | 512×512, PNG de 32 bits | Obligatorio |
Apple: hasta 10 por tamaño; PNG o JPEG; sin canal alfa ni transparencia. Play: hasta 8 por tipo de dispositivo; JPEG o PNG de 24 bits (sin alfa).
Activos creativos de la página de producto de la App Store (App Store Connect más reciente, pestaña "Encabezado y Resultados de búsqueda"):
- Encabezado: una imagen ancha en la parte superior de la página de producto, 3840×1646 o 5244×2950. Opcional (la presentación se aprueba sin ella).
- Resultados de búsqueda: 5244×2950, 3840×2560 o 1920×1280; si está vacío, se usan capturas de pantalla y vistas previas.
- Carga a través de la página de versión o la Biblioteca de activos (Cargar activos creativos), luego selecciona con Examinar activos. Los activos cargados en la biblioteca permanecen allí para uso futuro.
- Nota de diseño: la tienda superpone el icono, el nombre y el botón Obtener sobre parte del encabezado, así que verifica el resultado en la vista previa de la consola.
- Estas ranuras están bloqueadas mientras la versión está en Esperando revisión. Agrégalas antes de enviar.
Procedimiento
1. Planificar la historia (APROBACIÓN del storyboard)
Escribe un storyboard de 5 a 8 marcos: un título (≤ 6 palabras), una línea de apoyo, una captura cada uno. Diseño "panorámico" opcional (lo que hace la plantilla incluida): los marcos son porciones de un lienzo ancho, por lo que las formas continúan a través de los bordes del marco. Cualquiera que sea el diseño, cualquier oferta mostrada (inicio gratuito, prueba) debe ser real.
2. Capturar pantallas reales
Captura cada pantalla en el tamaño lógico × proporción de píxeles del dispositivo objetivo, para que el texto y el diseño sean exactamente lo que ese dispositivo muestra. Ejemplo de Flutter (prueba widget/golden):
// iPhone 6.9": 440 x 956 puntos lógicos @3x = 1320 x 2868 px
tester.view.physicalSize = const Size(1320, 2868);
tester.view.devicePixelRatio = 3.0;
await tester.pumpWidget(App(demo: DemoData.storeShots(locale: 'en')));
await tester.pumpAndSettle();
expect(find.text('1,850 steps'), findsOneWidget); // el número en el título es real
await expectLater(find.byType(App), matchesGoldenFile('captures/en/iphone69/01_home.png'));
- Carga las fuentes en las pruebas (de lo contrario, la fuente de prueba renderiza cajas).
- Reloj fijo, datos de demostración fijos, sin red.
- Oculta los banners de depuración; establece la barra de estado en un estado limpio (o recórtala y no dibujes ninguna).
- Captura cada idioma por separado; nunca coloques interfaz en inglés dentro de un marco localizado.
3. Componer marcos
Plantilla: templates/panorama.html, renderizador: scripts/render.mjs.
cd scripts && npm i
node render.mjs ../templates/frames.example.json out/
El renderizador coloca todos los marcos en un lienzo (ancho = marcos × ancho del marco), carga las capturas, espera las fuentes y captura cada porción de marco en el tamaño de píxel exacto, para cada dispositivo en la configuración. También renderiza el gráfico promocional de 1024×500.
4. Verificar
node check-images.mjs out/
Falla si: dimensiones incorrectas para el dispositivo de la carpeta, canal alfa presente (tipo de color PNG 4/6 o chunk tRNS), más de 10 (Apple) / 8 (Play) archivos, lagunas en la numeración. Luego mira cada imagen al 100% de zoom: texto cortado, interfaz de otra plataforma, cadenas de marcador de posición, números desactualizados.
5. Subir mediante APIs (APROBACIÓN antes de reemplazar conjuntos en vivo)
- App Store Connect — scripts/upload-asc.mjs: encuentra la
appStoreVersioneditable → susappStoreVersionLocalizations→appScreenshotSetsporscreenshotDisplayType→ elimina capturas antiguas → reserva (POST /v1/appScreenshotsconfileName,fileSize) → sube las partes deuploadOperations→ confirma (PATCHconuploaded: truey el MD5sourceFileChecksum) → establece el orden en la relaciónappScreenshotsdel conjunto. Documentación: Subir activos. - Google Play — scripts/upload-play.mjs:
edits.insert→edits.images.deleteallpor idioma y tipo de imagen →edits.images.uploaden orden (phoneScreenshots,sevenInchScreenshots,tenInchScreenshots,featureGraphic) →edits.commit. Documentación: edits.images.upload.
Ambos scripts tienen modo de prueba predeterminado; establece DRY_RUN=0 para escribir.
6. Leer de vuelta
Lista los activos subidos por idioma y dispositivo (ambas APIs) y compara el recuento y el orden con la carpeta local. Apple procesa las subidas de forma asíncrona; espera hasta que cada activo informe el estado de entrega COMPLETE.
Puntos de decisión que necesitan aprobación humana
Storyboard y títulos, dirección visual final, reemplazo de un conjunto de capturas en vivo, confirmación de la edición de Play.
Verificación
check-images.mjspasa; cada ranura obligatoria de Apple tiene al menos una imagen; Play tiene capturas de teléfono y el gráfico promocional.- El orden de lectura de vuelta coincide; no hay estados de activos fallidos.
- Cada número y funcionalidad en los marcos se verificó con la compilación.
Problemas comunes
- Subir solo la 6.9" y olvidar la ranura obligatoria de Dynamic Island mediana.
- PNG exportados con canal alfa (común desde herramientas de diseño y navegadores sin cabeza con fondos transparentes; siempre establece un fondo de cuerpo opaco).
- Usar la imagen de 6.9" 1320×2868 en Play: su relación de aspecto supera el límite 2:1 de Play; renderiza un tamaño específico para Play.
- Capturas de iPad para una aplicación solo iPhone (no necesarias) — o faltantes cuando la aplicación sí se ejecuta en iPad.
- Un marco que muestra una fila de configuración o resultado que la aplicación no tiene.
- Título traducido pero la captura aún en inglés.