Límites de animación en Live Activities, Dynamic Island y widgets
Por el equipo de Charmotion · Actualizado el

Las Live Activities, la Dynamic Island y los widgets no pueden reproducir una animación en loop continua. Desde iOS 17 animan los cambios de datos con transiciones y animaciones de SwiftUI, cada una limitada a dos segundos, y nada se anima en las pantallas Always-On. Para un personaje, cambia entre poses estáticas con una transición cuando cambien los datos, en lugar de reproducir Rive, Lottie, GIF o video.
Puntos clave
- Documentación de WidgetKit de Apple: "Las animaciones en widgets y Live Activities tienen una duración máxima de dos segundos."
- Un ingeniero de DTS de Apple dijo que las animaciones continuas en la Dynamic Island y en widgets no son compatibles y calificó el truco de la fuente de temporizador como un hack no compatible.
- Usa
transition(_:),contentTransition(_:),animation(_:value:)eid(_:);Transactionno está disponible. - Los datos de una Live Activity están limitados a 4 KB, y una actividad puede permanecer activa hasta ocho horas.
- Exporta poses estáticas de tu set de animaciones e inclúyelas como imágenes en la extensión del widget.
¿Una Live Activity o la Dynamic Island pueden reproducir una animación de personaje en loop?
No. El sistema renderiza los widgets y las Live Activities a partir de tu jerarquía de vistas de SwiftUI en el momento de la actualización; tu código no ejecuta un render loop en la pantalla de bloqueo ni en la Dynamic Island. Las animaciones solo ocurren como transición de un estado renderizado al siguiente.
Los desarrolladores preguntan por esto con frecuencia en los foros de Apple. En un hilo sobre cómo animar la Dynamic Island y los widgets, un ingeniero de DTS de Apple respondió que "hay un hack que algunos desarrolladores han descubierto, pero el sistema no lo admite y no se puede recomendar", y que el tipo de animación continua mostrado "no es compatible y puede agotar la batería". El hack en cuestión abusa del texto de temporizador con fuentes personalizadas para simular fotogramas; puede dejar de funcionar en cualquier versión.
Por lo tanto, una mascota de marca no puede tener un loop en reposo (idle), respirar ni parpadear en una Live Activity. Sí puede cambiar de pose, con una transición animada corta, cada vez que tu app o una notificación push actualice la actividad.

