Xamarin Forms -  Hierarquia do Shell
 Neste artigo vou apresentar alguns exemplos de hierarquia usando o novo recurso Shell do Xamarin Forms.

O Xamarin.Forms Shell é uma nova maneira de criar e arquitetar facilmente os aplicativos Xamarin Forms, permitindo que você se concentre na carga de trabalho do código do aplicativo.

Eu já apresentei o Shell nestes dois artigos:

  1. Xamarin Forms 4.0 - Apresentando o Shell - I
  2. Xamarin Forms 4.0 - Apresentando o Shell - II

Entender a hierarquia do Shell a princípio pode parecer um tanto confuso. Ele representa uma hierarquia complexa e fornece mecanismos poderosos para minimizar a quantidade código xaml padrão necessário para criar hierarquias ricas.

Nos exemplos que irei mostrar a princípio não vou usar o template ShellContent, que serão discutidos em outras partes da especificação.

A não utilização adequada do ShellContents com um ContentTemplate resultará no carregamento de todas as páginas na inicialização, o que afetará negativamente o desempenho da inicialização.

Felizmente, usar o ShellContents com o ContentTemplates e mais simples do que não usá-lo.

Recursos usados:

Criando o projeto no Visual Studio 2019 Community

Abra o  VS 2019 Community e clique em Create New Project e a seguir escolha:

Clique em Next e informe o nome XF_ShellHierarquia;

A seguir clique no botão Create :

A seguir selecione o template Blank e a plataforma Android e clique no botão OK:

Pronto, nosso projeto já esta criado.

No projeto Android na pasta Resource/drawable vamos incluir as imagens que iremos usar no projeto:

Vamos criar uma pasta Views no projeto onde vamos incluir todas as nossas páginas.

Para criar uma aplicação Shell basta criar um arquivo XAML que seja uma subclasse da classe Shell e definir a propriedade MainPage da classe App do aplicativo para o objeto Shell na subclasse descrevendo a hierarquia visual na classe Shell da subclasse.

O exemplo de código a seguir mostra um arquivo AppShell1.xaml recém-criado:

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       x:Class="Xaminals.AppShell1">
</Shell>
O exemplo a seguir mostra o arquivo code-behind, AppShell1.xaml.cs:
using Xamarin.Forms;
namespace Xaminals
{
    public partial class AppShell1 : Shell
    {
        public AppShell1()
        {
            InitializeComponent();
        }
    }
}

Vamos criar na pasta Views as seguitens páginas que serão usadas na página AppShell1.xaml:

  1. HomePage.xaml
  2. NotificacaoPage.xaml
  3. ConfiguracaoPage.xaml.

Lembrando que no arquivo App.xaml.cs devemos definir o código para inicializar a página:

        public App()
        {
            InitializeComponent();
            MainPage = new AppShell1();
        }

Agora vamos ver isso funcionando na prática.

Shell com apenas uma página

<?xml version="1.0" encoding="utf-8" ?>
<Shell 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:local="clr-namespace:XF_ShellHierarquia.Views"
      mc:Ignorable="d"
     x:Class="XF_ShellHierarquia.Views.AppShell1">

    <ShellItem>
        <ShellSection>
            <ShellContent>
                <local:HomePage />
            </ShellContent>
        </ShellSection>
    </ShellItem>
</Shell>

A seguir temos uma variação desta página onde desabilitamos o menu Flyout definindo FlyoutBehavior="Disabled" :

<?xml version="1.0" encoding="utf-8" ?>
<Shell 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:local="clr-namespace:XF_ShellHierarquia.Views"
      mc:Ignorable="d"
      FlyoutBehavior="Disabled"
     x:Class="XF_ShellHierarquia.Views.AppShell1">

    <ShellItem>
        <ShellSection>
            <ShellContent>
                <local:HomePage />
            </ShellContent>
        </ShellSection>
    </ShellItem>
</Shell>

Shell com duas abas inferiores e duas páginas

Temos aqui duas abas inferiores definidas pelos ícones e cada aba aciona a sua respectiva página:

<?xml version="1.0" encoding="utf-8" ?>
<Shell 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:local="clr-namespace:XF_ShellHierarquia.Views"
    mc:Ignorable="d"
   FlyoutBehavior="Disabled"
   x:Class="XF_ShellHierarquia.Views.AppShell1">
    <ShellItem>
        <ShellSection Title="Home" Icon="home.png">
            <ShellContent>
                <local:HomePage />
            </ShellContent>
        </ShellSection>
        <ShellSection Title="Notificações" Icon="notificacao.png">
            <ShellContent>
                <local:NotificacaoPage />
            </ShellContent>
        </ShellSection>
    </ShellItem>
</Shell

Incluimos duas seções ShellSection ao ShellItem para exibir duas guias na parte inferior definindo o título e o ícone utilizado.

Shell com duas abas inferiores sendo uma com duas abas superiores

