Ilustração com dois iphones sugerindo uma navegação entre telas.

Anime elementos nas telas do seu app no SwiftUI

Animações no SwiftUI

Thierri Cegantin

Criado à 4 meses atrás

Animações deixam qualquer aplicativo com um aspecto mais dinâmico e interativo. Algumas vezes elas até instigam os usuários a fuçarem mais no seu app, saindo apertando todos os botões só para descobrir novas animações.
Felizmente, o SwiftUI tem ferramentas que tornam a implementação de animações um processo muito simples e intuitivo. Em linhas gerais, você vai aplicar uma alteração num elemento e indicar para o compilador que aquela alteração de valores deve ser animada.
Vamos conhecer detalhadamente as ferramentas e alguns exemplos de animações para você usar em seus apps.

With Animation: a maneira mais fácil

Antes de aplicar uma animação é preciso codificar a interação que modifica o elemento. Veja esse exemplo bem simples, onde há um quadrado e dois botões na tela. Aumentar e diminuir seu tamanho.
import SwiftUI 

struct ContentView: View { 
    @State var aresta : CGFloat = 50 // Variável interativa 

    var body: some View { 
        Rectangle() 
            .frame(width: aresta, height: aresta) // Uso da variável 

        HStack{ 
            Text("Diminuir") 
                .onTapGesture { 
                    // Código para REDUZIR o quadrado 
                    aresta = aresta - CGFloat(50) 
                } 

            Text("Aumentar") 
                .onTapGesture { 
                    // Código para AUMENTAR o quadrado 
                    aresta = aresta + CGFloat(50) 
                } 
        }.padding() 
    } 
}

Para deixar o código mais didático foram removidos os Spacer(), responsáveis pelo alinhamento dos elementos.

O resultado obtido é o seguinte:
Sem animação
Note que tudo que foi feito é uma implementação simples que aumenta ou diminui o valor da variável aresta:
aresta = aresta - CGFloat(50) 
E isso faz com que o quadrado aumente ou diminua. Porém sem nenhum tipo de animação. Para adicionar uma animação basta encapsular a linha que altera o valor da variável aresta com o método withAnimation:
withAnimation{ 
    aresta = aresta - CGFloat(50) 
}
Pronto, agora o compilador já sabe que a alteração da variável aresta deverá ser feita com uma animação. O resultado obtido é será:
Sem animação
Caso você use apenas o withAnimation o compilador aplicará uma animação do tipo “spring” (mola, em português). Cada tipo de animação tem uma velocidade, duração e aceleração especificos. A “spring” padrão faz com que o início da animação tenha uma aceleração maior que o fim, fazendo um repouso suave. O gráfico abaixo demonstra a dinâmica da animação padrão.
Uma gráfico demonstrando o progresso da animação padrão.
Você também pode utilizar o método withAnimation passando os parametros da animação. Por exemplo, para aumentar a elasticidade da mola, basta passar um valor para a propriedade bounce da spring. Utilize valores em 0 e 1, sendo 1 uma super elasticidade.
withAnimation(.spring(bounce: 0.9)){ 
    aresta = aresta - CGFloat(50) 
}
Sem animação
Você também pode alterar a propriedade “duration” (duração, em português), para obter animações ainda mais interessantes:
withAnimation(.spring(duration: 0.3, bounce: 0.5)){ 
    aresta = aresta - CGFloat(50) 
}
Sem animação
Apesar de alterarmos o tamanho do quadrado qualquer outra propriedade poderia ser animada. Basta que ela esteja dentro da função withAnimation. Por exemplo, a posição do elemento.
import SwiftUI 

struct ContentView: View { 
    @State var offset : CGFloat = 50 // Variável interativa 

    var body: some View { 
        Rectangle() 
            .frame(width: 100, height: 100) // Uso da variável 
            .offset(y: offset) 

        HStack{ 

            Text("🔽") 
                .onTapGesture { 
                    withAnimation(.spring(duration: 0.3, bounce: 0.5)){ 
                        offset = offset + CGFloat(50) 
                    } 
                } 

            Text("🔼") 
                .onTapGesture { 
                    withAnimation(.spring(duration: 0.3, bounce: 0.5)){ 
                        offset = offset - CGFloat(50) 
                    } 
                } 
        } 
        .padding() 
    } 
}
Sem animação

Use .repeatForever() para uma animação contínua

Caso você queria uma animação contínua é possível utilizar o modificador .repeateForever(). Dessa forma a animação se repetirá numa espécie de “vai e vem”. Veja o exemplo:
withAnimation(.spring(duration: 0.3, bounce: 0.5).repeatForever()){ 
    aresta = aresta - CGFloat(50) 
}
Sem animação

Outra forma de animação: Animated Properties

Outra forma de atingir resultados semelhantes aos que conseguimos utilizando o método withAnimation é utilizando o método animation.
A diferença é que esse método deve ser adicionado no objeto cuja propriedade será animada e não método que modifica a propriedade. Por exemplo, a mesma animação que foi feita anteriormente utilizando o método .animation fica da seguinte forma:
import SwiftUI 

struct ContentView: View { 
    @State var offset : CGFloat = 50 // Variável interativa 

    var body: some View { 
        Rectangle() 
            .frame(width: 100, height: 100) // Uso da variável 
            .offset(y: offset) 
            .animation(.spring, value: offset) 

        HStack{ 
            Text("🔽") 
                .onTapGesture { 
                    offset = offset + CGFloat(50) 
                } 

            Text("🔼") 
                .onTapGesture { 
                    offset = offset - CGFloat(50) 
                } 
        } 
        .padding() 
    } 
}
Note que nos botões que modificam o valor da variável offset não há nenhuma menção a animação. Apenas no retângulo, através da seguinte linha:
.animation(.spring, value: offset)
Todas as modificações que fizemos anteriormente de duração ou elasticidade da mola podem ser feitas no primeiro atributo passado para o método animation. Já o segundo atributo “value” é necessário colocar a variável que deve ser animada.
Dessa forma em qualquer ponto do app que modificarmos a variável offset será sempre feito de maneira animada.

Conclusão

Animações causam um impacto bem interessante no usuário final e felizmente é bem simples de se implementar no SwiftUI. Não deixe de customizar os parâmetros da animação para que ele combine com o contexto do seu aplicativo. Confira também esses outros artigos para enriquecer ainda mais seu conhecimento.

https://developer.apple.com/documentation/swiftui/animations

https://developer.apple.com/videos/play/wwdc2023/10156