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:
- Mediante UIKit, que incluye animaciones basadas en vistas, así como transiciones animadas entre controladores.
- Mediante la Animación básica, que crea capas directamente, lo que permite un control más preciso.
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 apareceFlipHorizontal
: 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
:
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.Transition
a, 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:
Ver animaciones de propiedad
UIKit admite la animación de una variedad de propiedades en la clase UIView
de 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:
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 Autoreverse
e, la imagen se ajustaría al lado derecho después de que se complete la animación, como se muestra a continuació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:
Cuando se ejecuta el ejemplo, Position
, BorderWidth
y BorderColor
se animan como se muestra en las capturas de pantalla siguientes:
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:
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.