Animaciones y transiciones
SwiftUI anima solo: cambias un estado y describes cómo transicionar. withAnimation, .animation, transiciones y las phase animations modernas.
Animar en SwiftUI es casi mágico: no defines fotogramas ni temporizadores. Cambias un valor de estado dentro de una animación, y SwiftUI interpola suavemente entre el antes y el después. Menos código, mejores resultados.
- Animar cambios de estado con
withAnimation. - El modificador
.animation(_, value:). - Transiciones al aparecer y desaparecer.
- Animaciones por fases (phase animator).
withAnimation: anima un cambio
Envuelve el cambio de estado en withAnimation y todo lo que dependa de ese estado se anima:
struct Caja: View {
@State private var grande = false
var body: some View {
VStack {
RoundedRectangle(cornerRadius: 20)
.frame(width: grande ? 200 : 100, height: 100)
.foregroundStyle(.blue)
Button("Cambiar") {
withAnimation(.spring) { // .spring, .easeInOut, .bouncy…
grande.toggle()
}
}
}
}
}
El rectángulo crece o encoge con una animación de muelle. No animaste el tamaño: animaste el cambio de estado, y SwiftUI hizo el resto.
.animation(_, value:)
Alternativa: adjunta la animación a una vista y dispárala cuando cambie un valor concreto:
Circle()
.fill(activo ? .green : .gray)
.scaleEffect(activo ? 1.2 : 1.0)
.animation(.easeInOut, value: activo) // anima cuando 'activo' cambie
.spring y .bouncy dan sensación viva y natural (ideal para interacciones). .easeInOut es sobrio y elegante. .linear para movimiento constante. Empieza con .spring: es la que mejor sienta a la mayoría de interacciones táctiles, y por algo es la favorita del diseño de Apple.
Transiciones: aparecer y desaparecer
Cuando una vista entra o sale de la jerarquía, .transition define cómo:
if mostrando {
Text("¡Sorpresa!")
.transition(.scale.combined(with: .opacity))
}
// …dispara con:
withAnimation { mostrando.toggle() }
Combina transiciones (.slide, .scale, .opacity, .move(edge:)) para efectos ricos.
Animaciones por fases
Para animaciones que recorren varios estados en bucle (un icono que “respira”, un aviso que pulsa), .phaseAnimator:
Image(systemName: "heart.fill")
.foregroundStyle(.red)
.phaseAnimator([1.0, 1.3, 1.0]) { vista, escala in
vista.scaleEffect(escala)
}
SwiftUI recorre las fases [1.0, 1.3, 1.0] animando entre ellas automáticamente.
El cambio de mentalidad clave: en otros frameworks defines la animación (mueve de X a Y en 0.3s). En SwiftUI defines dos estados (pequeño/grande, visible/oculto) y le dices que la transición entre ellos sea animada. SwiftUI calcula todos los fotogramas intermedios. Esto hace que las animaciones sean interrumpibles y reversibles gratis: si el usuario cambia de idea a mitad, SwiftUI reacciona con fluidez, porque siempre está animando hacia el estado actual, no reproduciendo un guion fijo.
- Haz que una forma cambie de tamaño con
withAnimation(.spring). - Usa
.animation(_, value:)para animar un cambio de color con unToggle. - Muestra/oculta una vista con una
.transitioncombinada. - Aplica un
.phaseAnimatora un icono para que pulse en bucle.