Compartir a través de


Animación básica

Las clases de animación de interfaz de usuario de aplicación multiplataforma de .NET (.NET MAUI) tienen como destino diferentes propiedades de elementos visuales, con una animación básica típica que cambia progresivamente una propiedad de un valor a otro durante un período de tiempo.

Las animaciones básicas se pueden crear con métodos de extensión proporcionados por la clase ViewExtensions, que opera en objetos VisualElement:

De forma predeterminada, cada animación tomará 250 milisegundos. Sin embargo, se puede especificar una duración para cada animación al crear la animación.

Nota

La clase ViewExtensions también proporciona un método de extensión LayoutTo. Sin embargo, este método está pensado para ser utilizado por diseños para animar transiciones entre estados de diseño que contienen cambios de tamaño y posición.

Los métodos de extensión de animación de la clase ViewExtensions son asincrónicos y devuelven un objeto Task<bool>. El valor devuelto es false si se completa la animación y true si se cancela la animación. Por lo tanto, cuando las operaciones de animación se combinan con el operador await, es posible crear animaciones secuenciales con métodos de animación posteriores que se ejecutan después de que se haya completado el método anterior. Para obtener más información, vea animaciones compuestas.

Si hay un requisito para permitir que una animación se complete en segundo plano, se puede omitir el operador await. En este escenario, los métodos de extensión de animación finalizarán rápidamente tras iniciar la animación, mientras la animación se desarrolla en segundo plano. Esta operación se puede aprovechar al crear animaciones compuestas. Para obtener más información, consulte animaciones compuestas.

En Android, las animaciones respetan la configuración de animación del sistema:

  • Si las animaciones del sistema están deshabilitadas (ya sea por características de accesibilidad o características de desarrollador), las nuevas animaciones saltarán inmediatamente a su estado terminado.
  • Si el modo de ahorro de energía del dispositivo está activado mientras las animaciones están en curso, las animaciones saltarán inmediatamente a su estado terminado.
  • Si las duraciones de animación del dispositivo se establecen en cero (deshabilitadas) mientras las animaciones están en curso y la versión de la API es 33 o superior, las animaciones saltarán inmediatamente a su estado finalizado.

Animaciones únicas

Cada método de extensión de la clase ViewExtensions implementa una sola operación de animación que cambia progresivamente una propiedad de un valor a otro durante un período de tiempo.

Rotación

La rotación se realiza con el método RotateTo, que cambia progresivamente la propiedad Rotation de un elemento:

await image.RotateTo(360, 2000);
image.Rotation = 0;

En este ejemplo, una instancia de Image se gira hasta 360 grados durante 2 segundos (2000 milisegundos). El método RotateTo obtiene el valor de propiedad Rotation actual del elemento para el inicio de la animación y, a continuación, gira de ese valor a su primer argumento (360). Una vez completada la animación, la propiedad Rotation de la imagen se restablece a 0. Esto garantiza que la propiedad Rotation no permanezca en 360 después de que finalice la animación, lo que impediría rotaciones adicionales.

Nota

Además del método RotateTo, también hay métodos RotateXTo y RotateYTo que animan las propiedades RotationX y RotationY, respectivamente.

Rotación relativa

La rotación relativa se realiza con el método RelRotateTo, que cambia progresivamente la propiedad Rotation de un elemento:

await image.RelRotateTo(360, 2000);

En este ejemplo, una instancia de Image gira 360 grados desde su posición inicial durante 2 segundos (2000 milisegundos). El método RelRotateTo obtiene el valor de propiedad Rotation actual del elemento para el inicio de la animación y, a continuación, gira de ese valor al valor más su primer argumento (360). Esto garantiza que cada animación siempre será un giro de 360 grados desde la posición inicial. Por lo tanto, si se invoca una nueva animación mientras una animación ya está en curso, comenzará desde la posición actual y puede terminar en una posición que no sea un incremento de 360 grados.

Dimensionamiento

