Resumen del capítulo 22. Animación

Download SampleDescargar el ejemplo

Nota:

Este libro se publicó en la primavera de 2016 y no se ha actualizado desde entonces. Gran parte del libro sigue siendo útil, pero algunos de los materiales están anticuados y algunos temas ya no son completamente correctos o completos.

Ya ha observado que puede crear sus propias animaciones con el temporizador de Xamarin.Forms o Task.Delay, pero generalmente es más fácil usar las prestaciones de animación proporcionadas por Xamarin.Forms. Hay tres clases que implementan estas animaciones:

Por lo general, las animaciones tienen como destino propiedades respaldadas por propiedades enlazables. No se trata de un requisito, pero son las únicas propiedades que reaccionan de forma dinámica a los cambios.

No hay ninguna interfaz XAML para estas animaciones, pero puede integrar animaciones en XAML mediante las técnicas descritas en Capítulo 23. Desencadenadores y comportamientos.

Exploración de las animaciones básicas

Las funciones de animación básicas son métodos de extensión que se encuentran en la clase ViewExtensions. Estos métodos se aplican a cualquier objeto derivado de VisualElement. Las animaciones más sencillas apuntan a las propiedades de transformaciones que se describen en Chapter 21. Transforms.

AnimationTryout muestra cómo el controlador de eventos Clicked de un elemento Button puede llamar al método de extensión RotateTo para girar el botón en un círculo.

El método RotateTo cambia la propiedad Rotation de Button de 0 a 360 en un cuarto de segundo (de forma predeterminada). Sin embargo, si Button se vuelve a pulsar, no hace nada porque la propiedad Rotation ya es 360 grados.

Establecer la duración de la animación

El segundo argumento para RotateTo es una duración en milisegundos. Si se establece en un valor grande, al pulsar en Button durante una animación, se inicia una nueva animación que comienza en el ángulo actual.

Animaciones relativas

El método RelRotateTo realiza una rotación relativa agregando un valor especificado al valor existente. Este método permite que Button se pulse varias veces y, cada vez, aumenta la propiedad Rotation en 360 grados.

Animaciones en espera

Todos los métodos de animación de ViewExtensions devuelven objetos Task<bool>. Esto significa que puede definir una serie de animaciones secuenciales mediante ContinueWith o await. El valor devuelto de finalización bool es false si la animación ha finalizado sin interrupción o true si la ha cancelado el método CancelAnimation, que cancela todas las animaciones iniciadas por el otro método en ViewExtensions que se establecen en el mismo elemento.

Animaciones compuestas

Puede mezclar animaciones esperadas y no esperadas para crear animaciones compuestas. Estas son las animaciones de ViewExtensions que tienen como destino las propiedades de transformación TranslationX, TranslationY y Scale:

Tenga en cuenta que TranslateTo puede afectar a las propiedades TranslationX y TranslationY.

Task.WhenAll y Task.WhenAny

También es posible administrar animaciones simultáneas mediante Task.WhenAll, que indica cuándo se han concluido varias tareas, y Task.WhenAny, que indica cuándo ha concluido la primera de varias tareas.

Rotación y delimitadores

Cuando se llama a los métodos ScaleTo, RelScaleTo, RotateTo y RelRotateTo, se pueden establecer las propiedades AnchorX y AnchorY para indicar el centro del escalado y la rotación.

CircleButton demuestra esta técnica mediante el giro de un elemento Button en torno al centro de la página.

Funciones de aceleración

Por lo general, las animaciones son lineales desde un valor inicial hasta un valor final. Las funciones de aceleración pueden hacer que las animaciones aceleren o ralenticen su curso. El último argumento opcional de los métodos de animación es de tipo Easing, una clase que define 11 campos estáticos de solo lectura de tipo Easing:

El sufijo In indica que el efecto está al principio de la animación, Out significa al final y InOut significa que está al principio y al final de la animación.

En el ejemplo BounceButton se muestra el uso de las funciones de aceleración.

