Gráficos e animação Android
O Android fornece uma estrutura muito rica e diversificada para suportar gráficos e animações 2D. Este tópico apresenta essas estruturas e discute como criar gráficos e animações personalizados para uso em um aplicativo Xamarin.Android.
Visão geral
Apesar de rodarem em dispositivos tradicionalmente de potência limitada, os aplicativos móveis mais bem avaliados geralmente têm uma Experiência do Usuário (UX) sofisticada, completa com gráficos e animações de alta qualidade que fornecem uma sensação intuitiva, responsiva e dinâmica. À medida que os aplicativos móveis se tornam cada vez mais sofisticados, os usuários começaram a esperar cada vez mais dos aplicativos.
Felizmente para nós, as plataformas móveis modernas têm estruturas muito poderosas para criar animações sofisticadas e gráficos personalizados, mantendo a facilidade de uso. Isso permite que os desenvolvedores adicionem interatividade rica com muito pouco esforço.
As estruturas de API da interface do usuário no Android podem ser divididas em duas categorias: Gráficos e Animação.
Os gráficos são divididos em diferentes abordagens para fazer gráficos 2D e 3D. Os gráficos 3D estão disponíveis através de uma série de frameworks integrados, como o OpenGL ES (uma versão móvel específica do OpenGL), e frameworks de terceiros, como o MonoGame (um kit de ferramentas multiplataforma compatível com o kit de ferramentas XNA). Embora os gráficos 3D não estejam dentro do escopo deste artigo, examinaremos as técnicas de desenho 2D incorporadas.
O Android fornece duas APIs diferentes para criar gráficos 2D. Uma é uma abordagem declarativa de alto nível e a outra uma API programática de baixo nível:
Recursos desenháveis – Eles são usados para criar gráficos personalizados programaticamente ou (mais tipicamente) incorporando instruções de desenho em arquivos XML. Os recursos desenháveis são normalmente definidos como arquivos XML que contêm instruções ou ações para o Android renderizar um gráfico 2D.
Canvas – esta é uma API de baixo nível que envolve desenhar diretamente em um bitmap subjacente. Ele fornece um controle muito refinado sobre o que é exibido.
Além dessas técnicas de gráficos 2D, o Android também fornece várias maneiras diferentes de criar animações:
Animações Desenháveis – O Android também suporta animações quadro a quadro conhecidas como Animação Desenhável. Esta é a API de animação mais simples. O Android carrega e exibe sequencialmente recursos desenháveis em sequência (muito parecido com um desenho animado).
View Animations – View Animations são as APIs de animação originais no Android e estão disponíveis em todas as versões do Android. Essa API é limitada, pois só funcionará com objetos View e só pode executar transformações simples nesses Views. As animações de exibição geralmente são definidas em arquivos XML encontrados na
/Resources/anim
pasta.Animações de propriedade – O Android 3.0 introduziu um novo conjunto de APIs de animação conhecidas como animações de propriedade. Essas novas APIs introduziram um sistema extensível e flexível que pode ser usado para animar as propriedades de qualquer objeto, não apenas Exibir objetos. Essa flexibilidade permite que as animações sejam encapsuladas em classes distintas que facilitarão o compartilhamento de código.
As animações de visualização são mais adequadas para aplicativos que devem oferecer suporte às APIs anteriores ao Android 3.0 (API nível 11). Caso contrário, os aplicativos devem usar as APIs de animação de propriedade mais recentes pelos motivos mencionados acima.
Todas essas estruturas são opções viáveis, no entanto, sempre que possível, deve-se dar preferência às Animações de Propriedade, pois é uma API mais flexível para trabalhar. As animações de propriedade permitem que a lógica de animação seja encapsulada em classes distintas, o que facilita o compartilhamento de código e simplifica a manutenção do código.
Acessibilidade
Gráficos e animações ajudam a tornar os aplicativos Android atraentes e divertidos de usar; No entanto, é importante lembrar que algumas interações ocorrem por meio de leitores de tela, dispositivos de entrada alternativos ou com zoom assistido. Além disso, algumas interações podem ocorrer sem recursos de áudio.
Os aplicativos são mais utilizáveis nessas situações se tiverem sido projetados com a acessibilidade em mente: fornecendo dicas e assistência de navegação na interface do usuário e garantindo que haja conteúdo de texto ou descrições para elementos pictóricos da interface do usuário.
Consulte o Guia de acessibilidade do Google para obter mais informações sobre como utilizar as APIs de acessibilidade do Android.
Gráficos 2D
Recursos Drawable são uma técnica popular em aplicativos Android. Assim como acontece com outros recursos, os Recursos Desenháveis são declarativos – eles são definidos em arquivos XML. Essa abordagem permite uma separação clara do código dos recursos. Isso pode simplificar o desenvolvimento e a manutenção, pois não é necessário alterar o código para atualizar ou alterar os gráficos em um aplicativo Android. No entanto, embora os Recursos Desenháveis sejam úteis para muitos requisitos gráficos simples e comuns, eles não têm o poder e o controle da API do Canvas.
A outra técnica, usando o objeto Canvas , é muito semelhante a outras estruturas de API tradicionais, como System.Drawing ou Core Drawing do iOS. O uso do objeto Canvas fornece o maior controle de como os gráficos 2D são criados. É apropriado para situações em que um recurso sacável não funcionará ou será difícil de trabalhar. Por exemplo, pode ser necessário desenhar um controle deslizante personalizado cuja aparência será alterada com base em cálculos relacionados ao valor do controle deslizante.
Vamos examinar os Recursos Desenháveis primeiro. Eles são mais simples e cobrem os casos de desenho personalizados mais comuns.
Recursos Sacáveis
Recursos desenháveis são definidos em um arquivo XML no diretório /Resources/drawable
. Ao contrário da incorporação de PNG ou JPEG, não é necessário fornecer versões específicas de densidade dos Recursos Desenháveis.
Em tempo de execução, um aplicativo Android carregará esses recursos e usará as instruções contidas nesses arquivos XML para criar gráficos 2D.
O Android define vários tipos diferentes de recursos desenháveis:
ShapeDrawable – Este é um objeto Drawable que desenha uma forma geométrica primitiva e aplica um conjunto limitado de efeitos gráficos nessa forma. Eles são muito úteis para coisas como personalizar Buttons ou definir o plano de fundo de TextViews. Veremos um exemplo de como usar um
ShapeDrawable
mais adiante neste artigo.StateListDrawable – Este é um recurso desenhável que mudará a aparência com base no estado de um widget/controle. Por exemplo, um botão pode alterar sua aparência dependendo se ele é pressionado ou não.
LayerDrawable – Este recurso desenhável que irá empilhar vários outros drawables um em cima do outro. Um exemplo de um LayerDrawable é mostrado na captura de tela a seguir:
TransitionDrawable – Este é um LayerDrawable , mas com uma diferença. Um TransitionDrawable é capaz de animar uma camada aparecendo sobre outra.
LevelListDrawable – Isso é muito semelhante a um StateListDrawable em que ele exibirá uma imagem com base em determinadas condições. No entanto, ao contrário de um StateListDrawable, o LevelListDrawable exibe uma imagem com base em um valor inteiro. Um exemplo de um LevelListDrawable seria exibir a força de um sinal WiFi. À medida que a força do sinal WiFi muda, o desenho que é exibido mudará de acordo.
ScaleDrawable/ClipDrawable – Como o próprio nome indica, esses Drawables fornecem funcionalidade de dimensionamento e recorte. O ScaleDrawable dimensionará outro Drawable, enquanto o ClipDrawable cortará outro Drawable.
InsetDrawable – Este Drawable aplicará inserções nas laterais de outro recurso Drawable. Ele é usado quando um Modo de Exibição precisa de um plano de fundo menor do que os limites reais do Modo de Exibição.
XML BitmapDrawable – Esse arquivo é um conjunto de instruções, em XML, que devem ser executadas em um bitmap real. Algumas ações que o Android pode executar são mosaico, pontilhamento e suavização de serrilhado. Um dos usos muito comuns disso é colocar lado a lado um bitmap no plano de fundo de um layout.
Exemplo desenhável
Vejamos um exemplo rápido de como criar um gráfico 2D usando um ShapeDrawable
arquivo . A ShapeDrawable
pode definir uma das quatro formas básicas: retângulo, oval, linha e anel. Também é possível aplicar efeitos básicos, como gradiente, cor e tamanho. O XML a seguir é um ShapeDrawable
que pode ser encontrado no projeto complementar AnimationsDemo (no arquivo Resources/drawable/shape_rounded_blue_rect.xml
).
Ele define um retângulo com um fundo degradê roxo e cantos arredondados:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!-- Specify a gradient for the background -->
<gradient android:angle="45"
android:startColor="#55000066"
android:centerColor="#00000000"
android:endColor="#00000000"
android:centerX="0.75" />
<padding android:left="5dp"
android:right="5dp"
android:top="5dp"
android:bottom="5dp" />
<corners android:topLeftRadius="10dp"
android:topRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp" />
</shape>
Podemos referenciar esse Recurso Desenhável declarativamente em um Layout ou outro Drawable conforme mostrado no seguinte XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#33000000">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/shape_rounded_blue_rect"
android:text="@string/message_shapedrawable" />
</RelativeLayout>
Recursos desenháveis também podem ser aplicados programaticamente. O trecho de código a seguir mostra como definir programaticamente o plano de fundo de um TextView:
TextView tv = FindViewById<TextView>(Resource.Id.shapeDrawableTextView);
tv.SetBackgroundResource(Resource.Drawable.shape_rounded_blue_rect);
Para ver como isso seria, execute o projeto AnimationsDemo e selecione o item Shape Drawable no menu principal. Devemos ver algo semelhante à seguinte captura de tela:
Para obter mais detalhes sobre os elementos XML e a sintaxe dos Recursos Desenháveis, consulte a documentação do Google.
Usando a API de desenho do Canvas
Os drawables são poderosos, mas têm suas limitações. Certas coisas não são possíveis ou são muito complexas (por exemplo: aplicar um filtro a uma foto que foi tirada por uma câmera no dispositivo). Seria muito difícil aplicar a redução de olhos vermelhos usando um recurso desenhável. Em vez disso, a API do Canvas permite que um aplicativo tenha um controle muito refinado para alterar seletivamente as cores em uma parte específica da imagem.
Uma classe que é comumente usada com o Canvas é a classe Paint . Esta classe contém informações de cor e estilo sobre como desenhar. Ele é usado para fornecer coisas como cor e transparência.
A API do Canvas usa o modelo do pintor para desenhar gráficos 2D. As operações são aplicadas em camadas sucessivas umas sobre as outras. Cada operação cobrirá alguma área do bitmap subjacente. Quando a área se sobrepõe a uma área pintada anteriormente, a nova tinta obscurece parcial ou completamente a antiga. Isso é da mesma forma que muitas outras APIs de desenho, como System.Drawing e Core Graphics do iOS, funcionam.
Há duas maneiras de obter um Canvas
objeto. A primeira maneira envolve definir um objeto Bitmap e, em seguida, instanciar um Canvas
objeto com ele. Por exemplo, o trecho de código a seguir cria uma nova tela com um bitmap subjacente:
Bitmap bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(b);
A outra maneira de obter um Canvas
objeto é pelo método de retorno de chamada OnDraw que é fornecido a classe base View . O Android chama esse método quando decide que um View precisa se desenhar e passa um Canvas
objeto para o View trabalhar.
A classe Canvas expõe métodos para fornecer programaticamente as instruções de desenho. Por exemplo:
Canvas.DrawPaint – Preenche todo o bitmap da tela com a tinta especificada.
Canvas.DrawPath – Desenha a forma geométrica especificada usando a tinta especificada.
Canvas.DrawText – Desenha o texto na tela com a cor especificada. O texto é desenhado no local
x,y
.
Desenhando com a API do Canvas
Aqui está um exemplo da API do Canvas em ação. O trecho de código a seguir mostra como desenhar um modo de exibição:
public class MyView : View
{
protected override void OnDraw(Canvas canvas)
{
base.OnDraw(canvas);
Paint green = new Paint {
AntiAlias = true,
Color = Color.Rgb(0x99, 0xcc, 0),
};
green.SetStyle(Paint.Style.FillAndStroke);
Paint red = new Paint {
AntiAlias = true,
Color = Color.Rgb(0xff, 0x44, 0x44)
};
red.SetStyle(Paint.Style.FillAndStroke);
float middle = canvas.Width * 0.25f;
canvas.DrawPaint(red);
canvas.DrawRect(0, 0, middle, canvas.Height, green);
}
}
Esse código acima primeiro cria uma tinta vermelha e um objeto de pintura verde. Ele preenche o conteúdo da tela com vermelho e, em seguida, instrui a tela a desenhar um retângulo verde que é 25% da largura da tela. Um exemplo disso pode ser visto no AnimationsDemo
projeto que está incluído com o código-fonte deste artigo. Ao iniciar o aplicativo e selecionar o item Desenho no menu principal, devemos uma tela semelhante à seguinte:
Animação
Os usuários gostam de coisas que se movem em seus aplicativos. As animações são uma ótima maneira de melhorar a experiência do usuário de um aplicativo e ajudá-lo a se destacar. As melhores animações são aquelas que os usuários não percebem porque se sentem naturais. O Android fornece as três APIs a seguir para animações:
View Animation – Esta é a API original. Essas animações estão vinculadas a um Modo de Exibição específico e podem executar transformações simples no conteúdo do Modo de Exibição. Devido à sua simplicidade, essa API ainda é útil para coisas como animações alfa, rotações e assim por diante.
Animação de propriedade – As animações de propriedade foram introduzidas no Android 3.0. Eles permitem que um aplicativo anime quase tudo. As animações de propriedade podem ser usadas para alterar qualquer propriedade de qualquer objeto, mesmo que esse objeto não esteja visível na tela.
Animação Desenhável – Este é um recurso especial Desenhável que é usado para aplicar um efeito de animação muito simples aos layouts.
Em geral, a animação de propriedade é o sistema preferido para usar, pois é mais flexível e oferece mais recursos.
Exibir animações
As animações de exibição são limitadas a Modos de Exibição e só podem executar animações em valores como pontos de início e fim, tamanho, rotação e transparência. Esses tipos de animações são normalmente chamados de animações de interpolação. As animações de exibição podem ser definidas de duas maneiras: programaticamente no código ou usando arquivos XML. Os arquivos XML são a maneira preferida de declarar animações de exibição, pois são mais legíveis e fáceis de manter.
Os arquivos XML de animação serão armazenados no /Resources/anim
diretório de um projeto Xamarin.Android. Esse arquivo deve ter um dos seguintes elementos como o elemento raiz :
alpha
– Uma animação fade-in ou fade-out.rotate
– Uma animação de rotação.scale
– Uma animação de redimensionamento.translate
– Um movimento horizontal e/ou vertical.set
– Um contêiner que pode conter um ou mais dos outros elementos de animação.
Por padrão, todas as animações em um arquivo XML serão aplicadas simultaneamente. Para fazer com que as animações ocorram sequencialmente, defina o android:startOffset
atributo em um dos elementos definidos acima.
É possível afetar a taxa de mudança em uma animação usando um interpolador. Um interpolador possibilita que os efeitos de animação sejam acelerados, repetidos ou desacelerados. A estrutura do Android fornece vários interpoladores prontos para uso, como (mas não limitado a):
AccelerateInterpolator
/DecelerateInterpolator
– esses interpoladores aumentam ou diminuem a taxa de mudança em uma animação.BounceInterpolator
– a mudança salta no final.LinearInterpolator
– a taxa de variação é constante.
O XML a seguir mostra um exemplo de um arquivo de animação que combina alguns desses elementos:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android=http://schemas.android.com/apk/res/android
android:shareInterpolator="false">
<scale android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillAfter="false"
android:duration="700" />
<set android:interpolator="@android:anim/accelerate_interpolator">
<scale android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:startOffset="700"
android:duration="400" />
<rotate android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillBefore="false"
android:fillAfter="true"
android:startOffset="700"
android:duration="400" />
</set>
</set>
Esta animação irá executar todas as animações simultaneamente. A animação de primeira escala irá esticar a imagem horizontalmente e reduzi-la verticalmente, e então a imagem será girada simultaneamente 45 graus no sentido anti-horário e encolherá, desaparecendo da tela.
A animação pode ser aplicada programaticamente a um Modo de Exibição inflando a animação e, em seguida, aplicando-a a um Modo de Exibição. O Android fornece a classe Android.Views.Animations.AnimationUtils
auxiliar que inflará um recurso de animação e retornará uma instância do Android.Views.Animations.Animation
. Esse objeto é aplicado a um Modo de Exibição chamando StartAnimation
e passando o Animation
objeto. O trecho de código a seguir mostra um exemplo disso:
Animation myAnimation = AnimationUtils.LoadAnimation(Resource.Animation.MyAnimation);
ImageView myImage = FindViewById<ImageView>(Resource.Id.imageView1);
myImage.StartAnimation(myAnimation);
Agora que temos uma compreensão fundamental de como as animações de exibição funcionam, vamos passar para animações de propriedade.
Animações de propriedade
Os animadores de propriedade são uma nova API que foi introduzida no Android 3.0. Eles fornecem uma API mais extensível que pode ser usada para animar qualquer propriedade em qualquer objeto.
Todas as animações de propriedade são criadas por instâncias da subclasse Animator . Os aplicativos não usam diretamente essa classe, em vez disso, eles usam uma de suas subclasses:
ValueAnimator – Essa classe é a classe mais importante em toda a API de animação de propriedade. Ele calcula os valores das propriedades que precisam ser alteradas. O
ViewAnimator
não atualiza diretamente esses valores, em vez disso, ele gera eventos que podem ser usados para atualizar objetos animados.ObjectAnimator – Esta classe é uma subclasse de
ValueAnimator
. Destina-se a simplificar o processo de animação de objetos, aceitando um objeto de destino e uma propriedade para atualizar.AnimationSet – Esta classe é responsável por orquestrar como as animações são executadas em relação umas às outras. As animações podem ser executadas simultaneamente, sequencialmente ou com um atraso especificado entre elas.
Os avaliadores são classes especiais que são usadas pelos animadores para calcular os novos valores durante uma animação. Fora da caixa, o Android fornece os seguintes avaliadores:
IntEvaluator – Calcula valores para propriedades inteiras.
FloatEvaluator – Calcula valores para propriedades float.
ArgbEvaluator – Calcula valores para propriedades de cor.
Se a propriedade que está sendo animada não for um float
, int
ou cor, os aplicativos podem criar seu próprio avaliador implementando a ITypeEvaluator
interface. (A implementação de avaliadores personalizados está além do escopo deste tópico.)
Usando o ValueAnimator
Há duas partes em qualquer animação: calcular valores animados e, em seguida, definir esses valores em propriedades em algum objeto. O ValueAnimator calculará apenas os valores, mas não operará diretamente em objetos. Em vez disso, os objetos serão atualizados dentro de manipuladores de eventos que serão chamados durante a vida útil da animação. Esse design permite que várias propriedades sejam atualizadas a partir de um valor animado.
Você obtém uma instância de ValueAnimator
chamando um dos seguintes métodos de fábrica:
ValueAnimator.OfInt
ValueAnimator.OfFloat
ValueAnimator.OfObject
Feito isso, a ValueAnimator
instância deve ter sua duração definida e, em seguida, pode ser iniciada. O exemplo a seguir mostra como animar um valor de 0 a 1 durante o período de 1000 milissegundos:
ValueAnimator animator = ValueAnimator.OfInt(0, 100);
animator.SetDuration(1000);
animator.Start();
Mas em si, o trecho de código acima não é muito útil – o animador será executado, mas não há destino para o valor atualizado. A Animator
classe acionará o evento Update quando decidir que é necessário informar os ouvintes de um novo valor. Os aplicativos podem fornecer um manipulador de eventos para responder a esse evento, conforme mostrado no seguinte trecho de código:
MyCustomObject myObj = new MyCustomObject();
myObj.SomeIntegerValue = -1;
animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs e) =>
{
int newValue = (int) e.Animation.AnimatedValue;
// Apply this new value to the object being animated.
myObj.SomeIntegerValue = newValue;
};
Agora que já entendemos o ValueAnimator
, vamos aprender mais sobre o ObjectAnimator
.
Usando o ObjectAnimator
ObjectAnimator é uma subclasse que combina o mecanismo de temporização e o cálculo de valor do ValueAnimator
com a lógica necessária para conectar manipuladores de ViewAnimator
eventos. Os ValueAnimator
aplicativos necessários para conectar explicitamente um manipulador de eventos – ObjectAnimator
cuidarão dessa etapa para nós.
A API para ObjectAnimator
é muito semelhante à API para ViewAnimator
, mas requer que você forneça o objeto e o nome da propriedade a ser atualizada. O exemplo a seguir mostra um exemplo de uso ObjectAnimator
do :
MyCustomObject myObj = new MyCustomObject();
myObj.SomeIntegerValue = -1;
ObjectAnimator animator = ObjectAnimator.OfFloat(myObj, "SomeIntegerValue", 0, 100);
animator.SetDuration(1000);
animator.Start();
Como você pode ver no trecho de código anterior, ObjectAnimator
pode reduzir e simplificar o código necessário para animar um objeto.
Animações Desenháveis
A API de animação final é a API de animação desenhável. As animações desenháveis carregam uma série de recursos desenháveis um após o outro e os exibem sequencialmente, semelhante a um desenho animado flip-it.
Os recursos desenháveis são definidos em um arquivo XML que tem um <animation-list>
elemento como o elemento raiz e uma série de <item>
elementos que definem cada quadro na animação. Esse arquivo XML é armazenado na /Resource/drawable
pasta do aplicativo. O XML a seguir é um exemplo de uma animação desenhável:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/asteroid01" android:duration="100" />
<item android:drawable="@drawable/asteroid02" android:duration="100" />
<item android:drawable="@drawable/asteroid03" android:duration="100" />
<item android:drawable="@drawable/asteroid04" android:duration="100" />
<item android:drawable="@drawable/asteroid05" android:duration="100" />
<item android:drawable="@drawable/asteroid06" android:duration="100" />
</animation-list>
Esta animação será executada através de seis quadros. O android:duration
atributo declara por quanto tempo cada quadro será exibido. O próximo trecho de código mostra um exemplo de criação de uma animação Drawable e iniciá-la quando o usuário clica em um botão na tela:
AnimationDrawable _asteroidDrawable;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
_asteroidDrawable = (Android.Graphics.Drawables.AnimationDrawable)
Resources.GetDrawable(Resource.Drawable.spinning_asteroid);
ImageView asteroidImage = FindViewById<ImageView>(Resource.Id.imageView2);
asteroidImage.SetImageDrawable((Android.Graphics.Drawables.Drawable) _asteroidDrawable);
Button asteroidButton = FindViewById<Button>(Resource.Id.spinAsteroid);
asteroidButton.Click += (sender, e) =>
{
_asteroidDrawable.Start();
};
}
Neste ponto, abordamos os fundamentos das APIs de animação disponíveis em um aplicativo Android.
Resumo
Este artigo introduziu uma série de novos conceitos e APIs para ajudar a adicionar alguns gráficos a um aplicativo Android. Primeiro, discutiu as várias APIs de gráficos 2D e demonstrou como o Android permite que os aplicativos desenhem diretamente para a tela usando um objeto Canvas. Também vimos algumas técnicas alternativas que permitem que gráficos sejam criados declarativamente usando arquivos XML. Em seguida, passamos a discutir as APIs antigas e novas para criar animações no Android.