Learn About Xamarin.Forms Animation With PopupPage

Hello Xamarians,

Today, I am here with another post in which I will tell you about Xamarin.Forms Animation with PopupPage. Before going through the article I would like to tell you about Rg.Plugins.Popup. It is a very useful Plugin used to create popup windows in Xamarin.F forms. We can also put animations to these popups so that they look more attractive and enhance the user experience. This article is about XF Animation with PopupPage.

Xamarin

 In this article, we will learn how to use XF Animation with popup page.

Xamarin

Implementation

 Open Visual Studio and select a "New Project".

Xamarin

Now, select Cross-Platform App, give the project a name, and set the project path. Then, click OK.

Xamarin

Select the template as "Blank App" and code sharing as "PCL".

Xamarin

Now, we can install Rg.Plugins.Popup. Right-click on the project, then click on NuGet Package.

Xamarin

Click Browse and search for Rg.Plugins.Popup, select Plugins, and then check the projects in which we want to add this plugin.

Xamarin

Now, we are going to do some  XAML coding and  writing some button code in the MainPage.xaml:

  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XFPopupAnimation" x:Class="XFPopupAnimation.MainPage">  
  3.     <StackLayout>  
  4.         <!-- Place new controls here -->  
  5.         <Label Text="Welcome to Xamarin.Forms Popup Animation!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />  
  6.         <Button Text="Registration Page" Clicked="Button_Clicked_1" />  
  7.         <Button Text="Login Page" Clicked="Button_Clicked" /> </StackLayout>  
  8. </ContentPage> 

Then, write code for popup navigation:

  1. private async void Button_Clicked(object sender, EventArgs e) {  
  2.     await Navigation.PushPopupAsync(new LoginPopupPage());  
  3. }  
  4. private async void Button_Clicked_1(object sender, EventArgs e) {  
  5.     await Navigation.PushPopupAsync(new RegPage());  
  6. }  

Now, we are creating LoginPopupPage.xaml PopupPages.

  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XFPopupAnimation.LoginPopupPage" xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup" xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup">  
  3.     <pages:PopupPage.Resources>  
  4.         <ResourceDictionary>  
  5.             <Style x:Key="EntryStyle" TargetType="Entry">  
  6.                 <Setter Property="PlaceholderColor" Value="#9cdaf1"/><Setter Property="TextColor" Value="#7dbbe6"/>  
  7.             </Style>  
  8.         </ResourceDictionary>  
  9.     </pages:PopupPage.Resources>  
  10.     <pages:PopupPage.Animation>  
  11.         <animations:ScaleAnimation PositionIn="Bottom" PositionOut="Center" ScaleIn="1" ScaleOut="0.7" DurationIn="700" EasingIn="BounceOut" /> </pages:PopupPage.Animation>  
  12.     <ScrollView HorizontalOptions="Center" VerticalOptions="Center">  
  13.         <AbsoluteLayout>  
  14.             <Frame x:Name="FrameContainer" Margin="15" HorizontalOptions="Center" BackgroundColor="White">  
  15.                 <StackLayout IsClippedToBounds="True" Padding="10, 5" Spacing="3">  
  16.                     <Image HorizontalOptions="Center" x:Name="OctocatImage" Margin="10" HeightRequest="150" WidthRequest="150" Source="Logo" />  
  17.                     <Entry HorizontalOptions="Center" x:Name="UsernameEntry" Style="{StaticResource EntryStyle}" Placeholder="Username" />  
  18.                     <Entry HorizontalOptions="Center" x:Name="PasswordEntry" Style="{StaticResource EntryStyle}" Placeholder="Password" IsPassword="True" />  
  19.                     <Button Margin="10, 5" BackgroundColor="#7dbbe6" HorizontalOptions="Fill" x:Name="LoginButton" Text="Login">  
  20.   
  21. <Button.HeightRequest>  
  22.   
  23. <OnPlatform x:TypeArguments="x:Double" Android="50" iOS="30" WinPhone="30"/>  
  24.   
  25. </Button.HeightRequest>  
  26.   
  27. </Button> </StackLayout>  
  28.             </Frame>  
  29.             <ContentView AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="1, 0, -1, -1">  
  30.                 <ContentView.GestureRecognizers>  
  31.                     <TapGestureRecognizer Tapped="OnCloseButtonTapped" /> </ContentView.GestureRecognizers>  
  32.                 <Image x:Name="CloseImage" HeightRequest="30" WidthRequest="30">  
  33.                     <Image.Source>  
  34.                         <OnPlatform x:TypeArguments="ImageSource" Android="close_circle_button.png" iOS="close_circle_button.png" /> </Image.Source>  
  35.                 </Image>  
  36.             </ContentView>  
  37.         </AbsoluteLayout>  
  38.     </ScrollView>  
  39. </pages:PopupPage>  

