Hola a todos!
Ya he hablado anteriormente en otros artículos de este blog, lo sencillo que es crear animaciones en XAML para Windows y Windows Phone. Hoy quiero hablar de algo parecido, animaciones también, pero en nuestras aplicaciones Android e iOS, usando Xamarin.
Encontraremos dos aproximaciones distintas: Xamarin y Xamarin.Forms.
En Xamarin.Forms, al tener una vista unificada, dispondremos de mecanismos para crear animaciones en la vista directamente.
En Xamarin tenemos que partir de la base de que, al crear la interface de forma nativa, también tendremos que hacer lo mismo con las animaciones, por lo que cada plataforma tendrá su forma de realizarlas.
Vamos a verlo a continuación.
Xamarin.Forms
En XamarinForms, los controles que usamos para crear la interface de usuario heredan de la clase View.
Existen unos métodos extensores de esta clase, que nos permiten, mediante código, crear animaciones para nuestros controles. Por ejemplo podemos crear una página sencilla con una Label:
{
sampleLabel = new Label
{
Text = «Hello Xamarin.Forms animations!»,
TextColor = Color.Blue,
XAlign = TextAlignment.Center,
Opacity = 0
};
Content = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Children =
{
sampleLabel
}
};
}
Como podemos ver, hemos establecido la opacidad de la Label a 0, por lo que no será inmediatamente visible.
A continuación podemos sobre escribir el método OnAppearing, que se lanza justo antes de mostrarse la página, para animar esta Label y crear un efecto de FadeIn:
{
base.OnAppearing();
sampleLabel.FadeTo(1, 750, Easing.Linear);
}
El método extensor FadeTo puede recibir tres parámetros:
-
Valor final
-
Tiempo de la animación
-
Función de easing. Este parámetro es opcionmal.
Existen otros métodos como ScaleTo, RotateTo, RotateXTo, RotateYTo, LayoutTo, RelRotateTo, TranslateTo, podemos verlos todos aquí.
Podemos crear animaciones complejas, combinando varios efectos, por ejemplo vamos a probar con FadeTo + ScaleTo para crear una animación más completa:
{
base.OnAppearing();
sampleLabel.FadeTo(1, 750, Easing.Linear);
await sampleLabel.ScaleTo(2, 1500, Easing.CubicInOut);
await sampleLabel.ScaleTo(1, 500, Easing.Linear);
}
Lo que hemos hecho aquí, es crear una animación FadeTo lineal que tarda 750 milisegundos en completarse. Como no esperamos a que termine, al mismo tiempo se ejecuta una animación ScaleTo, que duplica el tamaño de la Label en 1 segundo, con una función de easing cúbica. Cuando termina el escalado, se ejecuta otro ScaleTo en 500 milisegundos, que establece de nuevo el tamaño de la Label a su escala original.
Esta forma de crear animaciones nos da mucha flexibilidad a la hora de añadir ese “extra” a nuestras interfaces de usuario con Xamarin Forms.
Además, esto mismo que hemos usado con una Label, se puede llevar a cabo con cualquier otro control, usando exactamente el mismo código fuente.
Xamarin y Windows/Windows Phone
Vamos a ver un repaso rápido de como llevar a cabo esa misma animación, que vimos en Xamarin.Forms, en una aplicación universal para Windows y Windows Phone.
Empezamos por definir el XAML de nuestro TextBlock:
<TextBlock x:Name=«TextHello»
Text=»{Binding Hello}«
VerticalAlignment=«Center»
HorizontalAlignment=«Center»
Foreground=«Blue»
Opacity=«0»
RenderTransformOrigin=«.5,.5»>
<TextBlock.RenderTransform>
<CompositeTransform ScaleX=«1» ScaleY=«1»/>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
Además de definir las propiedades básicas del TextBlock, añadimos un CompositeTransform, para poder animar el escalado del elemento.
Ahora ya podemos crear la animación, usando un Storyboard:
<Storyboard x:Key=«TextBlockAnimation» Duration=«0:0:1.5»>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=«TextHello» Storyboard.TargetProperty=«Opacity»>
<LinearDoubleKeyFrame KeyTime=«0:0:0.750» Value=«1»/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=«TextHello» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.ScaleX)»>
<LinearDoubleKeyFrame KeyTime=«0:0:1.0» Value=«2»/>
<LinearDoubleKeyFrame KeyTime=«0:0:1.5» Value=«1»/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName=«TextHello» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.ScaleY)»>
<LinearDoubleKeyFrame KeyTime=«0:0:1.0» Value=«2»/>
<LinearDoubleKeyFrame KeyTime=«0:0:1.5» Value=«1»/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</views:MvxWindowsPage.Resources>
Y ya solo nos queda lanzar la animación cuando se muestre la página, usando un Behavior o directamente desde código:
{
base.OnNavigatedTo(e);
var animation = (Storyboard)this.Resources[«TextBlockAnimation»];
animation.Begin();
}
Y ya hemos terminado, nada nuevo hasta ahora. Hemos creado una animación simple, como la que hicimos en Xamarin.Forms, pero esta vez usando XAML nativo para Windows y Windows Phone.
Xamarin y Android
Ahora vamos con Android y AXML, ¿Como creamos la misma animación? En primer lugar, creemos el layout de nuestra página inicial en AXML:
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android«
xmlns:local=»http://schemas.android.com/apk/res-auto«
android:orientation=»vertical«
android:layout_width=»fill_parent«
android:layout_height=»fill_parent«>
<TextView
android:id=»@+id/TextHello«
android:layout_width=»fill_parent«
android:layout_height=»wrap_content«
android:textSize=»40dp«
android:textColor=»#00F«
local:MvxBind=»Text Hello» />
</LinearLayout>
A continuación, necesitamos definir un set de animación. Para ello, crearemos un nuevo archivo AXML en la carpeta Drawable, que llamaremos TextAnimation:
<set xmlns:android=»http://schemas.android.com/apk/res/android«
android:shareInterpolator=»false«>
<alpha android:interpolator=»@android:anim/linear_interpolator«
android:toAlpha=»1«
android:startOffset=»0«
android:duration=»750«/>
<scale android:interpolator=»@android:anim/linear_interpolator«
android:scaleGravity=»center_vertical«
android:toXScale=»2«
android:toYScale=»2«
android:pivotX=»50%«
android:pivotY=»50%«
android:startOffset=»0«
android:duration=»1000«/>
<scale android:interpolator=»@android:anim/linear_interpolator«
android:scaleGravity=»center_vertical«
android:toXScale=»1«
android:toYScale=»1«
android:pivotX=»50%«
android:pivotY=»50%«
android:startOffset=»1000«
android:duration=»500«/>
</set>
En Android, si queremos ejecutar varias animaciones en un mismo objeto, podemos crear un Set. Se comporta de forma parecida al Storyboard de XAML. Para crear nuestra animación completa, primero realizamos una animación alpha y a continuación dos scale, el segundo de ellos con un startOffset de 1000 milisegundos (1 segundo).
Para iniciar la animación, vamos a la clase FirstView.cs, al método OnCreate:
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.FirstView);
Animation textAnimation = AnimationUtils.LoadAnimation(Application.ApplicationContext,
Resource.Drawable.TextAnimation);
TextView textHello = FindViewById<TextView>(Resource.Id.TextHello);
textHello.StartAnimation(textAnimation);
}
Obtenemos la animación con el método LoadAnimation de la clase AnimationUtils, obtenemos el TextView al que se la queremos aplicar, buscándolo por ID y finalmente llamamos al método StartAnimation del elemento a animar. Voila! Nuestra animación está lista!
Xamarin y iOS
Y por último, pero no menos importante, iOS. Aquí nos vamos a aprovechar de que creamos la interface de usuario en C# directamente, para ver lo facil que es crear animaciones.
Primero lo primero, Crear la view inicial:
{
View = new UIView { BackgroundColor = UIColor.White };
base.ViewDidLoad();
// ios7 layout
if (RespondsToSelector(new Selector(«edgesForExtendedLayout»)))
{
EdgesForExtendedLayout = UIRectEdge.None;
}
var label = new UILabel(new CGRect(10, 100, 300, 60));
label.Alpha = 0f;
label.TextColor = UIColor.Blue;
Add(label);
var set = this.CreateBindingSet<FirstView, Core.ViewModels.FirstViewModel>();
set.Bind(label).To(vm => vm.Hello);
set.Apply();
}
Tras crear nuestra UILabel, creamos los bindings y establecemos los datos para el texto de la etiqueta.
Ahora vamos a usar el método Animate de la clase UIView para crear nuestra animación, igual que el resto de las plataformas:
{
UIView.Animate(0.75, 0, UIViewAnimationOptions.CurveLinear,
() =>
{
label.Alpha = 1f;
}, null);
UIView.Animate(1, 0, UIViewAnimationOptions.CurveLinear,
() =>
{
label.Transform = CGAffineTransform.MakeScale(2f, 2f);
}, null);
UIView.Animate(0.5, 1, UIViewAnimationOptions.CurveLinear,
() =>
{
label.Transform = CGAffineTransform.MakeScale(1f, 1f);
}, null);
}
El método Animate recibe en primer lugar la duración, en segundos, a continuación la espera en segundos antes de ejecutar la animación, el tipo de transición en el enumerado UIViewAnimationOptions, una función que ejecute la animación y por último otra función que será ejecutada al terminar la animación.
Se explica solo el código, es muy sencillo. usamos una expresión lambda para modificar el objeto UILabel que queremos animar. En el primer caso, simplemente cambiamos la propiedad Alpha. En los dos siguientes usamos la clase CGAffineTransform y el método MakeScale para realizar el escalado necesario.
En resumen
Al final, el crear pequeñas animaciones le aporta un extra de calidad a nuestra aplicación, la hace parecer más suave y ligera.
Cada plataforma tiene su forma de hacer las cosas, a no ser que usemos Xamarin.Forms, donde animamos una sola vez y funciona en todas las plataformas.
Puedes descargarte el código del ejemplo directamente desde GitHub:
https://github.com/josueyeray/XamarinAnimations
Espero que os sea útil.
Un saludo y Happy Coding!