Animación básica en Xamarin.iOS

En este artículo se examina el marco Animación básica, se muestra cómo permite animaciones fluidas de alto rendimiento en UIKit, así como el uso directo para el control de animación de nivel inferior.

iOS incluye Animación básica para que se admitan animaciones en las vistas de la aplicación. Todas las animaciones ultra suaves en iOS, como el desplazamiento de tablas y el deslizamiento entre diferentes vistas, tienen un buen funcionamiento porque se basan en la Animación básica internamente.

Los marcos Animación básica y Gráficos básicos pueden funcionar juntos para crear gráficos 2D animados hermosos. De hecho, Animación básica puede incluso transformar gráficos 2D en un espacio 3D, creando experiencias cinematográficas increíbles. Sin embargo, para crear verdaderos gráficos 3D, tendría que usar algo como OpenGL ES o, en el caso de los juegos, debería pasarse a una API como MonoGame. Sin embargo, en este artículo no se va a tratar el 3D.

Animación básica

iOS usa el marco Animación básica para crear efectos de animación, como transición entre vistas, menús deslizantes y efectos de desplazamiento, por nombrar algunos. Hay dos maneras de trabajar con animación:

Uso de la animación UIKit

UIKit proporciona varias características que facilitan la adición de animación a una aplicación. Aunque usa la Animación básica internamente, lo abstrae para que solo trabaje con vistas y controladores.

En esta sección se describen las características de animación de UIKit, entre las que se incluyen:

  • Transiciones entre controladores
  • Transiciones entre vistas
  • Visualización de la animación de propiedades

Transiciones de controladores de vistas

UIViewController proporciona compatibilidad integrada para realizar la transición entre controladores de vista a través del método PresentViewController. Cuando se usa PresentViewController, la transición al segundo controlador puede animarse opcionalmente.

Por ejemplo, considere una aplicación con dos controladores, en la que al tocar un botón en el primer controlador se llama a PresentViewController para mostrar un segundo controlador. Para controlar qué animación de transición se usa para mostrar el segundo controlador, simplemente establezca su propiedad ModalTransitionStyle como se muestra a continuación:

SecondViewController vc2 = new SecondViewController {
  ModalTransitionStyle = UIModalTransitionStyle.PartialCurl
};

En este caso se usa una animación PartialCurl, aunque hay otras disponibles, entre las que se incluyen:

  • CoverVertical: diapositivas hacia arriba desde la parte inferior de la pantalla
  • CrossDissolve: la vista antigua se atenúa y la nueva vista aparece
  • FlipHorizontal: un volteo horizontal de derecha a izquierda. Si se ignora, la transición se voltea de izquierda a derecha.

Para animar la transición, pase true como segundo argumento a PresentViewController:

PresentViewController (vc2, true, null);

En la captura de pantalla siguiente se muestra el aspecto de la transición para el caso PartialCurl:

En esta captura de pantalla se muestra la transición PartialCurl

Ver transiciones

Además de las transiciones entre controladores, UIKit también admite la animación de transiciones entre vistas para intercambiar una vista por otra.

Por ejemplo, supongamos que tenía un controlador con UIImageView, en el que al pulsar la imagen debería mostrar un segundo UIImageView. Para animar la supervista de la vista de imagen para realizar la transición a la segunda vista de imagen es tan simple como llamar UIView.Transitiona, pasarla toView y fromView como se muestra a continuación:

UIView.Transition (
  fromView: view1,
  toView: view2,
  duration: 2,
  options: UIViewAnimationOptions.TransitionFlipFromTop |
    UIViewAnimationOptions.CurveEaseInOut,
  completion: () => { Console.WriteLine ("transition complete"); });

UIView.Transition también toma un parámetro duration que controla cuánto tiempo se ejecuta la animación, así como options para especificar cosas como la animación que se va a usar y la función de aceleración. Además, puede especificar un controlador de finalización al que se llamará cuando se complete la animación.

En la captura de pantalla siguiente se muestra la transición animada entre las vistas de imagen cuando TransitionFlipFromTop se usa:

En esta captura de pantalla se muestra la transición animada entre las vistas de imagen cuando se usa TransitionFlipFromTop

