English version: Animated Login in .Net MAUI.. Today, I wanted to do something… | by rretamal | Mar, 2024 | Medium
Hoy quería hacer algo distinto. Me gusta el concepto de usar animaciones en las apps móviles y mantenerlas interactivas y atractivas para los usuarios, así que dije: “Haré un login animado, total, ¿por qué no?”.
Así que abrí mi Visual Studio y creé un nuevo super proyecto llamado MauiLoginAnimation, sí, lo sé, super original.
El proyecto se verá de la siguiente manera:
Seguidamente, necesitamos una pantalla de login. Para ello, hacemos clic derecho al proyecto -> Add -> New Item y seleccionamos Content Page. Una vez creado el archivo, verás un XAML con el texto: “Welcome to .NET MAUI!”.
Aquí me detendré un rato. Lo primero, ¿de qué manera animaremos el login? Como quería mantenerlo divertido, quería poner una animación por encima de los controles de login a este estilo:
Ya perfecto, tenemos la idea, ¿cómo animamos? Bueno, mi querido amigo, me fui a LottieFiles. No soy un experto animador o dibujante, así que, ¿para qué matarnos reinventando la rueda?
Opté por la opción de una cara feliz y traté de buscar el mismo estilo de animación con distintos estados. Así que tendremos uno para: estado normal (sonriente), un estado alegre cuando el usuario pase la contraseña, un estado molesto cuando el usuario no introduzca nada y dos estados más por puro jugar: uno cuando lo tocas y otro cuando haces swipe en la imagen.