Now, we are coding in C#:

  1. using Rg.Plugins.Popup.Extensions;  
  2. using Rg.Plugins.Popup.Pages;  
  3. using System.Threading.Tasks;  
  4. using Xamarin.Forms;  
  5. using Xamarin.Forms.Xaml;  
  6. namespace XFPopupAnimation {  
  7.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  8.     public partial class LoginPopupPage: PopupPage {  
  9.         public LoginPopupPage() {  
  10.             InitializeComponent();  
  11.         }  
  12.         public bool IsAnimationEnabled {  
  13.             get;  
  14.             private set;  
  15.         } = true;  
  16.         protected override void OnAppearing() {  
  17.             base.OnAppearing();  
  18.             FrameContainer.HeightRequest = -1;  
  19.             if (!IsAnimationEnabled) {  
  20.                 CloseImage.Rotation = 0;  
  21.                 CloseImage.Scale = 1;  
  22.                 CloseImage.Opacity = 1;  
  23.                 LoginButton.Scale = 1;  
  24.                 LoginButton.Opacity = 1;  
  25.                 UsernameEntry.TranslationX = PasswordEntry.TranslationX = 0;  
  26.                 UsernameEntry.Opacity = PasswordEntry.Opacity = 1;  
  27.                 return;  
  28.             }  
  29.             CloseImage.Rotation = 380;  
  30.             CloseImage.Scale = 0.3;  
  31.             CloseImage.Opacity = 0;  
  32.             LoginButton.Scale = 0.3;  
  33.             LoginButton.Opacity = 0;  
  34.             UsernameEntry.TranslationX = PasswordEntry.TranslationX = -10;  
  35.             UsernameEntry.Opacity = PasswordEntry.Opacity = 0;  
  36.         }  
  37.         protected override async Task OnAppearingAnimationEnd() {  
  38.             if (!IsAnimationEnabled) return;  
  39.             var translateLength = 400 u;  
  40.             await Task.WhenAll(UsernameEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), UsernameEntry.FadeTo(1), (new Func < Task > (async () => {  
  41.                 await Task.Delay(200);  
  42.                 await Task.WhenAll(PasswordEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), PasswordEntry.FadeTo(1));  
  43.             }))());  
  44.             await Task.WhenAll(CloseImage.FadeTo(1), CloseImage.ScaleTo(1, easing: Easing.SpringOut), CloseImage.RotateTo(0), LoginButton.ScaleTo(1), LoginButton.FadeTo(1));  
  45.         }  
  46.         protected override async Task OnDisappearingAnimationBegin() {  
  47.             if (!IsAnimationEnabled) return;  
  48.             var taskSource = new TaskCompletionSource < bool > ();  
  49.             var currentHeight = FrameContainer.Height;  
  50.             await Task.WhenAll(UsernameEntry.FadeTo(0), PasswordEntry.FadeTo(0), LoginButton.FadeTo(0));  
  51.             FrameContainer.Animate("HideAnimation", d => {  
  52.                 FrameContainer.HeightRequest = d;  
  53.             }, start: currentHeight, end: 170, finished: async (d, b) => {  
  54.                 await Task.Delay(300);  
  55.                 taskSource.TrySetResult(true);  
  56.             });  
  57.             await taskSource.Task;  
  58.         }  
  59.         private void OnCloseButtonTapped(object sender, EventArgs e) {  
  60.             CloseAllPopup();  
  61.         }  
  62.         protected override bool OnBackgroundClicked() {  
  63.             CloseAllPopup();  
  64.             return false;  
  65.         }  
  66.         private async void CloseAllPopup() {  
  67.             await Navigation.PopAllPopupAsync();  
  68.         }  
  69.     }  
  70. }  