Ver animaciones de propiedad

UIKit admite la animación de una variedad de propiedades en la clase UIViewde forma gratuita, entre las que se incluyen:

  • Marco
  • Bounds
  • Centrar
  • Alpha
  • Transformación
  • Color

Estas animaciones se producen implícitamente especificando los cambios de propiedad en un delegado NSAction que se pasó al método estático UIView.Animate. Por ejemplo, el código siguiente anima el punto central de un UIImageView:

pt = imgView.Center;

UIView.Animate (
  duration: 2,
  delay: 0,
  options: UIViewAnimationOptions.CurveEaseInOut |
    UIViewAnimationOptions.Autoreverse,
  animation: () => {
    imgView.Center = new CGPoint (View.Bounds.GetMaxX ()
      - imgView.Frame.Width / 2, pt.Y);},
  completion: () => {
    imgView.Center = pt; }
);

Esto da como resultado una imagen que se anima hacia atrás y hacia delante en la parte superior de la pantalla, como se muestra a continuación:

Una imagen que se anima hacia atrás y hacia delante en la parte superior de la pantalla como salida

Al igual que con el método Transition, Animate permite establecer la duración, junto con la función de aceleración. En este ejemplo también se usó la opción UIViewAnimationOptions.Autoreverse, que hace que la animación se anime a partir del valor hasta el inicial. Sin embargo, el código también establece el Center en su valor inicial en un controlador de finalización. Mientras una animación interpola los valores de propiedad a lo largo del tiempo, el valor del modelo real de la propiedad es siempre el valor final que se ha establecido. En este ejemplo, el valor es un punto cerca del lado derecho de la supervista. Sin establecer el Center en el punto inicial, que es donde se completa la animación debido a que se establece Autoreversee, la imagen se ajustaría al lado derecho después de que se complete la animación, como se muestra a continuación:

Sin establecer el centro en el punto inicial, la imagen se ajustaría al lado derecho después de que se complete la animación

Uso de la Animación básica

Las animaciones UIView permiten una gran cantidad de funcionalidades y se deben usar si es posible debido a la facilidad de implementación. Como se mencionó anteriormente, las animaciones UIView usan el marco Animación básica. Sin embargo, algunas cosas no se pueden hacer con animaciones UIView, como animar propiedades adicionales que no se pueden animar con una vista o interpolar a lo largo de una ruta de acceso no lineal. En tales casos en los que se necesita un control más preciso, también se puede usar la Animación básica directamente.

Capas

Cuando se trabaja con la Animación básica, la animación se produce a través capas, que son de tipo CALayer. Una capa es conceptualmente similar a una vista, ya que hay una jerarquía de capas al igual que hay una jerarquía de vistas. En realidad, las capas tienen vistas (la vista permite la interacción del usuario). Puede acceder a la capa de cualquier vista a través de la propiedad de Layer. De hecho, el contexto usado en el método Draw de UIView se crea en realidad a partir de la capa. Internamente, la capa que tiene un UIView tiene su delegado establecido en la propia vista, que es lo que llama a Draw. Por lo tanto, cuando se dibuja en un UIView, realmente se dibuja en su capa.

Las animaciones de capa pueden ser implícitas o explícitas. Las animaciones implícitas son declarativas. Simplemente tiene que declarar qué propiedades de capa deben cambiar y la animación funcionará. Por otro lado, las animaciones explícitas se crean a través de una clase de animación que se agrega a una capa. Las animaciones explícitas permiten el control de suma sobre cómo se crea una animación. En las secciones siguientes se analizan las animaciones implícitas y explícitas en mayor profundidad.

Animaciones implícitas

Una manera de animar las propiedades de una capa es a través de una animación implícita. Las animaciones UIView crean animaciones implícitas. Sin embargo, también puede crear animaciones implícitas directamente en una capa.

Por ejemplo, el código siguiente establece el Contents de una capa a partir de una imagen, establece un ancho de borde y un color, y agrega la capa como una subcapa de la capa de la vista:

public override void ViewDidLoad ()
{
  base.ViewDidLoad ();

  layer = new CALayer ();
  layer.Bounds = new CGRect (0, 0, 50, 50);
  layer.Position = new CGPoint (50, 50);
  layer.Contents = UIImage.FromFile ("monkey2.png").CGImage;
  layer.ContentsGravity = CALayer.GravityResize;
  layer.BorderWidth = 1.5f;
  layer.BorderColor = UIColor.Green.CGColor;

  View.Layer.AddSublayer (layer);
}

Para agregar una animación implícita para la capa, simplemente ajuste los cambios de propiedad en un CATransaction. Esto permite animar propiedades que no se podrían animar con una animación de vista, como BorderWidth y BorderColor como se muestra a continuación:

public override void ViewDidAppear (bool animated)
{
  base.ViewDidAppear (animated);

  CATransaction.Begin ();
  CATransaction.AnimationDuration = 10;
  layer.Position = new CGPoint (50, 400);
  layer.BorderWidth = 5.0f;
  layer.BorderColor = UIColor.Red.CGColor;
  CATransaction.Commit ();
}

Este código también anima la Position de la capa, que es la ubicación del punto de anclaje de la capa medida desde la parte superior izquierda de las coordenadas de la supercapa. El punto de anclaje de una capa es un punto normalizado dentro del sistema de coordenadas de la capa.

En la ilustración siguiente se muestra la posición y el punto de anclaje:

Esta ilustración muestra la posición y el punto de anclaje

Cuando se ejecuta el ejemplo, Position, BorderWidth y BorderColor se animan como se muestra en las capturas de pantalla siguientes:

Cuando se ejecuta el ejemplo, las propiedades Position, BorderWidth y BorderColor se animan como se muestra

Animaciones explícitas

Además de las animaciones implícitas, la Animación básica incluye una gran variedad de clases que heredan de CAAnimation que permiten encapsular animaciones que se agregan explícitamente a una capa. Esto permite un control más preciso sobre las animaciones, como modificar el valor inicial de una animación, agrupar animaciones y especificar fotogramas clave para permitir rutas de acceso no lineales.

En el código siguiente se muestra un ejemplo de una animación explícita mediante un CAKeyframeAnimation para la capa que se mostró anteriormente (en la sección Animación implícita):

public override void ViewDidAppear (bool animated)
{
  base.ViewDidAppear (animated);

  // get the initial value to start the animation from
  CGPoint fromPt = layer.Position;

  /* set the position to coincide with the final animation value
  to prevent it from snapping back to the starting position
  after the animation completes*/
  layer.Position = new CGPoint (200, 300);

  // create a path for the animation to follow
  CGPath path = new CGPath ();
  path.AddLines (new CGPoint[] { fromPt, new CGPoint (50, 300), new CGPoint (200, 50), new CGPoint (200, 300) });

  // create a keyframe animation for the position using the path
  CAKeyFrameAnimation animPosition = (CAKeyFrameAnimation)CAKeyFrameAnimation.FromKeyPath ("position");
  animPosition.Path = path;
  animPosition.Duration = 2;

  // add the animation to the layer.
  /* the "position" key is used to overwrite the implicit animation created
  when the layer positino is set above*/
  layer.AddAnimation (animPosition, "position");
}

Este código cambia el Position de la capa mediante la creación de una ruta de acceso que se usa para definir una animación de fotograma clave. Observe que la capa Position está establecida en el valor final de la Position a partir de la animación. Sin esto, la capa volvería abruptamente a su Position antes de la animación porque la animación solo cambia el valor de presentación y no el valor del modelo real. Al establecer el valor del modelo en el valor final de la animación, la capa permanece en su lugar al final de la animación.

En las capturas de pantalla siguientes se muestra la capa que contiene la imagen que se anima a través de la ruta de acceso especificada:

Esta captura de pantalla muestra la capa que contiene la imagen que se anima a través de la ruta de acceso especificada

Resumen

En este artículo analizamos las funcionalidades de animación proporcionadas a través de los marcos Animación básica. Hemos examinado la Animación básica, mostrando cómo potencia animaciones en UIKit y cómo se puede usar directamente para el control de animaciones de nivel inferior.