Lottie no SwiftUI: LottieView, reprodução e loop
Por equipe Charmotion · Atualizado em

Para usar Lottie no SwiftUI, adicione o pacote lottie-spm e escreva LottieView(animation: .named("idle")).looping(). Use .playing(loopMode: .playOnce) para uma reação única, .playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop))) para intervalos e .animationDidFinish para reagir quando ela termina. O Lottie suporta iOS, macOS, tvOS e visionOS, mas não watchOS.
Principais pontos
- Instale a partir de
https://github.com/airbnb/lottie-spm.git: segundo o Airbnb, o clone tem menos de 500 KB, contra mais de 300 MB do repositório principal. LottieViewé uma view do SwiftUI com modificadores encadeáveis:.looping(),.playing(loopMode:),.playbackMode(_:),.resizable().- Marcadores nomeados permitem que um arquivo contenha vários segmentos, que você seleciona com
.marker(_:loopMode:). - Se o arquivo tiver um marcador "reduced motion", o Lottie pode tocá-lo no lugar quando Reduzir Movimento estiver ativado.
- O LottieView não tem state machine com Data Binding; o Rive é a melhor opção para um mascote que reage ao estado do app.
Como instalar o Lottie com o Swift Package Manager?
No Xcode, escolha File → Add Package Dependencies e informe https://github.com/airbnb/lottie-spm.git. O README do Airbnb recomenda esse repositório wrapper para o SwiftPM porque o clone do repositório principal lottie-ios passa de 300 MB, enquanto o lottie-spm tem menos de 500 KB. Adicione a biblioteca Lottie ao target do app e use import Lottie.
Coloque o JSON da animação (ou o arquivo .lottie) no target do app. Por padrão, LottieAnimation.named("idle") procura idle.json no bundle principal.
O manifesto do lottie-spm declara iOS, macOS, tvOS e visionOS. Não há plataforma watchOS, o que importa se você compartilha código de interface com um app para Watch.
Como exibir um LottieView no SwiftUI?
LottieView faz parte do lottie-ios desde a versão 4.3.0. A forma mais simples:
import SwiftUI
import Lottie
struct LoadingMascot: View {
var body: some View {
LottieView(animation: .named("loading"))
.looping()
.resizable()
.scaledToFit()
.frame(width: 180, height: 180)
.accessibilityLabel("Loading")
}
}
.resizable() permite que a animação se ajuste ao frame, como uma Image redimensionável; sem ele, a view usa o tamanho intrínseco da animação. Outros inicializadores incluem LottieView(dotLottieFile:) para arquivos .lottie e variantes com closure assíncrona que carregam uma animação (por exemplo, de uma URL) e mostram um placeholder durante o carregamento.
Uma observação sobre custo: o Lottie renderiza formas vetoriais a cada frame. Para um mascote pequeno em loop, tudo bem; para muitas animações simultâneas em uma lista com rolagem, prefira uma imagem estática na lista e anime só o item em foco.
Como fazer um LottieView rodar em loop ou tocar uma vez?
Os modificadores de reprodução correspondem a LottiePlaybackMode:
// Loop forever
LottieView(animation: .named("idle")).looping()
// Play once and stop on the last frame
LottieView(animation: .named("success")).playing(loopMode: .playOnce)
// Play a progress range on loop
LottieView(animation: .named("idle"))
.playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop)))
// Paused on the current frame
LottieView(animation: .named("idle")).paused(at: .currentFrame)
Para reagir quando uma animação de reprodução única termina, adicione .animationDidFinish { completed in … }. Para reiniciá-la sob demanda, controle o modo de reprodução a partir do estado e altere-o:
struct SaveButton: View {
@State private var playback: LottiePlaybackMode = .paused(at: .progress(0))
var body: some View {
VStack {
LottieView(animation: .named("success"))
.playbackMode(playback)
.animationDidFinish { _ in playback = .paused(at: .progress(0)) }
.frame(width: 120, height: 120)
Button("Save") {
playback = .playing(.fromProgress(0, toProgress: 1, loopMode: .playOnce))
}
}
}
}
Outros modos de loop incluem .autoReverse, .repeat(_:) e .repeatBackwards(_:).
Posso trocar de humor no Lottie sem arquivos separados?
Sim, com marcadores (markers). Se o designer adicionar marcadores nomeados no After Effects ou no Lottie Creator (por exemplo idle, happy, sad), você pode tocar um segmento por vez:
enum Mood: String { case idle, happy, sad }
struct MarkerMascot: View {
let mood: Mood
var body: some View {
LottieView(animation: .named("mascot"))
.playbackMode(.playing(.marker(mood.rawValue, loopMode: .loop)))
.resizable()
.scaledToFit()
}
}
Também existem .fromMarker(_:toMarker:loopMode:) e .markers([…]), que toca vários marcadores em sequência, útil para "reagir e depois voltar ao normal".
A limitação está nas transições. Trocar o marcador corta para o novo segmento onde quer que o anterior estivesse; nada se mistura, a menos que a arte seja feita para que todo segmento comece e termine na mesma pose. É exatamente esse o trabalho que uma state machine faz por você.
Como o LottieView lida com o Reduzir Movimento?
O Lottie 4.3.0 adicionou suporte a movimento reduzido. Se uma animação tiver um marcador chamado reduced motion (o código-fonte também aceita reducedMotion, reduced_motion e reduced-motion), o Lottie toca esse marcador em vez da animação completa quando a opção de movimento reduzido está ativa. Por padrão, ele segue a configuração do sistema.
Se o seu arquivo não tiver esse marcador, trate isso você mesmo:
struct AdaptiveLottie: View {
@Environment(\.accessibilityReduceMotion) private var reduceMotion
var body: some View {
LottieView(animation: .named("idle"))
.playbackMode(reduceMotion ? .paused(at: .progress(0)) : .playing(.fromProgress(0, toProgress: 1, loopMode: .loop)))
.resizable()
.scaledToFit()
}
}
Escolha um frame de pausa que funcione bem como pose parada; o frame 0 costuma ser uma pose neutra, mas nem sempre. Mais padrões: Reduzir Movimento no SwiftUI e no UIKit.
Como controlar um LottieView a partir do estado do app?
Mantenha a decisão no seu modelo e deixe a view escolher a animação. Um enum pequeno mantém os nomes de arquivo em um só lugar e deixa as reações únicas explícitas:
enum UploadState: Equatable {
case idle, uploading, done, failed
var animationName: String {
switch self {
case .idle: return "idle"
case .uploading: return "loading"
case .done: return "success"
case .failed: return "error"
}
}
var loopMode: LottieLoopMode {
switch self {
case .idle, .uploading: return .loop
case .done, .failed: return .playOnce
}
}
}
struct UploadMascot: View {
let state: UploadState
var body: some View {
LottieView(animation: .named(state.animationName))
.playing(loopMode: state.loopMode)
.resizable()
.scaledToFit()
.id(state) // new view per state, so each clip starts from frame 0
.transition(.opacity)
.animation(.easeInOut(duration: 0.2), value: state)
}
}
.id(state) força uma view nova quando o estado muda, o que reinicia a reprodução do começo e permite que um crossfade curto esconda o corte. Sem isso, o SwiftUI pode reutilizar a view e manter o progresso da animação anterior. Se preferir um único arquivo com marcadores, substitua o nome da animação por .playbackMode(.playing(.marker(…, loopMode:))), como mostrado acima.
É aqui também que os limites do Lottie para personagens ficam evidentes: você mesmo está escrevendo a state machine, um switch de cada vez.
Quais plataformas o Lottie suporta?
| Plataforma | lottie-spm | RiveRuntime |
|---|---|---|
| iOS | Yes | 14.0+ |
| macOS | Yes | 13.1+ |
| tvOS | Yes | 16.0+ |
| visionOS | Yes | 1.0+ |
| watchOS | Não declarado | Não declarado |
Confira a lista platforms em cada Package.swift para saber o mínimo exato da versão que você fixar; ele muda entre releases. Nenhum dos pacotes declara watchOS, então o Apple Watch precisa de animadores do SwiftUI ou de frames pré-renderizados; veja Animação de personagens no watchOS e no visionOS.
No visionOS, o LottieView funciona dentro de uma janela SwiftUI comum exatamente como no iPhone. No macOS, o mesmo código SwiftUI compila, e apps AppKit podem usar o LottieAnimationView diretamente. Para telas UIKit no iOS, o LottieAnimationView é a classe de view por trás do LottieView; ela expõe play(), loopMode e animationSpeed como propriedades e métodos.
Quando escolher Rive em vez de Lottie para um mascote?
| Lottie (LottieView) | Rive | |
|---|---|---|
| Formato | JSON ou .lottie, geralmente do After Effects ou do Lottie Creator | .riv binário exportado do editor do Rive |
| Mudar de estado pelo código | Escolher um arquivo, marcador ou intervalo de progresso | Definir um número ou disparar um trigger; a state machine faz a transição |
| Mistura entre estados | Feita à mão; caso contrário, corta | Embutida nas transições da state machine |
| Dados bidirecionais | No | Propriedades de Data Binding e streams de triggers |
| Indicado para | Clipes fixos: animações de carregamento, checks de sucesso, ilustrações | Personagens que reagem ao app |
Muitos apps usam os dois: Lottie para alguns clipes decorativos, Rive para o mascote. Um personagem no Rive com um número mood e triggers substitui o que, de outra forma, seria uma pasta de arquivos Lottie e uma lógica de troca. Veja State machines: Lottie vs Rive para um comparativo mais aprofundado.
Adicione uma animação Lottie em loop a uma view SwiftUI
- Adicione o pacote. No Xcode, adicione
https://github.com/airbnb/lottie-spm.gite vincule a bibliotecaLottie. - Inclua o arquivo no app. Adicione
idle.json(ou um arquivo .lottie) ao target do app. - Exiba a animação. Escreva
LottieView(animation: .named("idle")).looping().resizable().scaledToFit()com um frame. - Trate as reações únicas. Use
.playing(loopMode: .playOnce)e.animationDidFinish, ou controle.playbackModea partir do estado. - Respeite o Reduzir Movimento. Adicione um marcador "reduced motion" ao arquivo ou pause em um frame parado quando
accessibilityReduceMotionfor true.
Perguntas frequentes
Por que usar o lottie-spm em vez do repositório lottie-ios?
Os dois entregam a mesma biblioteca Lottie. A Airbnb recomenda o lottie-spm para o Swift Package Manager porque o repositório principal lottie-ios passa de 300 MB para clonar, enquanto o lottie-spm tem menos de 500 KB, o que torna a resolução de pacotes muito mais rápida no Xcode e no CI.
O LottieView funciona no iOS 13 ou 14?
Confira a lista platforms no Package.swift do lottie-spm para a versão que você fixar, porque os mínimos mudam entre releases. O LottieView em si chegou no lottie-ios 4.3.0. Se o seu deployment target estiver abaixo do que o pacote declara, o Xcode se recusa a resolvê-lo para esse target.
O LottieView consegue tocar um arquivo .lottie (dotLottie)?
Sim. O LottieView tem um inicializador que recebe um DotLottieFile, além de uma variante assíncrona que carrega o arquivo e mostra um placeholder enquanto isso. O dotLottie é um contêiner compactado que pode guardar várias animações e suas imagens em um só arquivo, que costuma ser menor que o JSON equivalente e mantém os assets juntos.
Respostas rápidas deste guia
Fontes
- lottie-ios, Airbnb (GitHub)
- LottieView.swift, Airbnb (GitHub)
- LottiePlaybackMode.swift, Airbnb (GitHub)
- lottie-spm Package.swift, Airbnb (GitHub)
- lottie-ios 4.3.0 release notes, Airbnb (GitHub)
- Lottie for iOS documentation, Airbnb
- rive-ios Package.swift, Rive (GitHub)