• Home

    Escolha seu Plano

    Carreiras Alura

    Evolua com profundidade técnica, direção clara e aplicação prática.

    Jornadas guiadas do básico ao avançado com checkpoints práticos, desenhadas para quem busca profundidade e protagonismo técnico.

    Iniciante

    Comece do zero com uma trilha clara e progressiva.

    Fundamentos práticos para dar os primeiros passos com segurança e construir uma base sólida.

    Intermediário

    Continue sua evolução com cursos que conectam fundamentos, ferramentas e prática profissional. Ganhe autonomia, e avance para projetos mais completos.

    Avançado

    Aprofunde temas técnicos e estratégicos para enfrentar desafios mais complexos. Explore boas práticas, arquitetura, performance com visão profissional.

    Cursos

    Ver mais cursos de Back-end
    • Pensamento computacional: fundamentos da computação e lógica de programação
    • Lógica de programação: mergulhe em programação com JavaScript
    • DDD: fundamentos do design orientado a domínio
    • ASP.NET: autenticação e autorização em APIs e aplicações web
    • Microsserviços: migração de monólitos e modularização

    Cursos

    Ver mais cursos de Dados
    • Python para Dados: primeiros passos
    • Excel: domine o editor de planilhas
    • Engenharia de Dados: Orquestração de Pipelines com Apache Airflow
    • Power BI Desktop: construindo meu primeiro dashboard
    • Governança e Arquitetura de Dados

    Cursos

    Ver mais cursos de Inteligência Artificial
    • IA: Explorando o Potencial da Inteligência Artificial Generativa
    • Engenharia de Prompt: Criando Prompts Eficazes para IA Generativa
    • Claude para Análise de Dados: prompts, integrações e automações
    • Agno: criando agentes e sistemas multiagente
    • Engenharia de software na era da IA: segurança de aplicações com agentes, MCPs e código gerado por IA

    Cursos

    Ver mais cursos de Front-end
    • HTML e CSS: ambiente, estrutura e estilo
    • React: realizando testes avançados com Jest e Testing Library
    • React: integrando TypeScript em projetos
    • JavaScript: aprendendo a programar
    • React: aplicando arquiteturas de Micro frontends

    Cursos

    Ver mais cursos de DevOps
    • Sistema Operacional Linux: fundamentos e administração prática
    • Containers e Docker: empacotamento, isolamento e gestão
    • Redes: dos conceitos iniciais à criação de uma intranet
    • Linux: gerenciando diretórios, arquivos, permissões e processos
    • Cibersegurança: Fundamentos e práticas integradas

    Cursos

    Ver mais cursos de UX & Design
    • UX Research: mapeando a experiência da pessoa usuária
    • UX/UI Design: Entregando produtos digitais com IA
    • UI Design: Prototipação e animações interativas
    • Figma: Conhecendo o programa
    • Product Design: métricas e ciclo de vida do produto

    Cursos

    Ver mais cursos de Gestão & Negócios
    • Canva: Criação de landing pages e e-mail marketing
    • Agilidade: como ela pode ajudar a criar um time de alta performance
    • Google Analytics 4: Extrair insights e configurar eventos
    • Management 3.0: gerencie o ambiente, não as pessoas
    • Automação de processos com n8n: Inteligência de dados para Marketing

    Cursos

    Ver mais cursos de Mobile
    • React Native: Estilização e Layouts com Flexbox e StyleSheet
    • Flutter: Graphql e suporte offline
    • Android com Gemini: Trabalhando com textos e imagens na IA
    • Dart: trabalhando com orientação a objetos
    • React Native: Dominando Listas com FlatList e ScrollView

    Carreiras

    Ver mais carreiras
    • Especialista em IA
    • Engenharia de IA
    • Ai native software engineering
    • Arquitetura de Soluções com IA
    • AI Product Design
    • Engenharia de Machine Learning
    • Desenvolvimento Front-End React
    • Engenharia de Dados
    • Cloud Security
    • Social Media Marketing
    • Engenharia de Agentes de IA

    Cursos

    • Engenharia de Prompt: Prompts Eficazes para IA Generativa
    • Claude Code: Criando sua Primeira Aplicação
    • Python: Crie sua Primeira Aplicação
    • Git e GitHub: Compartilhando e Colaborando
    • N8N: Fluxos de Trabalho Avançados

    Cursos

    • Copilot Studio: Solução Multiagentes
    • Padrões de API HTTP e Modelagem de APIs
    • Python para Análise de Dados com SQL
    • Docker: Criando e Gerenciando Containers
    • Design com IA: Otimizando o Processo Criativo

    Cursos

    • Model Context Protocol (MCP)
    • Spec-Driven Development: Dev Assistido por Agentes
    • Arquitetura de Sistemas Distribuídos com Java
    • Governança de Modelos e Reprodutibilidade
    • Pentest: Vulnerabilidades em Aplicações Web

    Escolha seu Plano

    Skills & Go

    O Skills & Go é para Tech Leads, Product Managers, estrategistas e early adopters que transformam ideias em soluções de alto impacto. Em cursos ao vivo e 100% online, você domina a nova era da IA em tempo real.

    Aulas ao vivo

    Saiba mais
    • Agentic Engineering: orquestre múltiplos agentes com confiabilidade
    • Building AI Products: transforme ideias em produtos reais com IA
    • AI Data Strategy: transforme dados em decisões estratégicas com IA

    Escolha seu Plano

    Eventos Alura

    Nossos eventos são pensados para quem quer estar à frente das mudanças em tecnologia, IA e inovação. Em experiências presenciais, você acompanha tendências e se conecta com especialistas que estão moldando o futuro.

    Próximos eventos

    • Imersão Engenharia de Software: Dev na Era da IA
    • IA Conference
    • Alura Signals
  • Talent Lab
  • IA

    Escolha seu Plano

    Conteúdos gratuitos

    Explore conteúdos gratuitos para aprender tecnologia no seu ritmo. Encontre artigos com conteúdos técnicos para aprender na prática, notícias para acompanhar as principais tendências do mercado e o Alura Labs, com análises e reflexões de especialistas sobre tecnologia, IA e carreira.

    Conteúdos gratuitos

    • Artigos
    • Notícias
    • Alura Labs
  • Para Empresas