¿Qué animaciones admiten los widgets y las Live Activities?
El artículo de Apple "Animating data updates in widgets and Live Activities" enumera lo que funciona. Desde iOS 17, los widgets y las Live Activities "admiten todas las transiciones y animaciones integradas de SwiftUI". En versiones anteriores del sistema, los widgets no se animan, y las Live Activities en iOS 16 o anterior ignoran los modificadores de animación y usan la temporización del sistema, aunque las transiciones integradas siguen aplicándose.
| Compatible | No compatible |
|---|---|
| Transiciones de contenido predeterminadas en texto, imágenes y SF Symbols | Animaciones continuas o repetitivas |
transition(_:): opacity, move(edge:), slide, push(from:) y combinaciones | Transaction (así que no puedes cancelar animaciones con él) |
contentTransition(_:), incluido .numericText(countsDown:) | Animaciones de más de dos segundos |
animation(_:value:) y springs | Cualquier animación en el modo Always-On de baja luminosidad |
id(_:) para animar una vista cuando cambian los datos relacionados | Ejecutar tu propio render loop o temporizadores |
Para desactivar la animación de una vista, Apple indica pasar .identity a transition(_:) o nil a animation(_:value:).
¿Qué es el límite de animación de 2 segundos?
Tanto la documentación de WidgetKit como la sección de Live Activities de las Human Interface Guidelines indican el mismo límite: las animaciones en widgets y Live Activities tienen una duración máxima de dos segundos, ya sean animaciones del sistema o personalizadas.
En la práctica, diseña cada transición para que termine con holgura dentro de ese margen. Un spring con un tiempo de asentamiento largo puede quedar cortado; un .smooth(duration: 0.6) o un .spring(duration: 0.5, bounce: 0.3) cabe cómodamente. Si una actualización cambia varias vistas, Apple sugiere desactivar la animación en las menos importantes para que la atención se centre en el cambio principal.
struct ScoreView: View {
let score: Int
var body: some View {
Text(score, format: .number)
.font(.title.monospacedDigit())
.contentTransition(.numericText())
.animation(.spring(duration: 0.5, bounce: 0.3), value: score)
}
}¿Puedo reproducir GIF, Lottie, Rive o video en un widget?
No como reproducción. El mecanismo compatible son las transiciones y animaciones propias de SwiftUI, que renderiza el sistema; no existe ningún punto de enganche para un reproductor que avance fotogramas con el tiempo. Tanto Rive como Lottie necesitan un loop de renderizado activo, y un widget o una Live Activity no lo ofrecen. La reproducción de GIF y video tampoco forma parte del modelo de animación documentado, y el equipo de DTS de Apple ha calificado la animación continua como no compatible.
Lo que sí puedes hacer con esos recursos es usar un fotograma de ellos. Exporta una imagen fija para cada estado de ánimo a partir de los videos de tu personaje e incluye las imágenes en el catálogo de recursos de la extensión del widget. Con ffmpeg, un fotograma de un WebM con fondo transparente conserva su canal alfa si decodificas con libvpx:
ffmpeg -c:v libvpx-vp9 -i happy.webm -ss 1.0 -frames:v 1 mascot-happy.png
ffmpeg -c:v libvpx-vp9 -i loading.webm -ss 1.0 -frames:v 1 mascot-loading.png
Los sets de Charmotion en los planes de pago incluyen versiones en WebM y MOV transparentes de las 17 animaciones, así que cada estado de ánimo y cada reacción está disponible como fuente para estas imágenes fijas. Redimensiónalas a los tamaños en puntos que realmente muestras; la presentación mínima de una Live Activity, por ejemplo, no debería superar los 45×36.67 puntos.
¿Qué son los límites de 4 KB de datos y de ocho horas?
Según la documentación de ActivityKit de Apple, "Displaying live data with Live Activities":
| Límite | Valor |
|---|---|
| Datos estáticos y dinámicos por actualización (incluidos los payloads push) | 4 KB en total |
| Duración activa | Hasta ocho horas |
| Tiempo total en la pantalla de bloqueo | Hasta 12 horas (ocho activas y hasta cuatro más después de que termina) |
| Imagen de la presentación mínima | No más de 45×36,67 puntos |
| Duración de la animación | Dos segundos como máximo |
Por el límite de 4 KB, las imágenes nunca viajan en el payload. Envía un valor pequeño, como un índice de estado de ánimo, y busca una imagen incluida en el paquete:
import ActivityKit
struct DeliveryAttributes: ActivityAttributes {
struct ContentState: Codable, Hashable {
var mood: Int // 0 idle, 5 loading, 1 happy ...
var minutesLeft: Int
}
var orderNumber: String
}
Las HIG añaden que las Live Activities son adecuadas para tareas que no superan las ocho horas y que, cuando una actividad termina, entre 15 y 30 minutos en la pantalla de bloqueo son suficientes en la mayoría de los casos.
¿Qué pasa en una pantalla Always-On?
En dispositivos con pantalla Always-On, Apple indica que "el sistema no ejecuta animaciones para preservar la batería en Always On". Consulta el valor de entorno isLuminanceReduced (iOS 16 y posteriores) y adapta la vista: omite la transición y muestra una pose más simple y oscura.
struct MascotPose: View {
@Environment(\.isLuminanceReduced) private var isLuminanceReduced
let mood: Int
var body: some View {
Image("mascot-mood-\(mood)")
.resizable()
.scaledToFit()
.opacity(isLuminanceReduced ? 0.6 : 1)
.id(mood)
.transition(isLuminanceReduced ? .identity : .push(from: .bottom))
}
}
Mantén simple el arte para baja luminosidad: las zonas grandes y brillantes se ven molestas en una pantalla de bloqueo atenuada.
¿Cuál es la mejor alternativa a una mascota de marca en loop en una Live Activity?
Cambiar de pose. Trata cada estado de ánimo como una imagen fija y deja que el sistema anime el paso de una a otra cuando cambie el estado. El patrón documentado por Apple para animar una vista cuando cambian otros datos es asociar la vista a esos datos mediante id(_:) y añadir una transición; aquí el estado de ánimo es la identidad:
import SwiftUI
import WidgetKit
struct DeliveryLockScreenView: View {
let state: DeliveryAttributes.ContentState
var body: some View {
HStack(spacing: 12) {
MascotPose(mood: state.mood)
.frame(width: 56, height: 56)
.accessibilityHidden(true)
VStack(alignment: .leading) {
Text("Arriving in")
.font(.caption)
HStack(alignment: .firstTextBaseline, spacing: 4) {
Text(state.minutesLeft, format: .number)
.contentTransition(.numericText(countsDown: true))
Text("min")
}
.font(.title2.bold())
}
}
.padding()
}
}
Así, cada actualización produce un movimiento corto y con sentido: el personaje entra con una pose nueva mientras los minutos avanzan. Asigna los estados de ánimo a las fases de la actividad (en preparación → pose loading, en camino → happy, con retraso → sad, entregado → una pose de éxito) y tendrás un personaje que se siente vivo sin romper las reglas de la plataforma. En la app completa, usa el personaje animado real; la versión con movimiento completo va ahí.

Preguntas frecuentes
¿Puedo animar la Dynamic Island con el truco de la fuente de temporizador?
Se ha hecho, pero un ingeniero de DTS de Apple dijo que el sistema no admite este enfoque, que no se puede recomendar y que las animaciones continuas pueden agotar la batería. Puede dejar de funcionar con cualquier actualización de iOS. Usa en su lugar transiciones compatibles entre actualizaciones de datos.
¿Los widgets se animan en iOS 16?
No. La documentación de Apple indica que en versiones del sistema anteriores a iOS 17 los widgets no se animan. Las Live Activities en iOS 16 ignoran modificadores de animación como animation(_:value:) y usan la temporización del sistema, pero las transiciones integradas como opacity, move, slide y push siguen aplicándose.
¿Puedo enviar una imagen de la mascota en un push de Live Activity?
En la práctica, no. Todos los datos estáticos y dinámicos de una Live Activity, incluidos los payloads push, deben caber en 4 KB en total. Incluye las imágenes de las poses en la extensión del widget y envía solo un valor pequeño, como un número de estado de ánimo, que seleccione qué imagen mostrar.
¿Cuánto puede durar una animación en un widget o una Live Activity?
Dos segundos como máximo. Tanto la documentación de WidgetKit de Apple como las Human Interface Guidelines de Live Activities indican que las animaciones del sistema y personalizadas en widgets y Live Activities tienen una duración máxima de dos segundos. Haz que los springs y las transiciones sean bastante más cortos para que no se corten a mitad del movimiento.
Respuestas rápidas de esta guía
Fuentes
- Animating data updates in widgets and Live Activities, Apple
- Displaying live data with Live Activities, Apple
- Human Interface Guidelines: Live Activities, Apple
- How to use animation for Dynamic Island and widgets?, Apple Developer Forums
- numericText(countsDown:), Apple
- isLuminanceReduced, Apple