Gráficos y animación de Android
Android proporciona un marco muy abundante y diverso para admitir gráficos y animaciones 2D. En este tema se presentan estos marcos y se describe cómo crear gráficos y animaciones personalizados para su uso en una aplicación de Xamarin.Android.
Información general
A pesar de ejecutarse en dispositivos que tradicionalmente son de potencia limitada, las aplicaciones móviles con mayor calificación suelen tener una experiencia de usuario (UX) sofisticada, completa con gráficos y animaciones de alta calidad que proporcionan una sensación intuitiva, receptiva y dinámica. A medida que las aplicaciones móviles son más sofisticadas, los usuarios han empezado a esperar más y más de las aplicaciones.
Por suerte, las plataformas móviles modernas tienen marcos muy potentes para crear animaciones sofisticadas y gráficos personalizados, a la vez que conservan la facilidad de uso. Esto permite a los desarrolladores agregar mucha interactividad con muy poco esfuerzo.
Los marcos de API de UI en Android se pueden dividir aproximadamente en dos categorías: Gráficos y Animación.
Los gráficos se dividen aún más en diferentes enfoques para realizar gráficos 2D y 3D. Los gráficos 3D están disponibles a través de varios marcos integrados, como OpenGL ES (una versión específica móvil de OpenGL) y marcos de terceros, como MonoGame (un kit de herramientas multiplataforma compatible con el kit de herramientas XNA). Aunque los gráficos 3D no están dentro del ámbito de este artículo, examinaremos las técnicas de dibujo 2D integradas.
Android proporciona dos API diferentes para crear gráficos 2D. Uno es un enfoque declarativo de alto nivel y el otro una API de bajo nivel mediante programación:
Recursos Drawable: se usan para crear gráficos personalizados mediante programación o (más habitualmente) mediante la inserción de instrucciones de dibujo en archivos XML. Los recursos Drawable normalmente se definen como archivos XML que contienen instrucciones o acciones para que Android represente un gráfico 2D.
Canvas: se trata de una API de bajo nivel que implica dibujar directamente en un mapa de bits subyacente. Proporciona un control muy específico sobre lo que se muestra.
Además de estas técnicas de gráficos 2D, Android también proporciona varias formas diferentes de crear animaciones:
Animaciones Drawable: Android también admite animaciones de fotograma a fotograma conocido como Animación Drawable. Esta es la API de animación más sencilla. Android carga secuencialmente y muestra recursos Drawable en secuencia (como un dibujo animado).
Animaciones de vista: Animaciones de vista son las API de animación original en Android y están disponibles en todas las versiones de Android. Esta API está limitada en que solo funcionará con Objetos de vista y solo puede realizar transformaciones simples en esas vistas. Las animaciones de vista normalmente se definen en archivos XML que se encuentran en la carpeta
/Resources/anim
.Animaciones de propiedades: Android 3.0 introdujo un nuevo conjunto de animaciones API conocidas como Animaciones de propiedades. Estas nuevas API introdujeron un sistema extensible y flexible que se puede usar para animar las propiedades de cualquier objeto, no solo para visualizar objetos. Esta flexibilidad permite que las animaciones se encapsulen en clases distintas que facilitarán el uso compartido de código.
Las animaciones de vista son más adecuadas para las aplicaciones que deben admitir las API anteriores a Android 3.0 (nivel de API 11). De lo contrario, las aplicaciones deben usar las API de animación de propiedades más recientes por los motivos mencionados anteriormente.
Todos estos marcos son opciones viables, pero se debe dar preferencia a animaciones de propiedades siempre que sea posible, ya que es una API más flexible con la que trabajar. Las animaciones de propiedad permiten encapsular la lógica de animación en distintas clases que facilitan el uso compartido de código y simplifican el mantenimiento del código.
Accesibilidad
Los gráficos y animaciones ayudan a hacer que las aplicaciones Android sean atractivas y divertidas para su uso. Sin embargo, es importante recordar que algunas interacciones se producen a través de lectores de pantalla, dispositivos de entrada alternativos o con zoom asistido. Además, algunas interacciones pueden producirse sin funcionalidades de audio.
Las aplicaciones se pueden utilizar mejor en estas situaciones si se han diseñado teniendo en cuenta la accesibilidad: proporcionar sugerencias y ayuda de navegación en la interfaz de usuario y asegurarse de que hay contenido de texto o descripciones para los elementos pictóricos de la UI.
Consulte la Guía de accesibilidad de Google para obtener más información sobre cómo usar las API de accesibilidad de Android.
Gráficos 2D
Los recursos Drawable son una técnica popular en aplicaciones Android. Al igual que con otros recursos, los recursos Drawable son declarativos: se definen en archivos XML. Este enfoque permite una separación limpia del código de los recursos. Esto puede simplificar el desarrollo y el mantenimiento ya que no es necesario cambiar el código para actualizar o cambiar los gráficos en una aplicación Android. Sin embargo, aunque los recursos Drawable son útiles para muchos requisitos gráficos simples y comunes, carecen de la potencia y el control de Canvas API.
La otra técnica, con el objeto Canvas, es muy similar a otros marcos de API tradicionales, como System.Drawing o Core Drawing de iOS. El uso del objeto Canvas proporciona el mayor control de cómo se crean los gráficos 2D. Es adecuado para situaciones con las que un recursos Drawable no funcionará o será difícil de trabajar. Por ejemplo, puede ser necesario dibujar un control deslizante personalizado cuya apariencia cambie en función de los cálculos relacionados con el valor del control deslizante.
Examinemos primero los recursos Drawable. Son más sencillos y cubren los casos de dibujo personalizados más comunes.
Recursos Drawable
Los recursos Drawable se definen en un archivo XML del directorio /Resources/drawable
. A diferencia de la inserción de PNG o JPEG, no es necesario proporcionar versiones específicas de densidad de recursos Drawable.
Durante el tiempo de ejecución, una aplicación Android cargará estos recursos y usará las instrucciones contenidas en estos archivos XML para crear gráficos 2D.
Android define varios tipos diferentes de recursos Drawable:
ShapeDrawable: se trata de un objeto Drawable que dibuja una forma geométrica primitiva y aplica un conjunto limitado de efectos gráficos en esa forma. Son muy útiles para personalizar botones o establecer el fondo de TextViews, entre otros. Veremos un ejemplo de cómo usar un elemento
ShapeDrawable
más adelante en este artículo.StateListDrawable: se trata de un recurso Drawable que cambiará la apariencia en función del estado de un widget o control. Por ejemplo, un botón puede cambiar su apariencia en función de si se presiona o no.
LayerDrawable: este recurso Drawable que apilará otros Drawable uno encima de otro. En la captura de pantalla siguiente se muestra un ejemplo de LayerDrawable:
TransitionDrawable: se trata de un LayerDrawable, pero con una diferencia. TransitionDrawable es capaz de animar una capa que se muestra encima de otra.
LevelListDrawable: es muy similar a StateListDrawable en que mostrará una imagen basada en determinadas condiciones. Sin embargo, a diferencia de StateListDrawable, LevelListDrawable muestra una imagen basada en un valor entero. Un ejemplo de LevelListDrawable sería mostrar la intensidad de una señal wifi. A medida que cambia la intensidad de la señal wifi, el Drawable que se muestra cambiará en consecuencia.
ScaleDrawable/ClipDrawable: como su nombre implica, estos Drawables proporcionan funcionalidades de escalado y recorte. ScaleDrawable escalará otro Drawable, mientras que ClipDrawable recortará otro Drawable.
InsetDrawable: este Drawable aplicará conjuntos en los lados de otro recurso Drawable. Se usa cuando una vista necesita un fondo que sea menor que los límites reales de la vista.
BitmapDrawable XML: este archivo es un conjunto de instrucciones, en XML, que se van a realizar en un mapa de bits real. Algunas acciones que Android puede realizar son mosaicos, interpolación de colores y suavizado de contorno. Uno de los usos muy comunes de esto es para crear un mosaico de un mapa de bits en el fondo de un diseño.
Ejemplo de Drawable
Veamos un ejemplo rápido de cómo crear un gráfico 2D mediante ShapeDrawable
. Un ShapeDrawable
puede definir una de las cuatro formas básicas: rectángulo, óvalo, línea y círculo. También es posible aplicar efectos básicos como degradado, color y tamaño. El siguiente XML es un ShapeDrawable
que se puede encontrar en el proyecto complementario AnimationsDemo (en el archivo Resources/drawable/shape_rounded_blue_rect.xml
).
Define un rectángulo con un fondo degradado púrpura y esquinas redondeadas:
<?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 hacer referencia a este recurso Drawable mediante declaración en un diseño u otro Drawable, como se muestra en el siguiente 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>
Los recursos Drawable también se pueden aplicar mediante programación. El siguiente fragmento de código muestra cómo establecer mediante programación el fondo de un TextView:
TextView tv = FindViewById<TextView>(Resource.Id.shapeDrawableTextView);
tv.SetBackgroundResource(Resource.Drawable.shape_rounded_blue_rect);
Para ver lo que tendría este aspecto, ejecute el proyecto AnimationsDemo y seleccione el elemento Drawable de formas en el menú principal. Deberíamos ver algo parecido a la siguiente captura de pantalla:
Para obtener más información sobre los elementos XML y la sintaxis de recursos Drawable, consulte Documentación de Google.
Uso de Canvas Drawing API
Los Drawables son eficaces, pero tienen sus limitaciones. Ciertas cosas son imposibles o muy complejas (por ejemplo, aplicar un filtro a una imagen tomada por una cámara del dispositivo). Sería muy difícil aplicar la reducción de ojos rojos mediante un recurso Drawable. En su lugar, Canvas API permite que una aplicación tenga un control muy específico para cambiar de forma selectiva los colores de una parte específica de la imagen.
Una clase que se usa normalmente con Canvas es la clasePaint. Esta clase contiene información del color y el estilo sobre cómo dibujar. Se usa para proporcionar un color y una transparencia, entre otros.
Canvas API usa el modelo del pintor para dibujar gráficos 2D. Las operaciones se aplican en capas sucesivas entre sí. Cada operación abarcará algún área del mapa de bits subyacente. Cuando el área se superpone a un área previamente pintada, la nueva pintura ocultará la antigua parcial o totalmente. Esta es la misma manera que muchas otras API de dibujo, como System.Drawing y el trabajo de gráficos básicos de iOS.
Hay dos maneras de obtener un objeto Canvas
. La primera forma implica definir un objeto de Mapa de bits y, a continuación, crear instancias de un objeto Canvas
con él. Por ejemplo, el siguiente fragmento de código crea un nuevo lienzo con un mapa de bits subyacente:
Bitmap bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(b);
La otra manera de obtener un objeto Canvas
es mediante el método de devolución de llamada OnDraw que se proporciona a la clase base View. Android llama a este método cuando decide que una vista debe dibujarse y pasar un objeto Canvas
con el que la vista funcione.
La clase Canvas expone métodos para proporcionar mediante programación las instrucciones de dibujo. Por ejemplo:
Canvas.DrawPaint: rellena el mapa de bits del lienzo completo con la pintura especificada.
Canvas.DrawPath: dibuja la forma geométrica especificada utilizando la pintura especificada.
Canvas.DrawText: dibuja el texto en el lienzo con el color especificado. El texto se dibuja en la ubicación
x,y
.
Dibujo con Canvas API
Este es un ejemplo de Canvas API en acción. El siguiente fragmento de código muestra cómo dibujar una vista:
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);
}
}
Este código anterior crea primero una pintura roja y un objeto de pintura verde. Rellena el contenido del lienzo con rojo y después indica al lienzo que dibuje un rectángulo verde que sea el 25 % del ancho del lienzo. En el proyecto AnimationsDemo
se puede ver un ejemplo de esto que se incluye con el código fuente de este artículo. Al iniciar la aplicación y seleccionar el elemento Dibujo en el menú principal, deberíamos ver una pantalla similar a la siguiente:
Animación
A los usuarios les gustan las cosas que se mueven en sus aplicaciones. Las animaciones son una excelente manera de mejorar la experiencia del usuario de una aplicación y ayudarla a destacar. Las mejores animaciones son las que los usuarios no perciben porque se sienten naturales. Android proporciona las tres API siguientes para animaciones:
Ver animación: esta es la API original. Estas animaciones están vinculadas a una vista específica y pueden realizar transformaciones simples en el contenido de la vista. Debido a su simplicidad, esta API sigue siendo útil para cosas como animaciones alfa, rotaciones, etc.
Animación de propiedades: las animaciones de propiedad se introdujeron en Android 3.0. Permiten a una aplicación animar casi cualquier cosa. Las animaciones de propiedad se pueden usar para cambiar cualquier propiedad de cualquier objeto, incluso si ese objeto no es visible en pantalla.
Animación Drawable: este recurso especial Drawable que se usa para aplicar un efecto de animación muy simple a los diseños.
Normalmente, la animación de propiedades es el sistema preferido para usar, ya que es más flexible y ofrece más características.
Ver animaciones
Las animaciones de vista se limitan a Vistas y solo pueden realizar animaciones en valores como puntos de inicio y fin, tamaño, rotación y transparencia. Estos tipos de animaciones se conocen normalmente como animaciones de interpolación. Las animaciones de vista se pueden definir de dos maneras: mediante programación en el código o mediante archivos XML. Los archivos XML son la manera preferida de declarar animaciones de vista, ya que son más legibles y fáciles de mantener.
Los archivos XML de animación se almacenarán en el directorio /Resources/anim
de un proyecto de Xamarin.Android. Este archivo debe tener uno de los siguientes elementos como elemento raíz:
alpha
: Animación de fundido de entrada o salida.rotate
: Animación de rotación.scale
: Animación de cambio de tamaño.translate
: Movimiento horizontal o vertical.set
: Un contenedor que puede contener uno o varios de los otros elementos de animación.
De forma predeterminada, todas las animaciones de un archivo XML se aplicarán simultáneamente. Para que las animaciones se produzcan secuencialmente, establezca el atributo android:startOffset
en uno de los elementos definidos anteriormente.
Es posible afectar a la tasa de cambio en una animación mediante un interpolador. Un interpolador permite acelerar, repetir o ralentizar los efectos de animaciones. El marco de Android proporciona varios interpoladores fuera de la caja, como (pero no limitado a):
AccelerateInterpolator
/DecelerateInterpolator
: estos interpoladores aumentan o reducen la tasa de cambio en una animación.BounceInterpolator
: el cambio rebota al final.LinearInterpolator
: la tasa de cambios es constante.
El siguiente XML muestra un ejemplo de un archivo de animación que combina algunos de estos 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 animación realizará todas las animaciones simultáneamente. La primera animación de escala ajustará la imagen horizontalmente y la reducirá verticalmente y después la imagen se girará simultáneamente 45 grados en sentido contrario a las agujas del reloj y se reducirá, desapareciendo de la pantalla.
La animación se puede aplicar mediante programación a una vista inflando la animación y luego aplicándola a una vista. Android proporciona la clase auxiliar Android.Views.Animations.AnimationUtils
que inflará un recurso de animación y devolverá una instancia de Android.Views.Animations.Animation
. Este objeto se aplica a una vista llamando a StartAnimation
y pasando el objeto Animation
. En el siguiente fragmento de código se muestra un ejemplo:
Animation myAnimation = AnimationUtils.LoadAnimation(Resource.Animation.MyAnimation);
ImageView myImage = FindViewById<ImageView>(Resource.Id.imageView1);
myImage.StartAnimation(myAnimation);
Ahora que tenemos una comprensión fundamental de cómo funcionan las Animaciones de vista, pasemos a las Animaciones de propiedad.
Animaciones de propiedades
Los animadores de propiedades son una nueva API que se introdujo en Android 3.0. Proporcionan una API más extensible que se puede usar para animar cualquier propiedad en cualquier objeto.
Todas las animaciones de propiedad se crean mediante instancias de la subclase Animator. Las aplicaciones no usan directamente esta clase, usan una de sus subclases:
ValueAnimator: esta clase es la clase más importante de toda la API de animación de propiedades. Calcula los valores de las propiedades que deben cambiarse.
ViewAnimator
no actualiza directamente esos valores; en su lugar, genera eventos que se pueden usar para actualizar objetos animados.ObjectAnimator: esta clase es una subclase de
ValueAnimator
. Está diseñado para simplificar el proceso de animación de objetos aceptando un objeto de destino y una propiedad que se van a actualizar.AnimationSet: esta clase es responsable de orquestar cómo se ejecutan las animaciones en relación entre sí. Las animaciones se pueden ejecutar simultáneamente, secuencialmente o con un retraso especificado entre ellas.
Los evaluadores son clases especiales que usan los animadores para calcular los nuevos valores durante una animación. De fábrica, Android proporciona los siguientes evaluadores:
IntEvaluator: calcula los valores de las propiedades de entero.
FloatEvaluator: calcula los valores de las propiedades float.
ArgbEvaluator: calcula los valores de las propiedades de color.
Si la propiedad que se está animando no es un float
, int
o color, las aplicaciones pueden crear su propio evaluador implementando la interfaz ITypeEvaluator
. (La implementación de evaluadores personalizados está fuera del ámbito de este tema).
Uso de ValueAnimator
Hay dos partes en cualquier animación: calcular valores animados y después establecer esos valores en propiedades en algún objeto. ValueAnimator solo calculará los valores, pero no funcionará directamente en objetos. En su lugar, los objetos se actualizarán dentro de los controladores de eventos invocados durante la duración de la animación. Este diseño permite actualizar varias propiedades a partir de un valor animado.
Para obtener una instancia de ValueAnimator
, llame a uno de los métodos de fábrica siguientes:
ValueAnimator.OfInt
ValueAnimator.OfFloat
ValueAnimator.OfObject
Una vez hecho esto, la instancia ValueAnimator
debe tener su duración establecida y podrá iniciarse a continuación. En el ejemplo siguiente se muestra cómo animar un valor de 0 a 1 en el intervalo de 1000 milisegundos:
ValueAnimator animator = ValueAnimator.OfInt(0, 100);
animator.SetDuration(1000);
animator.Start();
Pero en sí mismo, el fragmento de código anterior no es muy útil: el animador se ejecutará, pero no hay ningún destino para el valor actualizado. La clase Animator
generará el evento de actualización cuando decida que es necesario informar a los agentes de escucha de un nuevo valor. Las aplicaciones pueden proporcionar un controlador de eventos para responder a este evento, como se muestra en el siguiente fragmento 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;
};
Ahora que tenemos una comprensión de ValueAnimator
, aprendamos más sobre ObjectAnimator
.
Uso de ObjectAnimator
ObjectAnimator es una subclase de ViewAnimator
que combina el motor de control de tiempo y el cálculo de valores de ValueAnimator
con la lógica necesaria para conectar controladores de eventos. Requiere que las aplicaciones ValueAnimator
conecten explícitamente un controlador de eventos: ObjectAnimator
se encargará de este paso para nosotros.
La API para ObjectAnimator
es muy similar a la API para ViewAnimator
, pero requiere que proporcione el objeto y el nombre de la propiedad que se va a actualizar. En el ejemplo siguiente se muestra un ejemplo de uso de ObjectAnimator
:
MyCustomObject myObj = new MyCustomObject();
myObj.SomeIntegerValue = -1;
ObjectAnimator animator = ObjectAnimator.OfFloat(myObj, "SomeIntegerValue", 0, 100);
animator.SetDuration(1000);
animator.Start();
Como puede ver en el fragmento de código anterior, ObjectAnimator
puede reducir y simplificar el código necesario para animar un objeto.
Animaciones Drawable
La API de animación final es la API de animación Drawable. Las animaciones Drawable cargan una serie de recursos Drawable uno después del otro y los muestran secuencialmente, similar a un dibujo animado invertido.
Los recursos Drawable se definen en un archivo XML que tiene un elemento <animation-list>
como elemento raíz y una serie de elementos <item>
que definen cada fotograma de la animación. Este archivo XML se almacena en la carpeta /Resource/drawable
de la aplicación. El siguiente XML es un ejemplo de una animación Drawable:
<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 animación durará seis fotogramas. El atributo android:duration
declara cuánto tiempo se mostrará cada fotograma. El siguiente fragmento de código muestra un ejemplo de creación de una animación Drawable e iniciándola cuando el usuario hace clic en un botón en la pantalla:
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();
};
}
En este punto hemos tratado los fundamentos de las API de animación disponibles en una aplicación Android.
Resumen
En este artículo se introdujeron muchos conceptos nuevos y API nuevas para ayudar a agregar algunos gráficos a una aplicación Android. En primer lugar, se describen las diversas API de gráficos 2D y se muestra cómo Android permite a las aplicaciones dibujar directamente en la pantalla mediante un objeto Canvas. También vimos algunas técnicas alternativas que permiten crear gráficos mediante declaración mediante archivos XML. A continuación, hemos descrito las API antiguas y nuevas para crear animaciones en Android.