El escalado se realiza con el método ScaleTo, que cambia progresivamente la propiedad Scale de un elemento:

await image.ScaleTo(2, 2000);

En este ejemplo, una instancia de Image se escala verticalmente hasta dos veces su tamaño durante 2 segundos (2000 milisegundos). El método ScaleTo obtiene el valor de propiedad Scale actual del elemento para el inicio de la animación y, a continuación, se escala de ese valor a su primer argumento. Esto tiene el efecto de expandir el tamaño de la imagen a dos veces su tamaño.

Nota

Además del método ScaleTo, también hay métodos ScaleXTo y ScaleYTo que animan las propiedades ScaleX y ScaleY, respectivamente.

Escalado relativo

El escalado relativo se realiza con el método RelScaleTo, que cambia progresivamente la propiedad Scale de un elemento:

await image.RelScaleTo(2, 2000);

En este ejemplo, una instancia de Image se escala verticalmente hasta dos veces su tamaño durante 2 segundos (2000 milisegundos). El método RelScaleTo obtiene el valor de propiedad Scale actual del elemento para el inicio de la animación y, a continuación, escala de ese valor al valor más su primer argumento. Esto garantiza que cada animación siempre tendrá un factor de escala de 2 desde la posición inicial.

Escalado y rotación con anclajes

Las propiedades AnchorX y AnchorY de un elemento visual establecen el centro de escalado o rotación de las propiedades Rotation y Scale. Por lo tanto, sus valores también afectan a los métodos RotateTo y ScaleTo.

Dado un Image que se ha colocado en el centro de un diseño, en el ejemplo de código siguiente se muestra cómo girar la imagen alrededor del centro del diseño estableciendo su propiedad AnchorY:

double radius = Math.Min(absoluteLayout.Width, absoluteLayout.Height) / 2;
image.AnchorY = radius / image.Height;
await image.RotateTo(360, 2000);

Para girar la instancia de Image alrededor del centro del diseño, las propiedades AnchorX y AnchorY deben establecerse en valores relativos al ancho y alto del Image. En este ejemplo, el centro del Image se define para que esté en el centro del diseño y, por tanto, el valor predeterminado AnchorX de 0,5 no requiere cambiar. Sin embargo, la propiedad AnchorY se vuelve a definir como un valor desde la parte superior del Image hasta el punto central del diseño. Esto garantiza que el Image realice un giro completo de 360 grados alrededor del punto central del diseño.

Traducción

La traducción se realiza con el método TranslateTo, que cambia progresivamente las propiedades TranslationX y TranslationY de un elemento:

await image.TranslateTo(-100, -100, 1000);

En este ejemplo, la instancia Image se traduce horizontal y verticalmente a lo largo de 1 segundo (1000 milisegundos). El método TranslateTo traduce simultáneamente la imagen 100 unidades independientes del dispositivo a la izquierda y 100 unidades independientes del dispositivo hacia arriba. Esto se debe a que los argumentos primero y segundo son números negativos. Proporcionar números positivos desplazaría la imagen hacia la derecha y hacia abajo.

Importante

Si un elemento se coloca inicialmente fuera de la pantalla y, a continuación, se traduce en la pantalla, después de traducir el diseño de entrada del elemento permanece fuera de la pantalla y el usuario no puede interactuar con él. Por lo tanto, se recomienda que una vista se deba diseñar en su posición final y, a continuación, las traducciones necesarias realizadas.

Desvanecimiento

La atenuación se realiza con el método FadeTo, que cambia progresivamente la propiedad Opacity de un elemento:

image.Opacity = 0;
await image.FadeTo(1, 4000);

En este ejemplo, la instancia de Image se atenua en más de 4 segundos (4000 milisegundos). El método FadeTo obtiene el valor de propiedad Opacity actual del elemento para el inicio de la animación y, a continuación, se atenua de ese valor a su primer argumento.

Animaciones compuestas

Una animación compuesta es una combinación secuencial de animaciones y se puede crear con el operador await:

await image.TranslateTo(-100, 0, 1000);    // Move image left
await image.TranslateTo(-100, -100, 1000); // Move image diagonally up and left
await image.TranslateTo(100, 100, 2000);   // Move image diagonally down and right
await image.TranslateTo(0, 100, 1000);     // Move image left
await image.TranslateTo(0, 0, 1000);       // Move image up

En este ejemplo, la instancia de Image se traduce durante 6 segundos (6000 milisegundos). La traducción del Image usa cinco animaciones, con el operador await que indica que cada animación se ejecuta secuencialmente. Por lo tanto, los métodos de animación posteriores se ejecutan después de que se haya completado el método anterior.

Animaciones compuestas

Una animación compuesta es una combinación de animaciones en las que dos o más animaciones se ejecutan simultáneamente. Las animaciones compuestas se pueden crear combinando animaciones esperadas y no esperadas:

image.RotateTo(360, 4000);
await image.ScaleTo(2, 2000);
await image.ScaleTo(1, 2000);

En este ejemplo, la instancia de Image se escala y gira simultáneamente durante 4 segundos (4000 milisegundos). El escalado de la Image utiliza dos animaciones secuenciales que ocurren simultáneamente con la rotación. El método RotateTo se ejecuta sin un operador await y devuelve inmediatamente, con la primera animación ScaleTo que comienza. El operador await del primer método ScaleTo retrasa el segundo método ScaleTo hasta que se haya completado el primer método ScaleTo. En este momento, la animación RotateTo se completa a la mitad y el Image se rotará 180 grados. Durante los últimos 2 segundos (2000 milisegundos), la segunda animación ScaleTo y la animación RotateTo se completan.

Ejecutar varias animaciones simultáneamente

Los métodos Task.WhenAny y Task.WhenAll se pueden usar para ejecutar varios métodos asincrónicos simultáneamente y, por tanto, pueden crear animaciones compuestas. Ambos métodos devuelven un objeto Task y aceptan una colección de métodos que devuelven un objeto Task. El método Task.WhenAny se completa cuando cualquier método de su colección completa la ejecución, como se muestra en el ejemplo de código siguiente:

await Task.WhenAny<bool>
(
  image.RotateTo(360, 4000),
  image.ScaleTo(2, 2000)
);
await image.ScaleTo(1, 2000);

En este ejemplo, el método Task.WhenAny contiene dos tareas. La primera tarea gira una instancia de Image durante 4 segundos (4000 milisegundos) y la segunda tarea escala la imagen durante 2 segundos (2000 milisegundos). Cuando se completa la segunda tarea, se completa la llamada al método Task.WhenAny. Sin embargo, aunque el método RotateTo siga ejecutándose, el segundo método ScaleTo puede comenzar.

El método Task.WhenAll se completa cuando se han completado todos los métodos de su colección, como se muestra en el ejemplo de código siguiente:

// 10 minute animation
uint duration = 10 * 60 * 1000;
await Task.WhenAll
(
  image.RotateTo(307 * 360, duration),
  image.RotateXTo(251 * 360, duration),
  image.RotateYTo(199 * 360, duration)
);

En este ejemplo, el método Task.WhenAll contiene tres tareas, cada una de las cuales se ejecuta durante 10 minutos. Cada Task hace un número diferente de rotaciones de 360 grados: 307 rotaciones para RotateTo, 251 rotaciones para RotateXToy 199 rotaciones para RotateYTo. Estos valores son números primos, por lo que se garantiza que las rotaciones no están sincronizadas y, por tanto, no darán lugar a patrones repetitivos.

Cancelación de animaciones

El método de extensión CancelAnimations se usa para cancelar las animaciones, como rotación, escalado, traducción y atenuación, que se ejecutan en un VisualElementespecífico.

image.CancelAnimations();

En este ejemplo, todas las animaciones que se ejecutan en la instancia de Image se cancelan inmediatamente.