Temos aqui duas abas inferiores sendo que a aba Notificações possui duas abas superiores.

<?xml version="1.0" encoding="utf-8" ?>
<Shell 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:local="clr-namespace:XF_ShellHierarquia.Views"
             mc:Ignorable="d"
             FlyoutBehavior="Disabled"
             x:Class="XF_ShellHierarquia.Views.AppShell1">
    <ShellItem>
        <ShellSection Title="Home" Icon="home.png">
            <ShellContent>
                <local:HomePage />
            </ShellContent>
        </ShellSection>
        <ShellSection Title="Notificações" Icon="notificao.png">
            <ShellContent Title="Gerais">
                <local:NotificacaoPage />
            </ShellContent>
            <ShellContent Title="Configurações">
                <local:ConfiguracaoPage />
            </ShellContent>
        </ShellSection>
    </ShellItem>
</Shell>

Aqui incluimos uma seção ShellContent dentro da ShellSection Notificações incluimos uma guia superior e as páginas podem ser selecionadas na guia inferior.

Shell com menu Flyout ativado e cabeçalho

Vamos ativar o menu Flyout e definir um cabeçalho criando o arquivo FlyoutHeader.xaml na pasta Views com o tipo Content View:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView 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_ShellHierarquia.Views.FlyoutHeader">
    
    <Grid BackgroundColor="White">
        <Frame CornerRadius="50" 
                       HeightRequest="100"
                       WidthRequest="100"
                       HorizontalOptions="Center"
                       Padding="0"
                       IsClippedToBounds="True">
            <Image Aspect="AspectFit" Source="maco.jpg" Opacity="1.0" 
                   VerticalOptions="Center"
                   HorizontalOptions="Center"/>
        </Frame>
    </Grid>
    
</ContentView>

A seguir temos o código do arquivo AppShell1.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<Shell 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:local="clr-namespace:XF_ShellHierarquia.Views"
             mc:Ignorable="d"
             x:Class="XF_ShellHierarquia.Views.AppShell1">
    <Shell.FlyoutHeader>
        <local:FlyoutHeader />
    </Shell.FlyoutHeader>
    <ShellItem Title="Home" Icon="home.png">
        <ShellSection>
            <ShellContent>
                <local:HomePage />
            </ShellContent>
        </ShellSection>
    </ShellItem>
    <ShellItem Title="Notificações" Icon="notificacao.png">
        <ShellSection>
            <ShellContent>
                <local:NotificacaoPage />
            </ShellContent>
        </ShellSection>
    </ShellItem>

</Shell>

Ativamos o submenu Flyout e agora o usuário pode alternar entre as duas páginas usando o menu.

Usando a sintaxe abreviada

Agora que mostramos os níveis da hierarquia com detalhes, podemos simplificar o código usado.

O Shell contém apenas ShellItems que contêm ShellSections que, por sua vez, contêm ShellContents. No entanto, existem operadores de conversão implícitos para permitir o empacotamento automático, e por isso podemos escrever um código mais enxuto conforme mostramos a seguir:

Shell com apenas uma página

<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
      xmlns:local="clr-namespace:XF_ShellHierarquia.Views"
     x:Class="XF_ShellHierarquia.Views.AppShell1">

      <local:HomePage />

 </Shell>

Shell com duas abas inferiores e duas páginas

<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:local="clr-namespace:XF_ShellHierarquia.Views"
            FlyoutBehavior="Disabled"
            x:Class="XF_ShellHierarquia.Views.AppShell1">

           <ShellItem>
               <local:HomePage Icon="home.png" />
                <local:NotificacaoPage Icon="notificacao.png" />
            </ShellItem>

</Shell>

Shell com duas abas inferiores sendo uma com duas abas superiores

<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:local="clr-namespace:XF_ShellHierarquia.Views"
     FlyoutBehavior="Disabled"
     x:Class="XF_ShellHierarquia.Views.AppShell1">
    <ShellItem>
        <local:HomePage Icon="home.png" />
        <ShellSection Title="Notifications" Icon="notificacao.png">
            <local:NotificacaoPage />
            <local:ConfiguracaoPage />
        </ShellSection>
    </ShellItem>
</Shell>

Shell com menu Flyout ativado e cabeçalho

<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:local="clr-namespace:XF_ShellHierarquia.Views"
     x:Class="XF_ShellHierarquia.Views.AppShell1">   

    <Shell.FlyoutHeader>
        <local:FlyoutHeader />
    </Shell.FlyoutHeader>

  <ShellItem>
    <local:HomePage Icon="home.png" />
    <local:NotificacaoPage Icon="notificacao.png" />
  </ShellItem>

</Shell>

Pegue o código do projeto compartilhado aqui :  XF_ShellHierarquia.zip (sem as referências)

"O temor do Senhor é fonte de vida, para desviar dos laços da morte."
Provérbios 14:26,27

Referências:


José Carlos Macoratti