Now, we are creating RegPage.xaml PopupPages.

  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XFPopupAnimation.RegPage" xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup" xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup">  
  3.     <pages:PopupPage.Resources>  
  4.         <ResourceDictionary>  
  5.             <Style x:Key="EntryStyle" TargetType="Entry">  
  6.                 <Setter Property="PlaceholderColor" Value="#9cdaf1"/><Setter Property="TextColor" Value="#7dbbe6"/>  
  7.             </Style>  
  8.         </ResourceDictionary>  
  9.     </pages:PopupPage.Resources>  
  10.     <pages:PopupPage.Animation>  
  11.         <animations:ScaleAnimation PositionIn="Bottom" PositionOut="Center" ScaleIn="1" ScaleOut="0.7" DurationIn="700" EasingIn="BounceOut" /> </pages:PopupPage.Animation>  
  12.     <ScrollView HorizontalOptions="Center" VerticalOptions="Center">  
  13.         <AbsoluteLayout>  
  14.             <Frame x:Name="FrameContainer" Margin="15" HorizontalOptions="Center" BackgroundColor="White">  
  15.                 <StackLayout IsClippedToBounds="True" Padding="10, 5" Spacing="3">  
  16.                     <Image Source="Logo" HorizontalOptions="Center" x:Name="OctocatImage" Margin="10" HeightRequest="150" WidthRequest="150" />  
  17.                     <Entry HorizontalOptions="Center" x:Name="FnameEntry" Style="{StaticResource EntryStyle}" Placeholder="First Name" />  
  18.                     <Entry HorizontalOptions="Center" x:Name="LnameEntry" Style="{StaticResource EntryStyle}" Placeholder="Last Name" />  
  19.                     <Entry HorizontalOptions="Center" x:Name="UsernameEntry" Style="{StaticResource EntryStyle}" Placeholder="Username" />  
  20.                     <Entry HorizontalOptions="Center" x:Name="PasswordEntry" Style="{StaticResource EntryStyle}" Placeholder="Password" IsPassword="True" />  
  21.                     <Button Margin="10, 5" BackgroundColor="#7dbbe6" HorizontalOptions="Fill" x:Name="LoginButton" Text="Login">  
  22.   
  23. <Button.HeightRequest>  
  24.   
  25. <OnPlatform x:TypeArguments="x:Double" Android="50" iOS="30" WinPhone="30"/>  
  26.   
  27. </Button.HeightRequest>  
  28.   
  29. </Button> </StackLayout>  
  30.             </Frame>  
  31.             <ContentView AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="1, 0, -1, -1">  
  32.                 <ContentView.GestureRecognizers>  
  33.                     <TapGestureRecognizer Tapped="OnCloseButtonTapped" /> </ContentView.GestureRecognizers>  
  34.                 <Image x:Name="CloseImage" HeightRequest="30" WidthRequest="30">  
  35.                     <Image.Source>  
  36.                         <OnPlatform x:TypeArguments="ImageSource" Android="close_circle_button.png" iOS="close_circle_button.png" /> </Image.Source>  
  37.                 </Image>  
  38.             </ContentView>  
  39.         </AbsoluteLayout>  
  40.     </ScrollView>  
  41. </pages:PopupPage>  

Write some RegPage Code for animation

We are using override method for the animation with the names:

  1.  override void OnAppearing()
  2.  override async Task OnAppearingAnimationEnd()
  3.  override async Task OnDisappearingAnimationBegin()
  4.  override bool OnBackgroundClicked()

