Visão geral de drawables vetoriais

Um VectorDrawable é um gráfico vetorial definido em um XML file como um conjunto de pontos, linhas e curvas, junto às informações de cor associadas. A principal vantagem de usar um drawable vetorial é a escalonabilidade da imagem. Ela pode ser escalonada sem perder a qualidade de exibição. Isso significa que o mesmo arquivo é redimensionado para diferentes densidades de tela sem perder a qualidade de imagem. Isso resulta em arquivos menores de APK em e menos manutenção para o desenvolvedor. Você também pode usar imagens vetoriais para animação por meio de vários XML files, em vez de usar diversas imagens para cada resolução de tela.

Esta página e o vídeo abaixo trazem uma visão geral de como criar drawables vetoriais em XML. O Android Studio também converte arquivos SVG para o formato de drawable vetorial, conforme descrito em Adicionar gráficos vetoriais de várias densidades.

O Android 5.0 (API nível 21) foi a primeira versão a ser oficialmente compatível com drawables vetoriais com VectorDrawable e AnimatedVectorDrawable. No entanto, é possível usar versões mais antigas com a Biblioteca de Suporte do Android, que oferece as classes VectorDrawableCompat e AnimatedVectorDrawableCompat.

Sobre a classe VectorDrawable

VectorDrawable define um objeto drawable estático. Semelhante ao formato SVG, cada gráfico vetorial é definido como uma hierarquia de árvore, composta pelos objetos path e group. Cada path contém a geometria do contorno do objeto, e group contém detalhes da transformação. Todos os caminhos são desenhados na mesma ordem em que aparecem no XML file.

Figura 1. Amostra de hierarquia de um recurso de drawable vetorial.

A ferramenta Vector Asset Studio oferece uma maneira simples de adicionar um gráfico vetorial ao projeto como XML file.

Exemplo de XML

Veja uma amostra de XML file VectorDrawable que renderiza a imagem de uma bateria no modo de carregamento.

    <!-- res/drawable/battery_charging.xml -->
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        <!-- intrinsic size of the drawable -->
        android:height="24dp"
        android:width="24dp"
        <!-- size of the virtual canvas -->
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
       <group
             android:name="rotationGroup"
             android:pivotX="10.0"
             android:pivotY="10.0"
             android:rotation="15.0" >
          <path
            android:name="vect"
            android:fillColor="#FF000000"
            android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
            android:fillAlpha=".3"/>
          <path
            android:name="draw"
            android:fillColor="#FF000000"
            android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/>
       </group>
    </vector>
    

Esse XML renderiza a seguinte imagem:

Sobre a classe AnimatedVectorDrawable

AnimatedVectorDrawable adiciona animação às propriedades de um gráfico vetorial. Você pode definir um gráfico vetorial animado como três arquivos de recursos diferentes ou como um único XML file que define todo o drawable. Vamos dar uma olhada nas duas abordagens para entender melhor: Vários XML files e XML file único.

Vários XML files

Com essa abordagem, você pode definir três XML files diferentes:

Exemplo de vários XML files

Os seguintes XML files demonstram a animação de um gráfico vetorial.

  • XML file de VectorDrawable: vd.xml
  •     <vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:height="64dp"
           android:width="64dp"
           android:viewportHeight="600"
           android:viewportWidth="600" >
           <group
              android:name="rotationGroup"
              android:pivotX="300.0"
              android:pivotY="300.0"
              android:rotation="45.0" >
              <path
                 android:name="vectorPath"
                 android:fillColor="#000000"
                 android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
           </group>
        </vector>
        
  • XML file de AnimatedVectorDrawable: avd.xml
  •     <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:drawable="@drawable/vd" >
             <target
                 android:name="rotationGroup"
                 android:animation="@anim/rotation" />
             <target
                 android:name="vectorPath"
                 android:animation="@anim/path_morph" />
        </animated-vector>
        
  • XML files do animador usados no XML file de AnimatedVectorDrawable: rotation.xml e path_morph.xml
  •     <objectAnimator
           android:duration="6000"
           android:propertyName="rotation"
           android:valueFrom="0"
           android:valueTo="360" />
        
        <set xmlns:android="http://schemas.android.com/apk/res/android">
           <objectAnimator
              android:duration="3000"
              android:propertyName="pathData"
              android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
              android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
              android:valueType="pathType"/>
        </set>
        

XML file único

Com essa abordagem, você pode mesclar os XML files relacionados em um único XML file por meio do formato de pacote XML. No momento da criação do app, a tag aapt cria recursos diferentes e os referencia no vetor animado. Essa abordagem requer o Build Tools 24 ou posterior, e a saída é compatível com versões anteriores.

Exemplo de um XML file único

    <animated-vector
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt">
        <aapt:attr name="android:drawable">
            <vector
                android:width="24dp"
                android:height="24dp"
                android:viewportWidth="24"
                android:viewportHeight="24">
                <path
                    android:name="root"
                    android:strokeWidth="2"
                    android:strokeLineCap="square"
                    android:strokeColor="?android:colorControlNormal"
                    android:pathData="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7" />
            </vector>
        </aapt:attr>
        <target android:name="root">
            <aapt:attr name="android:animation">
                <objectAnimator
                    android:propertyName="pathData"
                    android:valueFrom="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7"
                    android:valueTo="M6.4,6.4 L17.6,17.6 M6.4,17.6 L17.6,6.4"
                    android:duration="300"
                    android:interpolator="@android:interpolator/fast_out_slow_in"
                    android:valueType="pathType" />
            </aapt:attr>
        </target>
    </animated-vector>
    

