Resumen del capítulo 22. Animación
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:
ViewExtensions
, el enfoque de alto nivelAnimation
, más versátil, pero más difícilAnimationExtension
, el enfoque más versátil y de nivel más bajo
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
:
Linear
, la opción predeterminadaSinIn
,SinOut
ySinInOut
CubicIn
,CubicOut
yCubicInOut
BounceIn
yBounceOut
SpringIn
ySpringOut
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:
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 RotateTo
RotateXTo
, RotateYTo
y 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:
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.