Write the following C# code for the animation that will appear when opening registration page.

  1. using Rg.Plugins.Popup.Extensions;  
  2. using Rg.Plugins.Popup.Pages;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8. using Xamarin.Forms;  
  9. using Xamarin.Forms.Xaml;  
  10. namespace XFPopupAnimation {  
  11.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  12.     public partial class RegPage: PopupPage {  
  13.         public RegPage() {  
  14.             InitializeComponent();  
  15.         }  
  16.         public bool IsAnimationEnabled {  
  17.             get;  
  18.             private set;  
  19.         } = true;  
  20.         protected override void OnAppearing() {  
  21.             base.OnAppearing();  
  22.             FrameContainer.HeightRequest = -1;  
  23.             if (!IsAnimationEnabled) {  
  24.                 CloseImage.Rotation = 0;  
  25.                 CloseImage.Scale = 1;  
  26.                 CloseImage.Opacity = 1;  
  27.                 LoginButton.Scale = 1;  
  28.                 LoginButton.Opacity = 1;  
  29.                 FnameEntry.TranslationX = LnameEntry.TranslationX = UsernameEntry.TranslationX = PasswordEntry.TranslationX = 0;  
  30.                 FnameEntry.TranslationX = LnameEntry.TranslationX = UsernameEntry.Opacity = PasswordEntry.Opacity = 1;  
  31.                 return;  
  32.             }  
  33.             CloseImage.Rotation = 380;  
  34.             CloseImage.Scale = 0.3;  
  35.             CloseImage.Opacity = 0;  
  36.             LoginButton.Scale = 0.3;  
  37.             LoginButton.Opacity = 0;  
  38.             FnameEntry.TranslationX = LnameEntry.TranslationX = UsernameEntry.TranslationX = PasswordEntry.TranslationX = -10;  
  39.             FnameEntry.Opacity = LnameEntry.Opacity = UsernameEntry.Opacity = PasswordEntry.Opacity = 0;  
  40.         }  
  41.         protected override async Task OnAppearingAnimationEnd() {  
  42.             if (!IsAnimationEnabled) return;  
  43.             var translateLength = 800 u;  
  44.             await Task.WhenAll(FnameEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), FnameEntry.FadeTo(1), (new Func < Task > (async () => {  
  45.                 await Task.Delay(400);  
  46.                 await Task.WhenAll(LnameEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), LnameEntry.FadeTo(1), Task.Delay(200), UsernameEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), UsernameEntry.FadeTo(1), Task.Delay(200), PasswordEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), PasswordEntry.FadeTo(1));  
  47.             }))());  
  48.             await Task.WhenAll(CloseImage.FadeTo(1), CloseImage.ScaleTo(1, easing: Easing.SpringOut), CloseImage.RotateTo(0), LoginButton.ScaleTo(1), LoginButton.FadeTo(1));  
  49.         }  
  50.         protected override async Task OnDisappearingAnimationBegin() {  
  51.             if (!IsAnimationEnabled) return;  
  52.             var taskSource = new TaskCompletionSource < bool > ();  
  53.             var currentHeight = FrameContainer.Height;  
  54.             await Task.WhenAll(FnameEntry.FadeTo(0), LnameEntry.FadeTo(0), UsernameEntry.FadeTo(0), PasswordEntry.FadeTo(0), LoginButton.FadeTo(0));  
  55.             FrameContainer.Animate("HideAnimation", d => {  
  56.                 FrameContainer.HeightRequest = d;  
  57.             }, start: currentHeight, end: 170, finished: async (d, b) => {  
  58.                 await Task.Delay(500);  
  59.                 taskSource.TrySetResult(true);  
  60.             });  
  61.             await taskSource.Task;  
  62.         }  
  63.         private void OnCloseButtonTapped(object sender, EventArgs e) {  
  64.             CloseAllPopup();  
  65.         }  
  66.         protected override bool OnBackgroundClicked() {  
  67.             CloseAllPopup();  
  68.             return false;  
  69.         }  
  70.         private async void CloseAllPopup() {  
  71.             await Navigation.PopAllPopupAsync();  
  72.         }  
  73.     }  
  74. }  

Xamarin

The XF Popup.Animation is working successfully. To watch the video of working animation, you can click here.

For more information, read my blog here at http://www.xamarinbuddy.com/2018/05/popupanimation.html