Ver planos
Links principais
  • Planos e Promoções
  • Links complementares do menu mobile
  • Talent lab
  • Inteligência Artificial
  • Pós Graduações
  • Para Empresas
  • Sobre a Alura
  • Grupo Alun
  • Entrar
    • Home
    • Carreiras
    • Skills & Go
    • Talent Lab
    • Inteligência Artificial
    • Pós Graduações
    • Artigos
    • Sobre a Alura
    • Grupo Alun
    LoginContato
    • LinkedIn
    • Instagram
    • YouTube
    1. Página inicial
    2. Mobile
    3. Entenda e implemente animações no Flutter

    Entenda e implemente animações no Flutter

    18 min18 minutos de leitura

    18 min18 minutos de leitura

    Publicado: 26/10/2023

    1. Introdução
    2. Animações no Flutter
    3. Animações implícitas
    4. Animações implícitas personalizadas
    5. Animações explícitas
    6. Animações explícitas personalizadas
    7. Pacotes de animação externos
    8. Como escolher uma animação?
    9. Conclusão

    Introdução

    Usar animações em sua aplicação pode ser um diferencial na experiência do usuário, tornando as transições entre telas e elementos mais atraentes e intuitivas, além de geralmente tornar sua aplicação mais bonita. No Flutter existem diversas formas de criar essas animações. Nesse artigo vamos entender o que são animações no Flutter, os tipos de animações e como podemos escolher a melhor opção para cada situação.

    Banner do Guia Tático Alura sobre carreira em tecnologia, destacando o mapa da carreira tech. A imagem convida a explorar diferentes caminhos profissionais, comparar possibilidades e encontrar a próxima fase da carreira na área de tecnologia, com chamada “Explore o mapa”.

    Animações no Flutter

    No Flutter existe suporte para diversos tipos de animações, facilitando a implementação delas em seu projeto, em geral existem algumas categorias de animações, como as:

    • Animações implícitas: São a primeira coisa que procuramos quando precisamos de animações, elas são animações prontas, o Flutter possui uma lista de widgets que pode ser animado dessa forma;
    • Animações implícitas personalizadas: Quando o que precisamos não está na lista de widgets de animação implícita de Flutter, é hora de criar as animações implícitas personalizadas;
    • Animações explícitas: O Flutter também disponibiliza uma série de widgets desse tipo, elas são uma opção quando precisamos obter mais controle sobre as animações ou controlar mais de uma animação ao mesmo tempo, algo que não é possível com animações implícitas;
    • Animações explícitas personalizadas: Quando não existem widgets de animação explícita para o que precisamos, é novamente o momento de criar os seus próprios widgets, e para isso personalizamos as animações com duas classes (AnimatedBuilder e AnimatedWidget);
    • Animações com pacotes externos: Então, se nenhuma das opções acima por possível, se sua animação se parece mais com um desenho, se for muito complexa para transformar em código, existem pacotes para te auxiliar a inserir elas na sua aplicação.

    Vamos conhecer cada um desses tipos e entender quando devemos utilizá-los!

    Animações implícitas

    Os widgets de animação implícita do Flutter geralmente são a primeira opção procurada por nós pessoas programadoras quando queremos adicionar animações nos aplicativos, pois facilitam a criação de uma animação de forma menos complexa. Eles são widgets prontos, com animações que possuem início e fim, e que não se repetem.

    No Flutter existem animações de widgets já existentes, elas são chamadas AnimatedFoo, em que o Foo é o nome do widget que ao ter suas propriedades alteradas é animado automaticamente, veja abaixo alguns dos widgets de animações implícitas:

    • AnimatedAlign: Versão animada do widget Align, em que quando o alinhamento é alterado, é feita uma animação para a nova posição;
    • AnimatedContainer: Versão animada do widget Container, em que as suas propriedades ao serem alteradas, é feita uma animação da mudança;
    • AnimatedCrossFade: Esse widget realiza a mudança entre dois widgets filhos de tamanhos iguais (caso sejam de tamanhos diferentes, o maior é “recortado”), animando a transição entre eles;
    • AnimatedDefaultTextStyle: Versão animada do DefaultTextStyle que faz a animação da mudança de estilo do texto sempre que algo é alterado;
    • AnimatedList: Esse widget possui uma lista de itens e realiza uma animação sempre que um item é adicionado ou removido;
    • AnimatedOpacity: Versão animada do widget Opacity, ele realiza a animação da mudança do valor de opacidade do widget filho;
    • AnimatedPositioned: Versão animada do widget Positioned, em que ao ser alterada a posição é feita uma animação da mudança; e
    • AnimatedSize: Esse widget anima a mudança das propriedades de borderRadius e elevation do filho.

    Ufa! São muitas animações possíveis. Que tal vermos um exemplo de uso do AnimatedContainer para entender como uma animação implícita funciona?

    AnimatedContainer

    O AnimatedContainer é uma versão animada do widget Container que já conhecemos porém quando uma dessas propriedades muda é automaticamente reproduzida uma animação de mudança. Esse widget possui todas as propriedades que um Container poderia ter e também algumas outras relacionadas a animações. Vamos conhecer ele?

    Veja um exemplo de AnimatedContainer cujas propriedades animadas são altura, largura e cor ao apertar um botão:

    GIF colorido. No centro da tela do celular, um quadrado que alterna de forma linear da cor rosa para a cor azul, e vice versa, sempre que um botão com o nome “Aperte” é apertado.

    Como fizemos isso?

    1. Criamos uma variável que é alterada sempre que o botão é apertado;
    2. Usamos ela como flag para alterar as propriedades do container;
    3. Além disso, especificamos uma nova propriedade (que um Container comum não possuiria), a duration, que especifica quanto tempo a interpolação (processo de animação entre o valor antigo e o valor novo) deve durar.
    AnimatedContainer(
      width: _crescer ? 300 : 100,
      height: _crescer ? 300 : 100,
      duration: const Duration(seconds: 1),
      color: _crescer ? Colors.blue : Colors.pink,
    )
    

    Você pode mudar os valores, criar funções que geram valores aleatórios de altura, largura, cores, o próprio decoration, ou seja qualquer propriedade do AnimatedContainer, poderia adicionar um filho ao widget, além de mudar também a duração da animação caso queira uma animação mais lenta ou mais rápida.

    Um exemplo de uso do AnimatedContainer pode ser um campo de texto que se expande com informações ao ser clicado, ou seja, quando a pessoa usuária clica no ícone de seta para baixo, os detalhes são exibidos ou ocultados com uma transição suave.

    A sua criatividade é o limite!

    Curve

    Vimos uma nova propriedade, a duration, que pode ser usada para controlar quanto tempo a interpolação da animação dura. Existe mais uma propriedade importante para conhecer: a curve.

    Curve é uma propriedade que determina como a interpolação deve ser feita. Por padrão, essa propriedade tem valor linear, mas podemos escolher ainda diversas outras opções de como interpolar a animação. Veja um exemplo:

    GIF colorido. No centro da tela do celular, um quadrado que alterna, de forma longa no início e mais rápido no fim, da cor rosa para a cor azul, e vice versa, sempre que um botão com o nome “Aperte” é apertado.

    Agora a animação possui uma interpolação diferente, começando mais lenta e terminando mais rapidamente, para isso apenas adicionamos uma curve do tipo easeInOutQuint. Olha só:

    AnimatedContainer(
      width: _crescer ? 300 : 100,
      height: _crescer ? 300 : 100,
      duration: const Duration(seconds: 1),
      color: _crescer ? Colors.blue : Colors.pink,
      curve: Curves.easeInOutQuint,
    ),
    

    Existem diversas curvas que você pode utilizar, caso tenha interesse a documentação de Flutter sobre Curves detalha todas elas.

    Animações implícitas personalizadas

    Existem muitas animações implícitas integradas no Flutter, contudo quando você pode precisar de alguma animação implícita que não exista na lista de animações prontas do Flutter, você pode criar uma nova, utilizando o TweenAnimationBuilder.

    O TweenAnimationBuilder anima a interpolação entre (tween em inglês) valores e para isso devemos definir duas propriedades principais:

    1. Duração da interpolação;
    2. Intervalo dos valores que desejo animar (pode ser qualquer tipo de valor);
    3. Construtor que retorna o widget que queremos animar.

    No exemplo abaixo estamos animando a mudança de cores (do branco para o azul), com a duração de 2 segundos de interpolação, e o construtor está retornando uma imagem com um filtro de cores.

    GIF colorido. No centro da tela do celular, a imagem de um gato laranja. Um filtro é aplicado na imagem de forma linear, da cor branca para a azul.

    O código para este exemplo fica dessa forma:

    TweenAnimationBuilder<Color?>(
      tween: ColorTween(
        begin: Colors.white,
        end: Colors.blue,
      ),
      duration: const Duration(seconds: 2),
      builder: (_, Color? color, __) {
        return ColorFiltered(
          colorFilter: ColorFilter.mode(
            color ?? Colors.transparent,
            BlendMode.modulate,
          ),
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Image.network(_imagePath),
          ),
        );
      },
    ),
    

    Muito legal! Nesse exemplo não precisamos utilizar o setState para alterar o valor do Tween, mas poderíamos utilizar para modificar esses valores dinamicamente, que tal vermos isso?

    Usando setState para modificar o valor do Tween

    Utilizando agora um widget com estado, podemos alterar o valor do Tween dinamicamente, fazendo com que a mudança de cores e animação, do branco até o azul, agora seja gradual. Para isso, nós vamos:

    1. Utilizar um novo widget chamado Slider (um controle deslizante);
    2. Para usar o Slider, vamos ter mais duas variáveis que serão atualizadas utilizando o setState:
    • 2.1. _newValue: Que deve receber um novo valor (do tipo double) sempre que usamos o Slider;
    • 2.2. _newColor: Que deve receber um novo valor (do tipo Color), variando entre branco e azul e utilizando a variável _newValue para a interpolação.
    1. O valor de _newColor deve ser o valor de end dentro de ColorTween agora.

    GIF colorido. No centro da tela do celular, a imagem de um gato laranja. Um filtro é aplicado na imagem de forma linear, da cor branca para a azul, sempre que uma deslizamos o Slider.

    Dessa maneira, a partir do valor do Slider, atualizamos o valor da nova cor que queremos utilizar, criando um filtro dinâmico para a imagem. Veja o código abaixo:

    double _newValue = 0.0;
    Color? _newColor = Colors.white;
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Center(
              child: TweenAnimationBuilder<Color?>(
                tween: ColorTween(
                  begin: Colors.white,
                  end: _newColor,
                ),
                duration: const Duration(seconds: 2),
                builder: (_, Color? color, __) {
                  return ColorFiltered(
                    colorFilter: ColorFilter.mode(
                      color ?? Colors.transparent,
                      BlendMode.modulate,
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Image.network(_path),
                    ),
                  );
                },
              ),
            ),
            Slider.adaptive(
              value: _newValue,
              onChanged: (double value) {
                setState(() {
                  _newValue = value;
                  _newColor = Color.lerp(
                    Colors.white,
                    Colors.blue,
                    value,
                  );
                });
              },
            ),
          ],
        ),
      );
    }
    

    Muito bem! Aprendemos como fazer uma animação implícita personalizada de maneira dinâmica, e ainda temos algumas propriedades do TweenAnimationBuilder para aprender, são elas: onEnd e Child.

    Propriedade Child

    Vamos começar pelo Child, ele é o filho do TweenAnimationBuilder. Se reparar bem, não precisamos utilizar ele para fazer a animação, contudo poderíamos e seria uma boa escolha pois:

    1. Evitaria reconstruir a imagem a cada vez que o construtor fosse chamado;
    2. A única coisa que precisa ser reconstruída é o filtro de cores;
    3. Otimizamos o desempenho com isso.

    Para usar a propriedade Child:

    1. Passamos um objeto do tipo Widget chamado child (poderia ser qualquer outro nome) no construtor;
    2. Esse objeto deve ser usado no ColorFiltered;
    3. Por fim, passamos a imagem no Child do próprio TweenAnimationBuilder.

    Veja o código abaixo:

    TweenAnimationBuilder<Color?>(
      tween: ColorTween(
        begin: Colors.white,
        end: Colors.blue,
      ),
      duration: const Duration(seconds: 2),
      builder: (_, Color? color, Widget? child) {
        return ColorFiltered(
          colorFilter: ColorFilter.mode(
            color ?? Colors.transparent,
            BlendMode.modulate,
          ),
          child: child,
        );
      },
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Image.network(_imagePath),
      ),
    ),
    

    Essa alteração não deve mudar nada visualmente, mas se o componente animado fosse mais complexo, essa otimização seria importante para a sua aplicação.

    Propriedade onEnd

    Como o nome diz, o parâmetro onEnd é executado no fim da animação. Ele pode ser usado para muitas coisas, podemos fazer um print, por exemplo, mostrar uma mensagem… No nosso exemplo vamos usar para que sempre que chegue ao final da animação, ele volte ao início, dessa maneira:

    GIF colorido. No centro da tela do celular, a imagem de um gato laranja. Um filtro é aplicado na imagem de forma linear, da cor branca para a azul e vice versa.

    Agora sempre que chegamos no fim da a animação, verificamos:

    1. O valor da variável _newValue é azul?
    • 1.1. Se sim, atribuímos a ela a cor branca;
    • 1.2 Se não, atribuímos a cor azul.

    E o código final fica da seguinte forma:

    Color _newColor = Colors.blue;
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Center(
              child: TweenAnimationBuilder<Color?>(
                tween: ColorTween(
                  begin: Colors.white,
                  end: _newColor,
                ),
                duration: const Duration(seconds: 2),
                builder: (_, Color? color, __) {
                  return ColorFiltered(
                    colorFilter: ColorFilter.mode(
                      color ?? Colors.transparent,
                      BlendMode.modulate,
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Image.network(_imagePath),
                    ),
                  );
                },
                onEnd: () {
                  setState(() {
                    if (_newColor == Colors.blue) {
                      _newColor = Colors.white;
                    } else {
                      _newColor = Colors.blue;
                    }
                  });
                },
              ),
            ),
          ],
        ),
      );
    }
    

    Agora conseguimos “rebobinar” a animação, que legal!

    Curve no TweenAnimationBuilder

    A propriedade Curve, que já conhecemos, determina como a interpolação deve ser feita, e ela funciona da mesma maneira com o TweenAnimationBuilder. Portanto, por padrão a animação tem uma interpolação linear, e podemos escolher outros tipos atribuindo uma Curve diferente.

    Para conhecer todas as opções de Curves, veja documentação de Flutter sobre Curves.

    Animações explícitas

    As animações implícitas são mais facilmente utilizadas pois interpolam-se do início ao fim e acabam automaticamente, com o próprio Flutter controlando por nós. Mas e se quisermos ter mais controle sobre as animações? Então podemos utilizar as animações explícitas!

    As animações explícitas possuem algo que as implícitas não poderiam ter (ao menos não sem dar um certo trabalho), elas podem: ser paradas, pausadas e retomadas; podem ser controladas de fato. Os widgets de animação explícita são chamados FooTransition, em que o Foo é o que queremos animar, veja alguns exemplos:

    • DecoratedBoxTransition: Versão animada do widget DecoratedBox, ele anima as várias propriedades de um DecoratedBox;
    • FadeTransition: Anima a opacidade do widget filho;
    • PositionedTransition: Versão animada do widget Positioned, realiza a transição da posição inicial até a final do widget filho;
    • RotationTransition: Esse widget anima a rotação do widget filho;
    • ScaleTransition: Anima a escala do widget filho;
    • SizeTransition: Anima o tamanho, corta e alinha o widget filho; e
    • SlideTransition: Anima a posição de um widget filho em relação à posição normal.

    Que tal vermos um exemplo de RotationTransition para entendermos melhor como uma animação explícita funciona?

    RotationTransition

    O RotationTransition realiza a rotação de um widget filho, veja abaixo um exemplo utilizando um Container como filho:

    GIF colorido. No centro da tela do celular, um quadrado na cor azul que rotaciona no eixo do centro, no sentido horário.

    Ele precisa de três propriedades:

    1. child: Aquilo que ele vai rotacionar;
    2. alignment: O alinhamento do widget, o eixo sobre o qual deve ser realizada a rotação;
    3. turn: Um controlador de animação.

    Vamos entender cada uma dessas propriedades!

    A começar pelo child, para reproduzir o exemplo mostrado, o filho do RotationTransition vai ser um Container, portanto:

    RotationTransition(
      alignment: //...,
      turns: //...,
      child: Container(
        width: 200,
        height: 200,
        color: Colors.blue,
      ),
    ),
    

    O eixo sobre o qual queremos que o widget filho rotacione será o centro, então em alignment usaremos Alignment.center:

    RotationTransition(
      alignment: Alignment.center,
      turns: _animationController,
      child: Container(
        width: 200,
        height: 200,
        color: Colors.blue,
      ),
    ),
    

    Por fim, a propriedade turns recebe um AnimationController, que é o que vai nos dar controle sobre a animação, diferentemente das animações implícitas que são automáticas. Essa uma parte muito importante dos widgets de animação explícita, então daremos uma atenção especial para ela no próximo tópico. Vamos lá?

    AnimationController

    Para começar, vamos criar uma instância de AnimationController:

    late AnimationController _animationController;
    

    Definimos ela como late pois queremos defini-la depois, no initState. E dentro do initState, ao atribuirmos o AnimationController a um objeto, vamos precisar de alguns detalhes para a animação funcionar, são eles:

    1. duration: Especifica a duração da animação.
    2. vsync: Mantem o controle da animação na tela. Ele deve receber o valor this, e para isso precisa utilizar o SingleTickerProviderStateMixin na classe State:
    class _Exemplo1State extends State<Exemplo1>
        with SingleTickerProviderStateMixin {
    	//...
    }
    
    1. repeat: Faz com que a animação se repita continuamente.

    O InitState deve ficar da seguinte maneira:

    @override
    void initState() {
      super.initState();
      _animationController = AnimationController(
        duration: const Duration(seconds: 15),
        vsync: this,
      )..repeat();
    }
    

    Precisamos também fazer o dispose da animação, para liberar o recurso alocado para a animação quando não estivermos mais utilizando ela. Veja:

    @override
    void dispose() {
      _animationController.dispose();
      super.dispose();
    }
    

    Por fim, basta utilizar no RotationTransition o controlador criado e, assim, a animação já deve estar funcionando!

    RotationTransition(
      alignment: Alignment.center,
      turns: _animationController,
      child: Container(
        width: 200,
        height: 200,
        color: Colors.blue,
      ),
    ),
    

    Parando e retomando a animação

    Com o AnimationController, podemos verificar o status da animação, obter informação sobre, além de realizar ações como parar, retroceder e reiniciar a animação. Um exemplo de caso real disso, poderia ser a animação de relógio, que seria pausada ou retomada ao clicar em um botão.

    Abaixo um exemplo de parar e reiniciar a animação criada:

    if (_animationController.isAnimating) {
      _animationController.stop();
    } else {
      _animationController.repeat();
    }
    

    Criei um ElevatedButton para isso e o resultado foi o seguinte:

    GIF colorido. No centro da tela do celular, um quadrado na cor azul que rotaciona no eixo do centro, no sentido horário. Abaixo dele, um botão que ao ser pressionado interrompe a rotação, e ao ser pressionado novamente retoma a rotação.

    Legal! Além de ter uma animação que se repete, também podemos controlar ela realizando ações como parar e retomar.

    Animações explícitas personalizadas

    Já conhecemos os widgets de animação explícita, chamados de FooTransition, mas ainda temos a possibilidade de não encontrar o que queremos dentro daquela lista de widgets prontos, e nesse caso, o que fazemos? Personalizamos as animações explícitas!

    As animações explícitas personalizadas são a solução quando precisamos criar nossas próprias animações, e isso é possível utilizando duas classes: AnimatedBuilder e AnimatedWidget.

    Vamos conhecê-las!

    GIF colorido. No centro da tela do celular, um quadrado na cor lilás que rotaciona no eixo do centro, no sentido horário.

    Para utilizar o AnimatedBuilder vamos precisar de:

    1. animation: Um controlador de animação;
    2. child: É o widget que vamos animar; e
    3. builder: O construtor da animação, ele vai determinar o que deve ser feito.

    A começar pelo animation vamos utilizar o mesmo controlador de animação do exemplo anterior:

    late AnimationController _animationController;
    @override
    void initState() {
      super.initState();
      _animationController = AnimationController(
        duration: const Duration(seconds: 10),
        vsync: this,
      )..repeat();
    }
    @override
    void dispose() {
      _animationController.dispose();
      super.dispose();
    }
    

    O child deve ser um container e estar centralizado, portanto vamos utilizar:

    child: Center(
      child: Container(
        width: 200,
        height: 200,
        color: Colors.purple,
      ),
    ),
    

    E, por fim, o builder deve ser uma função que:

    1. Recebe um contexto e um filho que deve animar;
    2. Retorna uma transformação, que no caso será uma rotação de Child em determinado ângulo, utilizando Transform.rotate.

    Veja:

    builder: (BuildContext context, Widget? child) {
      return Transform.rotate(
        angle: _animationController.value * 2.0 * math.pi,
        child: child,
      );
    },
    

    Ao final, o AnimatedBuilder ficará da seguinte forma:

    AnimatedBuilder(
      animation: _animationController,
      child: Center(
        child: Container(
          width: 200,
          height: 200,
          color: Colors.purple,
        ),
      ),
      builder: (BuildContext context, Widget? child) {
        return Transform.rotate(
          angle: _animationController.value * 2.0 * math.pi,
          child: child,
        );
      },
    ),
    

    Com isso, realizamos a animação de rotação do Container.

    AnimatedWidget

    O AnimatedWidget pode ser visto como uma refatoração do AnimatedBuilder, pois extrai o construtor para um código separado. AnimatedWidget é uma classe abstrata, então podemos criar novos componentes animados, que vão estender dessa classe.

    Portanto, vamos:

    1. Criar uma nova classe, que deve estender da classe abstrata AnimatedWidget;
    2. Ela recebe por parâmetro o controlador de animação;
    3. Ela deve retornar o Transform.rotate, reutilizando o construtor do exemplo anterior de AnimatedBuilder.

    A nova classe (que chamei de ContainerAnimatedExample) ficará da seguinte forma:

    import 'dart:math' as math;
    import 'package:flutter/material.dart';
    class ContainerAnimatedExample extends AnimatedWidget {
      const ContainerAnimatedExample({
        super.key,
        required AnimationController controller,
      }) : super(listenable: controller);
      Animation<double> get _animationController => listenable as Animation<double>;
      @override
      Widget build(BuildContext context) {
        return Transform.rotate(
          angle: _animationController.value * 2.0 * math.pi,
          child: Center(
            child: Container(
              width: 200,
              height: 200,
              color: Colors.purple,
            ),
          ),
        );
      }
    }
    

    E agora o que precisamos é usar a classe de animação separada que criamos na tela da aplicação, passando o controlador de animação do exemplo anterior, o código fica assim:

    class AnimatedWidgetExample extends StatefulWidget {
      const AnimatedWidgetExample({super.key});
      @override
      State<AnimatedWidgetExample> createState() => _AnimatedWidgetExampleState();
    }
    class _AnimatedWidgetExampleState extends State<AnimatedWidgetExample>
        with TickerProviderStateMixin {
      late AnimationController _animationController;
      @override
      void initState() {
        super.initState();
        _animationController = AnimationController(
          duration: const Duration(seconds: 10),
          vsync: this,
        )..repeat();
      }
      @override
      void dispose() {
        _animationController.dispose();
        super.dispose();
      }
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ContainerAnimatedExample(
            controller: _animationController,
          ),
        );
      }
    }
    

    Assim, devemos conseguir exatamente o mesmo resultado do exemplo anterior. Então você pode se perguntar qual devo usar, já que ambos chegam ao mesmo resultado? E na verdade não existe uma resposta correta, segundo a própria documentação de Flutter, é uma questão de gosto.

    Uma vantagem do AnimatedWidget é a possibilidade de separar seus widgets de animação individualmente, porém, se seu código de animação não for muito grande, o AnimatedBuilder pode fazer mais sentido. Caso tenha interesse em ler o artigo que fala sobre isso, deixo ele aqui: “Quando devo usar AnimatedBuilder ou AnimatedWidget?”.

    Pacotes de animação externos

    Até o momento, conhecemos as ferramentas de animações que o próprio Flutter nos proporciona, mas se mesmo com todas elas ainda precisarmos de algo mais, algo que elas não abrangem, recomenda-se o uso de pacotes de animações externos, como Rive e Lottie.

    Rive

    O pacote Rive para Flutter, anteriormente conhecido como Flare, é outra biblioteca que possibilita a incorporação de animações vetoriais diretamente em aplicativos Flutter. Ela oferece uma plataforma de criação e edição de animações vetoriais, permitindo que os desenvolvedores exportem essas animações e as integrem em seus aplicativos Flutter. Essa integração facilita a criação de interfaces de usuário mais dinâmicas e envolventes, enquanto a interface gráfica do Rive oferece uma maneira intuitiva de criar e ajustar animações, tornando o processo de desenvolvimento visualmente orientado e eficiente.

    Lottie

    O pacote Lottie para Flutter é uma biblioteca que permite a integração de animações vetoriais complexas diretamente em aplicativos Flutter. Ele simplifica a incorporação de animações interativas e atraentes. O formato JSON usado pelo Lottie é eficiente e otimizado para desempenho, permitindo uma experiência de usuário suave e responsiva, enquanto o Flutter Lottie oferece uma integração fácil por meio de widgets especializados para reproduzir essas animações vetoriais em aplicativos Flutter.

    Como escolher uma animação?

    Vamos recapitular! Com essa leitura aprendemos principalmente que:

    1. Animação implícita é a porta de entrada para animações, com ela temos diversas formas de animações, chamadas AnimatedFoo;
    2. Animação implícita personalizada é uma forma de criar animações implícitas com o TweenBuilderAnimation, quando as animações implícitas não suprem a sua necessidade;
    3. Animação explícita é uma animação sobre a qual possuímos controle, além de poder ser reproduzida continuamente, diferente das animações implícitas. Com ela temos diversas formas de animações, chamadas FooTransition;
    4. Animação explícita personalizada é a forma de criar suas próprias animações explícitas com AnimatedBuilder ou AnimatedWidget, caso os widgets FooTransition não tenham o que precisa; e
    5. Por fim, caso nenhuma das opções acima seja a melhor para você, o Flutter recomenda uso de pacotes externos como Rive e Lottie.

    Na documentação do Flutter sobre animações é disponibilizado um fluxograma com as perguntas que você deve fazer ao escolher uma animação e as respostas recomendadas, caso queira conferir, deixo aqui o tópico da documentação com o fluxograma.

    Conclusão

    No Flutter existem diversas formas de utilizar ou criar suas animações, sendo elas implícitas, explícitas ou com pacotes externos, e é importante entender sobre elas para aplicar em seu projeto a melhor forma.

    O Flutter possui uma documentação muito boa sobre animações, recomendo a leitura da Introdução a Animações, a qual foi a base deste artigo. Além disso, recomendo também que verifique o Catálogo de Animações do Flutter, com todos os exemplos de animações que ele disponibiliza.

    Espero que tenha gostado da leitura. Bons estudos!

    Banner do Guia Tático Alura sobre carreira em tecnologia, destacando o mapa da carreira tech. A imagem convida a explorar diferentes caminhos profissionais, comparar possibilidades e encontrar a próxima fase da carreira na área de tecnologia, com chamada “Explore o mapa”.

    Avalie este artigo

    • Foto de Jhoisnáyra Vitória Rodrigues de Almeida

      Autor(a)

      Jhoisnáyra Vitória Rodrigues de Almeida

      Scuba Team Mobile (com foco em Flutter). Estudante de Ciência da Computação na UFPI, pesquisadora da área de Internet das Coisas e formada em Eletrônica pelo IFPI.

    Explore por tópico

    • Back-end
    • Dados
    • DevOps
    • Front-end
    • Gestão & Negócios
    • Institucionais
    • Inteligência Artificial
    • Mobile
    • UX & Design

    Leia também

    • 14/12/2021

      React Native: fazendo requisições com Fetch

      Ler mais
    • 20/06/2021

      React Native - O mercado para desenvolvedores júnior

      Ler mais
    • 08/12/2019

      Flutter: como criar um formulário

      Ler mais
    Ver mais conteúdos

    Inscreva-se em nossa Newsletter

    Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.

    Institucional

    • Sobre nós
    • Trabalhe Conosco
    • Para Empresas
    • Para Escolas
    • Política de Privacidade
    • Compromisso de Integridade
    • Termos de Uso
    • Canal de Ética
    • Código de Ética
    • Fale Conosco
    • Documentos Institucionais
    • Status
    Institucional
    • Sobre nós
    • Trabalhe Conosco
    • Para Empresas
    • Para Escolas
    • Política de Privacidade
    • Compromisso de Integridade
    • Termos de Uso
    • Canal de Ética
    • Código de Ética
    • Fale Conosco
    • Documentos Institucionais
    • Status

    A Alura

    • Como Funciona
    • Inteligência Artificial
    • Plataforma
    • Depoimentos
    • Instrutores(as)
    • Dev em <T>
    • Luri, a Inteligência Artificial da Alura
    • IA Conference
    • Cursos Imersivos
    • Perguntas Frequentes
    A Alura
    • Como Funciona
    • Inteligência Artificial
    • Plataforma
    • Depoimentos
    • Instrutores(as)
    • Dev em <T>
    • Luri, a Inteligência Artificial da Alura
    • IA Conference
    • Cursos Imersivos
    • Perguntas Frequentes

    Conteúdos

    • Alura Cases
    • Imersão Engenharia de Software: Dev na Era da IA
    • Artigos
    • Podcasts
    • Artigos de educação corporativa
    Conteúdos
    • Alura Cases
    • Imersão Engenharia de Software: Dev na Era da IA
    • Artigos
    • Podcasts
    • Artigos de educação corporativa
    Uma Empresa do GrupoLogo Grupo Alun

    Outras empresas do Grupo Alun

    • FIAP
    • STARTSE
    • PM3
    • LUMINA

    Ao submeter seu e-mail, você concorda com a política de privacidade da Alura.

    Redes Sociais & Apps

    instagram
    youtube
    tiktok
    x
    appStore
    googlePlay
    Uma Empresa do GrupoLogo Grupo Alun

    Outras empresas do Grupo Alun

    • FIAP
    • STARTSE
    • PM3
    • LUMINA

    Ao submeter seu e-mail, você concorda com a política de privacidade da Alura.

    Redes Sociais & Apps

    instagram
    youtube
    tiktok
    x
    appStore
    googlePlay
    Alura