Xamarin Forms - Transições entre páginas

 Neste artigo vou apresentar o componente SharedTransitions para o Xamarin Forms.

Que tal dar um toque mais profissional nas transições das páginas de suas aplicações Xamarin Forms ?

É esse o objetivo do plugin SharedTransitions  que atua aplicando transições em elementos compartilhados.

O que é uma transição de elemento compartilhado ?

As transições de elemento compartilhado são animações que conectam elementos comuns de uma página para outra.
Uma transição de elemento compartilhado determina como os elementos presentes em duas páginas fazem a transição entre eles. Por exemplo, uma imagem exibida na página A e na página B transita de A para B quando B se torna visível.

Para usar basta fazer o seguinte :

Configura a documentação em : https://github.com/GiampaoloGabba/Xamarin.Plugin.SharedTransitions

Bora pra prática...

Recursos usados:

Criando o projeto Xamarin Forms

Vamos criar um novo projeto Xamarin Forms no VS 2019 Community com o nome XF_Transicoes1.

Nota: Verifique se você precisa atualizar as versões do Xamarin Forms e do Xamarin.Essentials

Você pode ver como criar um projeto no Xamarin Forms neste link: Criar Projeto Xamarin Forms

A seguir inclua o pacote Nuget Xamarin.Plugin.SharedTransitions no projeto:

Abra o arquivo App.xaml.cs e altere o seu código conforme abaixo:

using Plugin.SharedTransitions;
using Xamarin.Forms;
namespace XF_Transicoes1
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new SharedTransitionNavigationPage(new MainPage());
        }
        protected override void OnStart()
        {}
        protected override void OnSleep()
        {}
        protected override void OnResume()
        { }
    }
}

Substituimos o NavigationPage por SharedTransitionNavigationPage para ativar as transições na navegação.

A seguir abra o arquivo MainPage.xaml e inclua o código abaixo:

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="XF_Transicoes1.MainPage"
             Title="Usando SharedTransitions" >
    <StackLayout>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <Button x:Name="BtnLayoutExemplo" Text="Transição com layout" Clicked="BtnLayout_Clicked"/>
            <Button x:Name="BtnCollectionExemplo" Text="Transição com Coleção" Clicked="BtnCollection_Clicked"/>
        </StackLayout>
    </StackLayout>
</ContentPage>

Aqui apenas criamos dois botões na página principal para acionar os dois tipos de transições que iremos mostrar.

E no arquivo MainPage.xaml.cs o código para os eventos Click de cada Button:

public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
        private void BtnLayout_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new Pagina1());
        }
        private void BtnCollection_Clicked(object sender, EventArgs e)
        {
            App.Current.MainPage.Navigation.PushAsync(new PaginaColecao1());
        }
    }

 

Agora vamos criar uma pasta chamada Views no projeto e nesta pasta vamos criar as views Pagina1.xaml e Pagina2.xaml onde vamos aplicar a primeira transição que refere-se a uma transição de layout.

1- Pagina1.xaml - Origem

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
             mc:Ignorable="d"
             x:Class="XF_Transicoes1.Views.Pagina1"
             Title="Transição Layout - Origem">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="110" />
            <RowDefinition Height="110" />
            <RowDefinition Height="110" />
            <RowDefinition Height="110" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Image Source="bemtevi.jpg" Grid.Row="0"
                                    sharedTransitions:Transition.Name="bemtevi"
                                    BackgroundColor="Transparent"
                                    Aspect="AspectFit"
                                    Margin="5"
                                    HeightRequest="100" WidthRequest="100"
                                    HorizontalOptions="Center" VerticalOptions="Center" />
        <Image Source="anu.jpg" Grid.Row="1"
               sharedTransitions:Transition.Name="anu"
               BackgroundColor="Transparent"
               Aspect="AspectFit"
               Margin="5"
               HeightRequest="100" WidthRequest="100"
               HorizontalOptions="Center" VerticalOptions="Center" />
        <BoxView Grid.Row="2"
                 sharedTransitions:Transition.Name="boxview1"
                 BackgroundColor="BlueViolet"
                 Margin="5"
                 HeightRequest="100" WidthRequest="100"
                 HorizontalOptions="Center" VerticalOptions="Center" />
        <BoxView Grid.Row="3"
                 sharedTransitions:Transition.Name="boxview2"
                 BackgroundColor="DarkBlue"
                 Margin="5"
                 CornerRadius="50"
                 HeightRequest="100" WidthRequest="100"
                 HorizontalOptions="Center" VerticalOptions="Center" />
        <Button x:Name="BtnAction" Grid.Row="4"
                Text="Fazer Transições"
                Clicked="BtnAction_Clicked"
                HorizontalOptions="Center" VerticalOptions="Center" />
    </Grid>
</ContentPage>

2- Pagina2.xaml - Destino

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
             mc:Ignorable="d"
             x:Class="XF_Transicoes1.Views.Pagina2"
             Title="Transição Layout - Destino">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="220" />
            <RowDefinition Height="220" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Image Source="bemtevi.jpg" Grid.Row="0" Grid.Column="0"
                                    sharedTransitions:Transition.Name="bemtevi"
                                    BackgroundColor="Transparent"
                                    Aspect="AspectFit"
                                    Margin="10"
                                    HorizontalOptions="Center" VerticalOptions="Center" />
        <Image Source="anu.jpg" Grid.Row="1" Grid.Column="0"
               sharedTransitions:Transition.Name="anu"
               BackgroundColor="Transparent"
               Aspect="AspectFit"
               Margin="10"
               HeightRequest="200" WidthRequest="200"
               HorizontalOptions="Center" VerticalOptions="Center" />
        <BoxView Grid.Row="0" Grid.Column="1"
                 sharedTransitions:Transition.Name="boxview1"
                 BackgroundColor="BlueViolet"
                 Margin="10"
                 CornerRadius="75"
                 HeightRequest="150" WidthRequest="150"
                 HorizontalOptions="Center" VerticalOptions="Center" />
        <BoxView Grid.Row="1" Grid.Column="1"
                 sharedTransitions:Transition.Name="boxview2"
                 BackgroundColor="DarkBlue"
                 Margin="10"
                 HeightRequest="150" WidthRequest="150"
                 HorizontalOptions="Center" VerticalOptions="Center" />
    </Grid>