Sus propias funciones de aceleración

También puede definir sus propias funciones de aceleración pasando un elemento Func<double, double> al constructor Easing. Easing también define una conversión implícita de Func<double, double> a Easing. El argumento para la función de aceleración siempre está en el rango de 0 a 1, ya que la animación continúa linealmente desde el principio hasta el final. La función normalmente devuelve un valor en el rango de 0 a 1, pero, durante poco tiempo, podría ser negativo o mayor que 1 (como sucede con las funciones SpringIn y SpringOut) o podría romper las reglas si sabe lo que está haciendo.

En el ejemplo UneasyScale se muestra una función de aceleración personalizada, y CustomCubicEase muestra otra.

En el ejemplo SwingButton también se muestra una función de aceleración personalizada, así como una técnica para cambiar las propiedades AnchorX y AnchorY en una secuencia de animaciones de rotación.

La biblioteca Xamarin.FormsBook.Toolkit tiene una clase JiggleButton que usa una función de aceleración personalizada para mover un botón cuando se hace clic en él. En el ejemplo JiggleButtonDemo se muestra este comportamiento.

Animaciones de entrada

Se produce un tipo popular de animación cuando aparece por primera vez una página. Esta animación se puede iniciar en la anulación del método OnAppearing de la página. Para estas animaciones, lo mejor es configurar el código XAML para el modo en que desea que aparezca la página después de la animación y, a continuación, inicializar y animar el diseño desde el código.

En el ejemplo FadingEntrance se usa el método de extensión FadeTo para atenuar el contenido de la página.

En el ejemplo SlidingEntrance se usa el método de extensión TranslateTo para deslizar el contenido de la página desde los lados.

En el ejemplo SwingingEntrance se usa el método de extensión RotateYTo para animar la propiedad RotationY. También hay disponible un método RotateXTo.

Animaciones indefinidas

En el otro extremo, las animaciones "indefinidas" se ejecutan hasta que finaliza el programa. Por lo general, están pensadas para fines de demostración.

En el ejemplo FadingTextAnimation se usa la animación FadeTo para atenuar dos partes de texto dentro y fuera.

PalindromeAnimation muestra un palíndromo y, a continuación, gira secuencialmente las letras individuales en 180 grados, de modo que estén todas invertidas. A continuación, toda la cadena se voltea 180 grados para leer lo mismo que en la cadena original.

En el ejemplo CopterAnimation, rota un sencillo helicóptero BoxView mientras este gira en torno al centro de la pantalla.

RotatingSpokes gira BoxView radios en torno al centro de la pantalla y, a continuación, gira cada radio para crear patrones interesantes:

Triple screenshot of Rotating Spokes

Sin embargo, el aumento progresivo de la propiedad Rotation de un elemento podría no funcionar a largo plazo, como se muestra en el ejemplo RotationBreakdown.

En el ejemplo SpinningImage se usa RotateToRotateXTo, RotateYToy para que parezca como si un mapa de bits está girando en el espacio 3D.

Animar la propiedad enlazada

El único método de extensión de ViewExtensions que todavía no se ha mostrado es LayoutTo, que anima eficazmente la propiedad Bounds de solo lectura llamando al método Layout. Los derivados Layout normalmente llaman a este método, como se tratará en el Capítulo 26. CustomLayouts.

El método LayoutTo se debe restringir a propósitos especiales. El programa BouncingBox lo usa para comprimir y expandir un elemento BoxView mientras rebota fuera de los lados de una página.

El ejemplo XamagonXuzzle usa LayoutTo para mover iconos en una implementación del rompecabezas clásico de 15-16 que muestra una imagen codificada en lugar de mosaicos numerados:

Triple screenshot of Xamarin Xuzzle

Animaciones propias que admiten await

El ejemplo TryAwaitableAnimation crea una animación que admite await. La clase fundamental que puede devolver un objeto Task desde el método y señalar cuando se completa la animación es TaskCompletionSource.

