Spanish version: Login animado en .Net MAUI. Hoy quería hacer algo distinto. Me… | by rretamal | Mar, 2024 | Medium
Today, I wanted to do something different. I like the concept of using animations in mobile apps to keep them interactive and attractive for users, so I said, “I’ll make an animated login. Why not, after all?”
So, I opened my Visual Studio and created a new super project called MauiLoginAnimation, yes, I know, super original.
The project will look as follows:
Next, we need a login screen. For this, right-click on the project -> Add -> New Item and select Content Page. Once you’ve created the file, you’ll see a XAML with the text: “Welcome to .NET MAUI!”
Here I’ll pause for a moment. First, how will we animate the login? Wanting to keep it fun, I wanted to place an animation over the login controls in this style:
Perfect, now we have the idea, how do we animate? Well, my dear friend, I went to LottieFiles. I’m not an expert animator or drawer, so why reinvent the wheel?
I opted for a happy face option and tried to find the same animation style with different states. So, we’ll have one for: a normal state (smiling), a happy state when the user enters the username and password, an annoyed state when the user doesn’t enter anything, and two more states just for fun: one when you touch it and another when you swipe on the image.

LottieFiles gives you a JSON file for each animation, which you should save in Resources -> Raw, and they should look like this:
Next, we need to add a NuGet package to use those animations, so you should install the following:
SkiaSharp.Extended.UI.Maui
And if you don’t have it yet, you need to install the CommunityToolkit to display some messages:
CommunityToolkit.Maui
Next, modify the Program of the solution to use the libraries. So it should look like this:
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();
}
}
}Once that’s done, let’s modify our login Page to look like our mockup, which will finally look like this:
<?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>Then, in our code-behind, I added two functions, one to change the animation:
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;
}You’ll see that I have a default animation. We specify the number of times it will repeat, given that we only want the animation to run once, we set it to zero. And when the animation completes, we’ll return to the original animation, which is the default state of laughing. People, we enable the view again for the animation to execute.
I also added a second function that serves to display messages. Each change in the animation state will generate a message. If the user enters a username and password, we’ll execute a message. If the user doesn’t enter any username or password, we’ll show another, and we’ll do that with the following function:
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();
}In the function, we slightly modify the aspect by changing the background, the text color, and the button to give it a more cartoonish look and anchor it to the animation view.
Now we will execute the animations:
- When the user clicks on the 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");
}- When the user taps on the image:
private void OnLottieViewTapped(object sender, EventArgs e)
{
ShowMessage("Ouch!");
ChangeAnimationAndReturn("dizzyface.json");
}- When the user swipes on the image:
private void OnSwipe(object sender, SwipedEventArgs e)
{
ShowMessage("Hahahahaha");
ChangeAnimationAndReturn("laughingface.json");
}And this is how the app will finally look when you run it:

Here you can see a small recording of the app working:

If you liked the article, like it and share it.
rretamal/MauiLoginAnimation (github.com)
Happy Coding!