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.
In this article, we will learn how to use XF Animation with popup page.
Implementation
Open Visual Studio and select a "New Project".
Now, select Cross-Platform App, give the project a name, and set the project path. Then, click OK.
Select the template as "Blank App" and code sharing as "PCL".
Now, we can install Rg.Plugins.Popup. Right-click on the project, then click on NuGet Package.
Click Browse and search for Rg.Plugins.Popup, select Plugins, and then check the projects in which we want to add this plugin.
Now, we are going to do some XAML coding and writing some button code in the MainPage.xaml:
- <?xml version="1.0" encoding="utf-8" ?>
- <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">
- <StackLayout>
- <!-- Place new controls here -->
- <Label Text="Welcome to Xamarin.Forms Popup Animation!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
- <Button Text="Registration Page" Clicked="Button_Clicked_1" />
- <Button Text="Login Page" Clicked="Button_Clicked" /> </StackLayout>
- </ContentPage>
Then, write code for popup navigation:
- private async void Button_Clicked(object sender, EventArgs e) {
- await Navigation.PushPopupAsync(new LoginPopupPage());
- }
- private async void Button_Clicked_1(object sender, EventArgs e) {
- await Navigation.PushPopupAsync(new RegPage());
- }
Now, we are creating LoginPopupPage.xaml PopupPages.
- <?xml version="1.0" encoding="utf-8" ?>
- <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">
- <pages:PopupPage.Resources>
- <ResourceDictionary>
- <Style x:Key="EntryStyle" TargetType="Entry">
- <Setter Property="PlaceholderColor" Value="#9cdaf1"/><Setter Property="TextColor" Value="#7dbbe6"/>
- </Style>
- </ResourceDictionary>
- </pages:PopupPage.Resources>
- <pages:PopupPage.Animation>
- <animations:ScaleAnimation PositionIn="Bottom" PositionOut="Center" ScaleIn="1" ScaleOut="0.7" DurationIn="700" EasingIn="BounceOut" /> </pages:PopupPage.Animation>
- <ScrollView HorizontalOptions="Center" VerticalOptions="Center">
- <AbsoluteLayout>
- <Frame x:Name="FrameContainer" Margin="15" HorizontalOptions="Center" BackgroundColor="White">
- <StackLayout IsClippedToBounds="True" Padding="10, 5" Spacing="3">
- <Image HorizontalOptions="Center" x:Name="OctocatImage" Margin="10" HeightRequest="150" WidthRequest="150" Source="Logo" />
- <Entry HorizontalOptions="Center" x:Name="UsernameEntry" Style="{StaticResource EntryStyle}" Placeholder="Username" />
- <Entry HorizontalOptions="Center" x:Name="PasswordEntry" Style="{StaticResource EntryStyle}" Placeholder="Password" IsPassword="True" />
- <Button Margin="10, 5" BackgroundColor="#7dbbe6" HorizontalOptions="Fill" x:Name="LoginButton" Text="Login">
-
- <Button.HeightRequest>
-
- <OnPlatform x:TypeArguments="x:Double" Android="50" iOS="30" WinPhone="30"/>
-
- </Button.HeightRequest>
-
- </Button> </StackLayout>
- </Frame>
- <ContentView AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="1, 0, -1, -1">
- <ContentView.GestureRecognizers>
- <TapGestureRecognizer Tapped="OnCloseButtonTapped" /> </ContentView.GestureRecognizers>
- <Image x:Name="CloseImage" HeightRequest="30" WidthRequest="30">
- <Image.Source>
- <OnPlatform x:TypeArguments="ImageSource" Android="close_circle_button.png" iOS="close_circle_button.png" /> </Image.Source>
- </Image>
- </ContentView>
- </AbsoluteLayout>
- </ScrollView>
- </pages:PopupPage>
Now, we are coding in C#:
- using Rg.Plugins.Popup.Extensions;
- using Rg.Plugins.Popup.Pages;
- using System.Threading.Tasks;
- using Xamarin.Forms;
- using Xamarin.Forms.Xaml;
- namespace XFPopupAnimation {
- [XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class LoginPopupPage: PopupPage {
- public LoginPopupPage() {
- InitializeComponent();
- }
- public bool IsAnimationEnabled {
- get;
- private set;
- } = true;
- protected override void OnAppearing() {
- base.OnAppearing();
- FrameContainer.HeightRequest = -1;
- if (!IsAnimationEnabled) {
- CloseImage.Rotation = 0;
- CloseImage.Scale = 1;
- CloseImage.Opacity = 1;
- LoginButton.Scale = 1;
- LoginButton.Opacity = 1;
- UsernameEntry.TranslationX = PasswordEntry.TranslationX = 0;
- UsernameEntry.Opacity = PasswordEntry.Opacity = 1;
- return;
- }
- CloseImage.Rotation = 380;
- CloseImage.Scale = 0.3;
- CloseImage.Opacity = 0;
- LoginButton.Scale = 0.3;
- LoginButton.Opacity = 0;
- UsernameEntry.TranslationX = PasswordEntry.TranslationX = -10;
- UsernameEntry.Opacity = PasswordEntry.Opacity = 0;
- }
- protected override async Task OnAppearingAnimationEnd() {
- if (!IsAnimationEnabled) return;
- var translateLength = 400 u;
- await Task.WhenAll(UsernameEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), UsernameEntry.FadeTo(1), (new Func < Task > (async () => {
- await Task.Delay(200);
- await Task.WhenAll(PasswordEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), PasswordEntry.FadeTo(1));
- }))());
- await Task.WhenAll(CloseImage.FadeTo(1), CloseImage.ScaleTo(1, easing: Easing.SpringOut), CloseImage.RotateTo(0), LoginButton.ScaleTo(1), LoginButton.FadeTo(1));
- }
- protected override async Task OnDisappearingAnimationBegin() {
- if (!IsAnimationEnabled) return;
- var taskSource = new TaskCompletionSource < bool > ();
- var currentHeight = FrameContainer.Height;
- await Task.WhenAll(UsernameEntry.FadeTo(0), PasswordEntry.FadeTo(0), LoginButton.FadeTo(0));
- FrameContainer.Animate("HideAnimation", d => {
- FrameContainer.HeightRequest = d;
- }, start: currentHeight, end: 170, finished: async (d, b) => {
- await Task.Delay(300);
- taskSource.TrySetResult(true);
- });
- await taskSource.Task;
- }
- private void OnCloseButtonTapped(object sender, EventArgs e) {
- CloseAllPopup();
- }
- protected override bool OnBackgroundClicked() {
- CloseAllPopup();
- return false;
- }
- private async void CloseAllPopup() {
- await Navigation.PopAllPopupAsync();
- }
- }
- }
Now, we are creating RegPage.xaml PopupPages.
- <?xml version="1.0" encoding="utf-8" ?>
- <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">
- <pages:PopupPage.Resources>
- <ResourceDictionary>
- <Style x:Key="EntryStyle" TargetType="Entry">
- <Setter Property="PlaceholderColor" Value="#9cdaf1"/><Setter Property="TextColor" Value="#7dbbe6"/>
- </Style>
- </ResourceDictionary>
- </pages:PopupPage.Resources>
- <pages:PopupPage.Animation>
- <animations:ScaleAnimation PositionIn="Bottom" PositionOut="Center" ScaleIn="1" ScaleOut="0.7" DurationIn="700" EasingIn="BounceOut" /> </pages:PopupPage.Animation>
- <ScrollView HorizontalOptions="Center" VerticalOptions="Center">
- <AbsoluteLayout>
- <Frame x:Name="FrameContainer" Margin="15" HorizontalOptions="Center" BackgroundColor="White">
- <StackLayout IsClippedToBounds="True" Padding="10, 5" Spacing="3">
- <Image Source="Logo" HorizontalOptions="Center" x:Name="OctocatImage" Margin="10" HeightRequest="150" WidthRequest="150" />
- <Entry HorizontalOptions="Center" x:Name="FnameEntry" Style="{StaticResource EntryStyle}" Placeholder="First Name" />
- <Entry HorizontalOptions="Center" x:Name="LnameEntry" Style="{StaticResource EntryStyle}" Placeholder="Last Name" />
- <Entry HorizontalOptions="Center" x:Name="UsernameEntry" Style="{StaticResource EntryStyle}" Placeholder="Username" />
- <Entry HorizontalOptions="Center" x:Name="PasswordEntry" Style="{StaticResource EntryStyle}" Placeholder="Password" IsPassword="True" />
- <Button Margin="10, 5" BackgroundColor="#7dbbe6" HorizontalOptions="Fill" x:Name="LoginButton" Text="Login">
-
- <Button.HeightRequest>
-
- <OnPlatform x:TypeArguments="x:Double" Android="50" iOS="30" WinPhone="30"/>
-
- </Button.HeightRequest>
-
- </Button> </StackLayout>
- </Frame>
- <ContentView AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="1, 0, -1, -1">
- <ContentView.GestureRecognizers>
- <TapGestureRecognizer Tapped="OnCloseButtonTapped" /> </ContentView.GestureRecognizers>
- <Image x:Name="CloseImage" HeightRequest="30" WidthRequest="30">
- <Image.Source>
- <OnPlatform x:TypeArguments="ImageSource" Android="close_circle_button.png" iOS="close_circle_button.png" /> </Image.Source>
- </Image>
- </ContentView>
- </AbsoluteLayout>
- </ScrollView>
- </pages:PopupPage>
Write some RegPage Code for animation
We are using override method for the animation with the names:
- override void OnAppearing()
- override async Task OnAppearingAnimationEnd()
- override async Task OnDisappearingAnimationBegin()
- override bool OnBackgroundClicked()
Write the following C# code for the animation that will appear when opening registration page.
- using Rg.Plugins.Popup.Extensions;
- using Rg.Plugins.Popup.Pages;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Xamarin.Forms;
- using Xamarin.Forms.Xaml;
- namespace XFPopupAnimation {
- [XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class RegPage: PopupPage {
- public RegPage() {
- InitializeComponent();
- }
- public bool IsAnimationEnabled {
- get;
- private set;
- } = true;
- protected override void OnAppearing() {
- base.OnAppearing();
- FrameContainer.HeightRequest = -1;
- if (!IsAnimationEnabled) {
- CloseImage.Rotation = 0;
- CloseImage.Scale = 1;
- CloseImage.Opacity = 1;
- LoginButton.Scale = 1;
- LoginButton.Opacity = 1;
- FnameEntry.TranslationX = LnameEntry.TranslationX = UsernameEntry.TranslationX = PasswordEntry.TranslationX = 0;
- FnameEntry.TranslationX = LnameEntry.TranslationX = UsernameEntry.Opacity = PasswordEntry.Opacity = 1;
- return;
- }
- CloseImage.Rotation = 380;
- CloseImage.Scale = 0.3;
- CloseImage.Opacity = 0;
- LoginButton.Scale = 0.3;
- LoginButton.Opacity = 0;
- FnameEntry.TranslationX = LnameEntry.TranslationX = UsernameEntry.TranslationX = PasswordEntry.TranslationX = -10;
- FnameEntry.Opacity = LnameEntry.Opacity = UsernameEntry.Opacity = PasswordEntry.Opacity = 0;
- }
- protected override async Task OnAppearingAnimationEnd() {
- if (!IsAnimationEnabled) return;
- var translateLength = 800 u;
- await Task.WhenAll(FnameEntry.TranslateTo(0, 0, easing: Easing.SpringOut, length: translateLength), FnameEntry.FadeTo(1), (new Func < Task > (async () => {
- await Task.Delay(400);
- 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));
- }))());
- await Task.WhenAll(CloseImage.FadeTo(1), CloseImage.ScaleTo(1, easing: Easing.SpringOut), CloseImage.RotateTo(0), LoginButton.ScaleTo(1), LoginButton.FadeTo(1));
- }
- protected override async Task OnDisappearingAnimationBegin() {
- if (!IsAnimationEnabled) return;
- var taskSource = new TaskCompletionSource < bool > ();
- var currentHeight = FrameContainer.Height;
- await Task.WhenAll(FnameEntry.FadeTo(0), LnameEntry.FadeTo(0), UsernameEntry.FadeTo(0), PasswordEntry.FadeTo(0), LoginButton.FadeTo(0));
- FrameContainer.Animate("HideAnimation", d => {
- FrameContainer.HeightRequest = d;
- }, start: currentHeight, end: 170, finished: async (d, b) => {
- await Task.Delay(500);
- taskSource.TrySetResult(true);
- });
- await taskSource.Task;
- }
- private void OnCloseButtonTapped(object sender, EventArgs e) {
- CloseAllPopup();
- }
- protected override bool OnBackgroundClicked() {
- CloseAllPopup();
- return false;
- }
- private async void CloseAllPopup() {
- await Navigation.PopAllPopupAsync();
- }
- }
- }
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