Animaciones más profundas

El sistema de animación de Xamarin.Forms puede ser un poco confuso. Además de la clase Easing, el sistema de animación consta de las clases ViewExtensions, Animation y AnimationExtension.

Clase ViewExtensions

Ya ha visto ViewExtensions. Define nueve métodos que devuelven Task<bool> y CancelAnimations. Siete de los nueve métodos que tienen como destino las propiedades de transformación. Los otros dos son FadeTo, que tiene como destino la propiedad Opacity, y LayoutTo, que llama al método Layout.

Clase Animation

La clase Animation tiene un constructor con cinco argumentos para definir los métodos de devolución de llamada y finalización, y los parámetros de la animación.

Se pueden agregar animaciones secundarias con Add, Insert, WithConcurrent y la sobrecarga de WithConcurrent.

A continuación, el objeto de animación se inicia con una llamada al método Commit.

Clase AnimationExtensions

La clase AnimationExtensions contiene principalmente métodos de extensión. Hay varias versiones de un método Animate, y el método genérico Animate es tan versátil que es realmente la única función de animación que necesita.

Trabajar con la clase Animation

En el ejemplo ConcurrentAnimations se muestra la clase Animation con varias animaciones diferentes.

Animaciones secundarias

En el ejemplo ConcurrentAnimations también se muestran animaciones secundarias, que hacen uso de los métodos Add y Insert (muy similares).

Más allá de los métodos de animación de alto nivel

En el ejemplo ConcurrentAnimations también se muestra cómo realizar animaciones que van más allá de las propiedades a las que se destinan los métodos ViewExtensions. En un ejemplo, una serie de períodos es más larga; en otro ejemplo, una propiedad BackgroundColor es animada.

Más de sus propios métodos que admiten await

El método TranslateTo de ViewExtensions no funciona con la función Easing.SpringOut. Se detiene cuando la salida de aceleración supera 1.

La biblioteca Xamarin.FormsBook.Toolkit contiene una clase MoreViewExtensions con los métodos de extensión TranslateXTo y TranslateYTo que no tienen este problema, así como los métodos CancelTranslateXTo y CancelTranslateYTo para cancelar esas animaciones.

SpringSlidingEntrance muestra el método TranslateXTo.

La clase MoreExtensions también contiene un método de extensión TranslateXYTo que combina la traducción X e Y, y un método CancelTranslateXYTo.

Implementar una animación Bézier

También es posible desarrollar una animación que mueva un elemento a lo largo del trazado de una curva B-spline. La biblioteca Xamarin.FormsBook.Toolkit contiene una estructura BezierSpline que encapsula una curva B-spline y una enumeración BezierTangent para controlar la orientación.

La clase MoreViewExtensions contiene un método de extensión BezierPathTo y un método CancelBezierPathTo.

En el ejemplo BezierLoop se muestra cómo animar un elemento a lo largo de un trazado Béizer.

Trabajar con AnimationExtensions

Un tipo de animación que falta en la colección estándar es una animación de color. El problema es que no hay ninguna manera adecuada de interpolar entre dos valores Color. Es posible interpolar los valores RGB individuales, pero igual de válido es interpolar valores HSL.

Por esta razón, la clase MoreViewExtensions de la biblioteca Xamarin.FormsBook.Toolkit contiene dos métodos de animación Color: RgbColorAnimation y HslColorAnimation. (También hay dos métodos de cancelación: CancelRgbColorAnimation y CancelHslColorAnimation).

Ambos métodos hacen uso de ColorAnimation, que realiza la animación mediante una llamada al método Animate genérico en AnimationExtensions.

En el ejemplo ColorAnimations se muestra el uso de estos dos tipos de animaciones de color.

Estructurar las animaciones

A veces resulta útil expresar animaciones en XAML y usarlas junto con MVVM. Esto se trata en el capítulo siguiente, Capítulo 23. Desencadenadores y comportamientos.