Solução de compatibilidade com versões anteriores de drawables vetoriais

Para oferecer compatibilidade com drawables vetoriais e drawables vetoriais animados em dispositivos com versões da plataforma anteriores ao Android 5.0 (API nível 21), VectorDrawableCompat e AnimatedVectorDrawableCompat estão disponíveis por meio de duas Bibliotecas de Suporte: support-vector-drawable e animated-vector-drawable, respectivamente.

O Android Studio 1.4 introduziu compatibilidade limitada para drawables vetoriais gerando arquivos PNG durante a compilação. No entanto, as Bibliotecas de Suporte para drawables vetoriais simples e animados oferecem flexibilidade e ampla compatibilidade. Tratam-se de Bibliotecas de Suporte, o que significa que você pode usá-las em todas as versões da plataforma Android até o Android 2.1 (API de nível 7 ou posterior). Para configurar seu app para usar Bibliotecas de Suporte vetoriais, adicione o elemento vectorDrawables ao seu arquivo build.gradle no módulo do app.

Use o seguinte snippet de código para configurar o elemento vectorDrawables:

    //For Gradle Plugin 2.0+
     android {
       defaultConfig {
         vectorDrawables.useSupportLibrary = true
        }
     }
    
    //For Gradle Plugin 1.5 or below
    android {
      defaultConfig {
        // Stops the Gradle plugin’s automatic rasterization of vectors
        generatedDensities = []
      }
      // Flag notifies aapt to keep the attribute IDs around
      aaptOptions {
        additionalParameters "--no-version-vectors"
      }
    }
     

É possível usar VectorDrawableCompat e AnimatedVectorDrawableCompat em todos os dispositivos com o Android 4.0 (API nível 14) e versões posteriores. A forma como o Android carrega os drawables, não todo lugar que aceita um código drawable, como em um arquivo XML, é compatível com o carregamento de drawables vetoriais. O pacote android.support.v7.appcompat adicionou vários recursos para facilitar o uso de drawables vetoriais. Primeiramente, quando você usa o pacote android.support.v7.appcompat com ImageView ou com subclasses como ImageButton e FloatingActionButton, é possível usar o novo atributo app:srcCompat para referenciar drawables vetoriais, bem como qualquer outro drawable disponível para android:src:

    <ImageView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:srcCompat="@drawable/ic_add" />
    

Para mudar drawables durante a execução, use o método setImageResource() como antes. O uso de AppCompat e app:srcCompat é o método mais seguro de integrar drawables vetoriais ao app.

A Biblioteca de Suporte 25.4.0 e versões posteriores são compatíveis com os seguintes recursos:

  • Transformação de caminhos (avaliador PathType): usado para transformar um caminho em outro.
  • Interpolação de caminho: usado para definir um interpolador flexível (representado como caminho), em vez dos interpoladores definidos pelo sistema, como LinearInterpolator.

A Biblioteca de Suporte 26.0.0-beta1 e versões posteriores são compatíveis com os seguintes recursos:

  • Mover pelo caminho: o objeto de geometria pode ser movido por um caminho arbitrário como parte de uma animação.

Exemplo de vários XML files que usam a Biblioteca de Suporte

Os XML files a seguir demonstram a abordagem do uso de vários XML files para animar um gráfico vetorial.

  • XML file de VectorDrawable: vd.xml
  •     <vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:height="64dp"
           android:width="64dp"
           android:viewportHeight="600"
           android:viewportWidth="600" >
           <group
              android:name="rotationGroup"
              android:pivotX="300.0"
              android:pivotY="300.0"
              android:rotation="45.0" >
              <path
                 android:name="vectorPath"
                 android:fillColor="#000000"
                 android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
           </group>
        </vector>
        
  • XML file de AnimatedVectorDrawable: avd.xml
  •     <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:drawable="@drawable/vd" >
             <target
                 android:name="rotationGroup"
                 android:animation="@anim/rotation" />
        </animated-vector>
        
  • XML file do animador usado no XML file de AnimatedVectorDrawable: rotation.xml
  •     <objectAnimator
           android:duration="6000"
           android:propertyName="rotation"
           android:valueFrom="0"
           android:valueTo="360" />
        

XML file único

O XML file a seguir demonstra a abordagem de usar um único XML file para animar um gráfico vetorial. No momento da criação do app, a tag aapt cria recursos diferentes e os referencia no vetor animado. Essa abordagem requer o Build Tools 24 ou posterior, e a saída é compatível com versões anteriores.

Exemplo de um XML file único que usa a Biblioteca de Suporte

    <animated-vector
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt">
        <aapt:attr name="android:drawable">
            <vector xmlns:android="http://schemas.android.com/apk/res/android"
                android:width="64dp"
                android:height="64dp"
                android:viewportWidth="600"
                android:viewportHeight="600">
                <group
                    android:name="rotationGroup"
                    android:pivotX="300"
                    android:pivotY="300"
                    android:rotation="45.0" >
                    <path
                        android:name="vectorPath"
                        android:fillColor="#000000"
                        android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
                </group>
            </vector>
        </aapt:attr>
        <target android:name="rotationGroup">
            <aapt:attr name="android:animation">
                <objectAnimator
                    android:propertyName="rotation"
                    android:valueFrom="0"
                    android:valueTo="360"
                    android:duration="6000"
                    android:interpolator="@android:interpolator/fast_out_slow_in" />
            </aapt:attr>
        </target>
    </animated-vector>