</ContentPage>

Estamos realizando a transição da Pagina1 para a Pagina2. Observe que:

1- Ambos os arquivos XAML devem declarar o namespace
 xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"

2- Estamos atribuindo um identificador único nas views que queremos transacionar. Este identificador deve ser o mesmo na página de origem e na de destino. Fizemos isso usando a propriedade:
 sharedTransitions:Transition.Name = "nome"

Executando o projeto teremos o seguinte resultado:

Fazendo transições em Coleções

Para realizar as transições com itens de coleções podemos usar a propriedade Transition.Group.

Assim, cada item da coleção deve ter as propriedades Transition.Name e Transition.Group atribuídas e o último deve ser exclusivo na lista, portanto, é recomendável atribuí-lo ao identificador exclusivo do item.

Vejamos um exemplo prático usando coleções.

Vamos incluir no projeto Android, em Resources/drawable as imagens: monkey1.jpg, monkey2.jpg, monkey3.jpg, monkey4.jpg, monkey5.jpg

Crie uma pasta
Models no projeto e nesta pasta crie a classe Monkey que será nosso modelo para exibir as informações em uma coleção:

public class Monkey
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Detail { get; set; }
        public string ImageUrl { get; set; }
    }

A seguir vamos criar na pasta Views as views PaginaColecao1.xaml e PaginaColecao2.xaml onde vamos aplicar a transição.

1- PaginaColecao1.xaml - Origem

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
             sharedTransitions:SharedTransitionNavigationPage.TransitionSelectedGroup="{Binding SelectedMonkey.Id}"
             sharedTransitions:SharedTransitionNavigationPage.BackgroundAnimation="Fade"
             sharedTransitions:SharedTransitionNavigationPage.TransitionDuration="300"
             x:Class="XF_Transicoes1.Views.PaginaColecao1">
    <Grid>
        <CollectionView x:Name="CvMonkeys"
                        SelectionMode="Single"
                        SelectedItem="{Binding SelectedMonkey}">            
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="4*" />
                        </Grid.ColumnDefinitions>
                        <Image Grid.RowSpan="2"
                               BackgroundColor="Transparent"
                               Source="{Binding ImageUrl}"
                               Aspect="AspectFit"
                               sharedTransitions:Transition.Name="MonkeyImage"
                               sharedTransitions:Transition.Group="{Binding Id}"
                               Margin="2"
                               VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                        </Image>
                        <Label Grid.Column="1" 
                               Text="{Binding Name}"
                               FontSize="Title"
                               sharedTransitions:Transition.Name="MonkeyTitle"
                               sharedTransitions:Transition.Group="{Binding Id}"
                               HorizontalOptions="Start" VerticalOptions="Center" />
                        <Label Grid.Column="1" Grid.Row="1"
                               Text="{Binding Detail}"
                               FontSize="Subtitle"
                               sharedTransitions:Transition.Name="MonkeySubtitle"
                               sharedTransitions:Transition.Group="{Binding Id}"
                               HorizontalOptions="Start" VerticalOptions="Center" />
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>

Estamos definindo na página de origem a referência ao SharedTransitions,

 xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
 sharedTransitions:SharedTransitionNavigationPage.TransitionSelectedGroup="{Binding SelectedMonkey.Id}"
 sharedTransitions:SharedTransitionNavigationPage.BackgroundAnimation="Fade"
 sharedTransitions:SharedTransitionNavigationPage.TransitionDuration="300"

2- PaginaColecao2.xaml - Destino

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:sharedTransitions="clr-namespace:Plugin.SharedTransitions;assembly=Plugin.SharedTransitions"
             mc:Ignorable="d"
             x:Class="XF_Transicoes1.Views.PaginaColecao2">
     <StackLayout>

        <Image  BackgroundColor="Transparent"
                                     Source="{Binding Monkey.ImageUrl}"
                                     Aspect="AspectFit"
                                     sharedTransitions:Transition.Name="MonkeyImage"
                                     Margin="20"
                                     HeightRequest="200" WidthRequest="200"
                                     VerticalOptions="Start" HorizontalOptions="Center">
        </Image>
        <Label Text="{Binding Monkey.Name}"
               FontSize="Title"
               sharedTransitions:Transition.Name="MonkeyTitle"
               HorizontalOptions="Center" VerticalOptions="Center" />
        <Label Text="{Binding Monkey.Detail}"
               FontSize="Subtitle"
               sharedTransitions:Transition.Name="MonkeySubtitle"
               HorizontalOptions="Center" VerticalOptions="Center" />
    </StackLayout> 
</ContentPage>

Eu não me preocupei em criar um aparência mais elaborada para interface pois o objetivo é mostrar a transição funcionando.

Executando o projeto e acionando a transição para a coleção teremos o resultado abaixo:

Pegue o código do projeto compartilhado aqui :  XF_Transicoes1.zip   

"Os meus olhos estão continuamente no Senhor, pois ele tirará os meus pés da rede."
Salmos 25:15

Referências:


José Carlos Macoratti