Imagem do Google

Criando ícones animados no Android

Como criar ícones animados através de imagens vetoriais que irão incrementar a experiência do usuário a partir do Android Lollipop

--

De acordo com as especificações do Material Design:

“Animações podem existir dentro de todos os componentes de um aplicativo e em todas as escalas, desde ícones detalhados a transições-chave e ações.”

Um ícone de menu que suavemente se transforma em uma seta serve para duas funções: informar ao usuário e fasciná-lo quando uma animação é usada além do óbvio.

Ícone de menu que se transforma em uma seta. GIF do Material Design specs
Exemplo de animações vetoriais em ícones. GIF do Material Design specs

Mas antes de nos aprofundarmos nos ícones animados, precisamos entender alguns pontos importantes…

Bitmap x Vetor

Um bitmap representa uma imagem através de uma série de pixels coloridos. Já uma imagem vetorial é representada através de formas geométricas (pontos, linhas e curvas) utilizando cores.

Mas onde isso pode ser útil?

A principal utilidade de uma imagem vetorial é permitir escalar a imagem sem perder definição.

Imagem vetorial à esquerda sendo escalada sem perda de difinição. Imagem bitmap á direita sendo escalada com perda de definição. GIF do 9 basic principles of responsive web design

Um bitmap que foi feito para uma resolução de 100x100 tem uma ótima visualização nesta mesma resolução. Mas se for preciso visualizá-la em uma resolução maior, 500x500 por exemplo, ela terá que ser escalada e sua visualização não ficará muito boa.

Para resolvermos isso, temos uma opção de criar várias versões deste bitmap para cada densidade de tela, fazendo o tamanho do APK (Android Package) ficar cada vez maior.

Diversas versões da imagem bitmap para cada densidade de tela. Imagem do Devices and Displays

Com imagens vetoriais, só precisamos criar o gráfico uma vez e ele será ajustado para as diversas densidades, reduzindo assim o tamanho do APK e simplificando a manutenção.

E onde os ícones animados entram na história?

Através das características do vetor, podemos criar animações que aplicam tranformações em imagens, sem distorcê-las, e ainda ampliar as possibilidades destas transformações.

VectorDrawable

Desde do Android API 21 (hoje nós temos uma Support Library que fornece o suporte a partir do Android API 7 em diante), podemos criar imagens vetoriais mais facilmente através da classe VectorDrawable.

Para criarmos uma imagem vetorial precisamos defini-la em um arquivo de recurso XML dentro da pasta res/drawable/.

O conteúdo do atributo pathData deve estar no padrão especificado para SVG (Scalable Vector Graphics) e é chamado de path.

Exemplo de comandos de um path que representa a imagem de ícone de menu

Neste exemplo são utilizados apenas dois tipos de comandos:

  • moveto, representado pelo M e estabelece um novo ponto de início.
  • lineto, representado pelo L e desenha uma linha do ponto anterior para o novo ponto.

AnimatedVectorDrawable

Com um AnimatedVectorDrawable podemos animar as propriedades de um VectorDrawable, e para isto, basicamente precisamos de três arquivos XML:

  1. Um VectorDrawable <vector> na pasta res/drawable/
  2. Um ou mais ObjectAnimator <objectAnimator> ou AnimatorSet <set> na pasta res/anim/
  3. E um AnimatedVectorDrawable <animated-vector> na pasta res/drawable/

É possível animar atributos de um elemento <group>, <path> ou do próprio <vector>.

Elementos <group> são utilizados para agrupar paths ou subgrupos que precisam ser animados em conjunto.

  1. Quando definimos um VectorDrawable precisamos usar o atributo android:name e definir um nome único nos elementos que queremos animar, para então podermos referenciá-los das definições do Animator. Exemplo:
  • O elemento <group> define um conjunto chamado “rotation”.
  • Já o elemento <path> define as formas geométricas a serem desenhadas cujo nome é “menu”.

2.1. Definições da animação são representadas por objetos ObjectAnimator ou AnimatorSet.

  • Neste exemplo, o Animator rotaciona o alvo em 180 graus com duração de 500 milisegundos.

2.2. O segundo Animator neste exemplo, transforma um path de uma forma para outra. Ambos os paths precisam ser compatíveis para a transformação: Eles devem ter a mesma quantidade de comandos e de parâmetros para cada comando.

Mapeamento da transformação de um path para outro

3. As definições de um AnimatedVectorDrawable servem de ligação entre o VectorDrawable e as definições de animações.

Atualização

Você pode também, definir um VectorDrawable, ObjectAnimator e AnimatedVectorDrawable em um único arquivo. Veja este exemplo.

O AnimatedVectorDrawable é carregado como um Drawable comum, porém, é preciso chamar o método start() para iniciar a animação:

Um vez configurado corretamente, veremos o ícone animar desta forma (a duração da animação foi ampliada para 2 segundos):

Ícone de menu se transformando em uma seta com duração de 2 segundos

Performance

  • Evite usar comandos desnecessários. Simplifique seu path.
  • Limite o tamanho do VectorDrawable. Esses Drawables são primeiro desenhados em um bitmap e depois é feito um upload para uma textura na GPU (unidade de processamento gráfico). Portanto, bitmaps maiores ocuparão mais memória e levarão mais tempo para fazer o upload. É recomendado usar VectorDrawables para ícones e botões pequenos com menos de 200dp.
  • Atualize os atributos de um VectorDrawable somente o necessário. Quando não houver mudança de largura, altura ou opacidade (alpha), o framework será capaz de manter um cache de bitmap sem redesenhar o path ou fazer upload da textura para a GPU. Para o AnimatedVectorDrawable, esta abordagem de cache não ajudará. Portanto, mantenha as animações curtas e simples.

Confira o projeto de exemplo no github:

https://github.com/andremion/Android-Animated-Icons

Exemplo utilizando dois tipos de ícones animados.

Utilize ícones animados com moderação, deixe seu aplicativo mais bonito e forneça ao usuário uma melhor experiência de uso.

Algumas referências e bons artigos (em inglês) sobre isto:

--

--

André Mion
Android Dev BR