LottieFiles te entrega un archivo JSON por cada animación, los cuales debes guardar en Resources -> Raw y deben verse de la siguiente manera:
Lo siguiente es agregar el paquete NuGet para usar esas animaciones, por lo que debes instalar el siguiente:
SkiaSharp.Extended.UI.Maui
Y por si no lo tienes, hay que instalar el CommunityToolkit para mostrar algunos mensajes:
CommunityToolkit.Maui
Lo siguiente es modificar el Program de la solución para usar las librerías. Así que debería quedar de la siguiente manera:
using CommunityToolkit.Maui;
using Microsoft.Extensions.Logging;
using SkiaSharp.Views.Maui.Controls.Hosting;
namespace MauiLoginAnimation
{
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.UseSkiaSharp()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
}Una vez hecho eso, vamos a modificar nuestra página de login para que luzca como nuestro mockup, que finalmente quedará así:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiLoginAnimation.LoginPage"
xmlns:skia="clr-namespace:SkiaSharp.Extended.UI.Controls;assembly=SkiaSharp.Extended.UI"
Title="LoginPage"
NavigationPage.HasNavigationBar="False"
BackgroundColor="{AppThemeBinding Light={StaticResource BackgroundColorLight}, Dark={StaticResource BackgroundColorDark}}">
<Grid Margin="40">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="icon.png" Aspect="AspectFit" HeightRequest="100" HorizontalOptions="Center" VerticalOptions="Center" />
<skia:SKLottieView
Grid.Row="0"
x:Name="faceView"
Source="happyface.json"
RepeatCount="-1"
HeightRequest="150"
HorizontalOptions="Center"
VerticalOptions="Center"
IsAnimationEnabled="True">
<skia:SKLottieView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnLottieViewTapped"/>
<SwipeGestureRecognizer Direction="Right" Swiped="OnSwipe"/>
<SwipeGestureRecognizer Direction="Left" Swiped="OnSwipe"/>
</skia:SKLottieView.GestureRecognizers>
</skia:SKLottieView>
<VerticalStackLayout Grid.Row="1" Spacing="10">
<Label Text="Login into our App!" FontSize="20"
TextColor="{AppThemeBinding Light={StaticResource TextColorLight}, Dark={StaticResource TextColorDark}}"
FontAttributes="Bold" Margin="0,0,0,20"
HorizontalOptions="Center"/>
<Label Text="Email Address"
TextColor="{AppThemeBinding Light={StaticResource TextColorLight}, Dark={StaticResource TextColorDark}}"/>
<Entry x:Name="txtEmail" Placeholder="email@domain.com" Keyboard="Email"
TextColor="{AppThemeBinding Light={StaticResource TextColorLight}, Dark={StaticResource TextColorDark}}"
PlaceholderColor="{AppThemeBinding Light={StaticResource SecondaryTextColorLight}, Dark={StaticResource SecondaryTextColorDark}}"/>
<Label Text="Password"
TextColor="{AppThemeBinding Light={StaticResource TextColorLight}, Dark={StaticResource TextColorDark}}"/>
<Entry x:Name="txtPassword" Placeholder="password" IsPassword="True"
TextColor="{AppThemeBinding Light={StaticResource TextColorLight}, Dark={StaticResource TextColorDark}}"
PlaceholderColor="{AppThemeBinding Light={StaticResource SecondaryTextColorLight}, Dark={StaticResource SecondaryTextColorDark}}"/>
<Label Text="Forgot password?" HorizontalOptions="End"
TextColor="{AppThemeBinding Light={StaticResource SecondaryTextColorLight}, Dark={StaticResource SecondaryTextColorDark}}"
FontSize="Small"/>
<Button x:Name="btnLogin" Text="Log In"
BackgroundColor="{AppThemeBinding Light={StaticResource AccentColorLight}, Dark={StaticResource AccentColorDark}}"
TextColor="{AppThemeBinding Light={StaticResource BackgroundColorLight}, Dark={StaticResource BackgroundColorDark}}"
Margin="0,10,0,0"/>
<Label HorizontalOptions="CenterAndExpand" Margin="0,10,0,0">
<Label.FormattedText>
<FormattedString>
<Span Text="New User? "
TextColor="{AppThemeBinding Light={StaticResource SecondaryTextColorLight}, Dark={StaticResource SecondaryTextColorDark}}"/>
<Span Text="Create Account"
TextColor="{AppThemeBinding Light={StaticResource AccentColorLight}, Dark={StaticResource AccentColorDark}}"/>
</FormattedString>
</Label.FormattedText>
</Label>
</VerticalStackLayout>
</Grid>
</ContentPage>Después, en nuestro code-behind, agregué dos funciones, una para ir cambiando la animación:
private void ChangeAnimationAndReturn(string newAnimationFile)
{
// Save the file name of the original animation
var originalAnimationFile = new SKFileLottieImageSource { File = "happyface.json" };
// Change the animation of the AnimationView to the new JSON file.
faceView.RepeatCount = 0;
faceView.Source = new SKFileLottieImageSource { File = newAnimationFile };
// Subscribe to the AnimationCompleted event to switch back to the original animation
faceView.AnimationCompleted += (sender, args) =>
{
// Switch back to the original animation
faceView.RepeatCount = -1;
faceView.Source = originalAnimationFile;
faceView.IsAnimationEnabled = true;
};
faceView.IsAnimationEnabled = true;
}Verás que tengo una animación por defecto. Especificamos el número de veces que se repetirá, dado que solo queremos que la animación se ejecute una sola vez, la ponemos en cero. Y cuando la animación se complete, volveremos a la animación original, que es el estado por defecto riendo. Gente, habilitamos nuevamente la vista para que se ejecute la animación.
Igualmente, agregué una segunda función que sirve para mostrar mensajes. Cada cambio en el estado de la animación generará un mensaje. Si el usuario introduce un usuario y contraseña, ejecutaremos un mensaje. Si el usuario no introduce ningún usuario ni contraseña, mostraremos otro, y eso lo haremos con la siguiente función:
private void ShowMessage(string message)
{
var snackbar = Snackbar.Make(message, visualOptions: new SnackbarOptions()
{
BackgroundColor = Color.FromArgb("#FFFCBA03"),
TextColor = Color.FromArgb("#FF000000"),
ActionButtonTextColor = Color.FromArgb("#FFFCBA03"),
Font = Microsoft.Maui.Font.SystemFontOfSize(20, FontWeight.Bold),
CornerRadius = new CornerRadius(12),
}, anchor: faceView);
snackbar.Show();
}En la función, modificamos un poco el aspecto cambiando el fondo, el color del texto y del botón para darle un aspecto más cartoon y lo anclamos a la vista de la animación.
Ahora iremos ejecutando las animaciones:
- Cuando el usuario haga clic en el login
private async void BtnLogin_Clicked(object? sender, EventArgs e)
{
if(string.IsNullOrEmpty(txtEmail.Text) && string.IsNullOrEmpty(txtPassword.Text))
{
ShowMessage("I think you missed something");
ChangeAnimationAndReturn("putpassword.json");
return;
}
ShowMessage("Now we are talking!");
ChangeAnimationAndReturn("cowboyface.json");
}- Cuando el usuario haga tap en la imagen:
private void OnLottieViewTapped(object sender, EventArgs e)
{
ShowMessage("Ouch!");
ChangeAnimationAndReturn("dizzyface.json");
}- Cuando el usuario haga swipe en la imagen
private void OnSwipe(object sender, SwipedEventArgs e)
{
ShowMessage("Hahahahaha");
ChangeAnimationAndReturn("laughingface.json");
}Y así luciría finalmente la app cuando la ejecutes:

Aquí puedes ver una pequeña grabación de la app funcionando:

Si te gustó el artículo, dale me gusta y compártelo.
rretamal/MauiLoginAnimation (github.com)
Happy Coding!