Xamarin.Forms Submenu shell

Baixar exemplo Baixar o exemplo

A experiência de navegação fornecida pelo Xamarin.Forms Shell é baseada em submenus e guias. Um submenu é o menu raiz opcional para um aplicativo Shell e é totalmente personalizável. Ele é acessível por meio de um ícone ou passando o dedo do lado da tela. O submenu consiste em um cabeçalho opcional, itens de submenu, itens de menu opcionais e um rodapé opcional:

Captura de tela de um submenu anotado do Shell

Itens de submenu

Um ou mais itens de submenu podem ser adicionados ao submenu e cada item de submenu é representado por um objeto FlyoutItem. Cada FlyoutItem objeto deve ser um filho do objeto subclasse Shell . Os itens de submenu aparecem na parte superior do submenu quando um cabeçalho de submenu não está presente.

O exemplo a seguir cria um submenu contendo dois itens de submenu:

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:controls="clr-namespace:Xaminals.Controls"
       xmlns:views="clr-namespace:Xaminals.Views"
       x:Class="Xaminals.AppShell">
    <FlyoutItem Title="Cats"
                Icon="cat.png">
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:CatsPage}" />
       </Tab>
    </FlyoutItem>
    <FlyoutItem Title="Dogs"
                Icon="dog.png">
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:DogsPage}" />
       </Tab>
    </FlyoutItem>
</Shell>

A FlyoutItem.Title propriedade, do tipo string, define o título do item de submenu. A FlyoutItem.Icon propriedade, do tipo ImageSource, define o ícone do item de submenu:

Captura de tela de um aplicativo shell de duas páginas com itens de submenu, no iOS e no Android

Neste exemplo, cada ShellContent objeto só pode ser acessado por meio de itens de submenu, e não por meio de guias. Isso ocorre porque, por padrão, as guias só serão exibidas se o item de submenu contiver mais de uma guia.

Importante

Em um aplicativo Shell, as páginas são criadas sob demanda em resposta à navegação. Isso é feito usando a DataTemplate extensão de marcação para definir a ContentTemplate propriedade de cada ShellContent objeto como um ContentPage objeto .

O Shell tem operadores de conversão implícita que permitem que a hierarquia visual no Shell seja simplificada, sem a introdução de modos de exibição adicionais na árvore visual. Isso é possível porque um objeto Shell na subclasse só pode conter objetos FlyoutItem ou um objeto TabBar, que só podem conter objetos Tab, que só podem conter objetos ShellContent. Esses operadores de conversão implícita podem ser usados para remover os objetos FlyoutItem e Tab do exemplo anterior:

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:controls="clr-namespace:Xaminals.Controls"
       xmlns:views="clr-namespace:Xaminals.Views"
       x:Class="Xaminals.AppShell">
   <ShellContent Title="Cats"
                 Icon="cat.png"
                 ContentTemplate="{DataTemplate views:CatsPage}" />
   <ShellContent Title="Dogs"
                 Icon="dog.png"
                 ContentTemplate="{DataTemplate views:DogsPage}" />
</Shell>

Essa conversão implícita encapsula automaticamente cada ShellContent objeto em Tab objetos , que são encapsulados em FlyoutItem objetos .

Observação

Todos os FlyoutItem objetos em um objeto subclasse são adicionados automaticamente à coleção, que Shell.FlyoutItems define a lista de itens que serão mostrados no submenuShell.

Opções de exibição do submenu

A FlyoutItem.FlyoutDisplayOptions propriedade configura como um item de submenu e seus filhos são exibidos no submenu. Essa propriedade deve ser definida como um FlyoutDisplayOptions membro de enumeração:

  • AsSingleItem, indica que o item ficará visível como um item único. Este é o valor padrão da propriedade FlyoutDisplayOptions.
  • AsMultipleItems, indica que o item e seus filhos ficarão visíveis no submenu como um grupo de itens.

Um item de submenu para cada Tab objeto dentro de um FlyoutItem pode ser exibido definindo a FlyoutItem.FlyoutDisplayOptions propriedade AsMultipleItemscomo :

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:controls="clr-namespace:Xaminals.Controls"
       xmlns:views="clr-namespace:Xaminals.Views"
       FlyoutHeaderBehavior="CollapseOnScroll"
       x:Class="Xaminals.AppShell">

    <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
        <Tab Title="Domestic"
             Icon="paw.png">
            <ShellContent Title="Cats"
                          Icon="cat.png"
                          ContentTemplate="{DataTemplate views:CatsPage}" />
            <ShellContent Title="Dogs"
                          Icon="dog.png"
                          ContentTemplate="{DataTemplate views:DogsPage}" />
        </Tab>
        <ShellContent Title="Monkeys"
                      Icon="monkey.png"
                      ContentTemplate="{DataTemplate views:MonkeysPage}" />
        <ShellContent Title="Elephants"
                      Icon="elephant.png"
                      ContentTemplate="{DataTemplate views:ElephantsPage}" />  
        <ShellContent Title="Bears"
                      Icon="bear.png"
                      ContentTemplate="{DataTemplate views:BearsPage}" />
    </FlyoutItem>

    <ShellContent Title="About"
                  Icon="info.png"
                  ContentTemplate="{DataTemplate views:AboutPage}" />    
</Shell>

Neste exemplo, os itens do submenu foram criados para o objeto Tab que é um filho do objeto FlyoutItem e os objetos de ShellContent que são filhos do objeto FlyoutItem. Isso ocorre porque cada objeto ShellContent que é um filho do objeto FlyoutItem é automaticamente encapsulado em um objeto Tab. Além disso, um item de submenu é criado para o objeto final ShellContent , que é encapsulado automaticamente em um Tab objeto e, em seguida, em um FlyoutItem objeto .

Observação

As guias são exibidas quando um FlyoutItem contém mais de um ShellContent objeto .

Isso resulta nos seguintes itens de submenu:

Captura de tela do submenu que contém objetos FlyoutItem, no submenu shell do iOS e do Android

Definir a aparência de FlyoutItem

A aparência de cada FlyoutItem pode ser personalizada definindo a propriedade anexada Shell.ItemTemplate como um DataTemplate:

<Shell ...>
    ...
    <Shell.ItemTemplate>
        <DataTemplate>
            <Grid ColumnDefinitions="0.2*,0.8*">
                <Image Source="{Binding FlyoutIcon}"
                       Margin="5"
                       HeightRequest="45" />
                <Label Grid.Column="1"
                       Text="{Binding Title}"
                       FontAttributes="Italic"
                       VerticalTextAlignment="Center" />
            </Grid>
        </DataTemplate>
    </Shell.ItemTemplate>
</Shell>

Este exemplo exibe o título de cada objeto FlyoutItem em itálico:

Captura de tela de objetos FlyoutItem com modelo, no iOS e no Android

Como Shell.ItemTemplate é uma propriedade anexada, modelos diferentes podem ser anexados a objetos específicos FlyoutItem .

Observação

O Shell fornece as propriedades Title e FlyoutIcon para o BindingContext do ItemTemplate.

Além disso, o Shell inclui três classes de estilo, que são aplicadas automaticamente a FlyoutItem objetos . Para obter mais informações, consulte Objetos Style FlyoutItem e MenuItem.

Modelo padrão para FlyoutItems

O padrão DataTemplate usado para cada FlyoutItem um é mostrado abaixo:

<DataTemplate x:Key="FlyoutTemplate">
    <Grid x:Name="FlyoutItemLayout"
          HeightRequest="{x:OnPlatform Android=50}"
          ColumnSpacing="{x:OnPlatform UWP=0}"
          RowSpacing="{x:OnPlatform UWP=0}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal" />
                    <VisualState x:Name="Selected">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor"
                                    Value="{x:OnPlatform Android=#F2F2F2, iOS=#F2F2F2}" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </VisualStateManager.VisualStateGroups>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="{x:OnPlatform Android=54, iOS=50, UWP=Auto}" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Image x:Name="FlyoutItemImage"
               Source="{Binding FlyoutIcon}"
               VerticalOptions="Center"
               HorizontalOptions="{x:OnPlatform Default=Center, UWP=Start}"
               HeightRequest="{x:OnPlatform Android=24, iOS=22, UWP=16}"
               WidthRequest="{x:OnPlatform Android=24, iOS=22, UWP=16}">
            <Image.Margin>
                <OnPlatform x:TypeArguments="Thickness">
                    <OnPlatform.Platforms>
                        <On Platform="UWP"
                            Value="12,0,12,0" />
                    </OnPlatform.Platforms>
                </OnPlatform>
            </Image.Margin>
        </Image>
        <Label x:Name="FlyoutItemLabel"
               Grid.Column="1"
               Text="{Binding Title}"
               FontSize="{x:OnPlatform Android=14, iOS=Small}"
               HorizontalOptions="{x:OnPlatform UWP=Start}"
               HorizontalTextAlignment="{x:OnPlatform UWP=Start}"
               FontAttributes="{x:OnPlatform iOS=Bold}"
               VerticalTextAlignment="Center">
            <Label.TextColor>
                <OnPlatform x:TypeArguments="Color">
                    <OnPlatform.Platforms>
                        <On Platform="Android"
                            Value="#D2000000" />
                    </OnPlatform.Platforms>
                </OnPlatform>
            </Label.TextColor>
            <Label.Margin>
                <OnPlatform x:TypeArguments="Thickness">
                    <OnPlatform.Platforms>
                        <On Platform="Android"
                            Value="20, 0, 0, 0" />
                    </OnPlatform.Platforms>
                </OnPlatform>
            </Label.Margin>
            <Label.FontFamily>
                <OnPlatform x:TypeArguments="x:String">
                    <OnPlatform.Platforms>
                        <On Platform="Android"
                            Value="sans-serif-medium" />
                    </OnPlatform.Platforms>
                </OnPlatform>
            </Label.FontFamily>
        </Label>
    </Grid>
</DataTemplate>

Esse modelo pode ser usado como base para fazer alterações no layout de submenu existente e também mostra os estados visuais implementados para itens de submenu.

Além disso, os Gridelementos , Imagee Label têm x:Name valores e, portanto, podem ser direcionados com o Gerenciador de Estado Visual. Para obter mais informações, consulte Definir estado em vários elementos.

Observação

O mesmo modelo também pode ser usado para MenuItem objetos .

Substituir conteúdo do submenu

Os itens de submenu, que representam o conteúdo do submenu, podem opcionalmente ser substituídos pelo seu próprio conteúdo definindo a propriedade associável Shell.FlyoutContent como um object:

<Shell ...
       x:Name="shell">
    ...
    <Shell.FlyoutContent>
        <CollectionView BindingContext="{x:Reference shell}"
                        IsGrouped="True"
                        ItemsSource="{Binding FlyoutItems}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Label Text="{Binding Title}"
                           TextColor="White"
                           FontSize="Large" />
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Shell.FlyoutContent>
</Shell>

Neste exemplo, o conteúdo do submenu é substituído por um CollectionView que exibe o título de cada item na FlyoutItems coleção.

Observação

A FlyoutItems propriedade, na Shell classe , é uma coleção somente leitura de itens de submenu.

Como alternativa, o conteúdo do submenu pode ser definido definindo a propriedade associável Shell.FlyoutContentTemplate como um DataTemplate:

<Shell ...
       x:Name="shell">
    ...
    <Shell.FlyoutContentTemplate>
        <DataTemplate>
            <CollectionView BindingContext="{x:Reference shell}"
                            IsGrouped="True"
                            ItemsSource="{Binding FlyoutItems}">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Label Text="{Binding Title}"
                               TextColor="White"
                               FontSize="Large" />
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </DataTemplate>
    </Shell.FlyoutContentTemplate>
</Shell>

Importante

Opcionalmente, um cabeçalho de submenu pode ser exibido acima do conteúdo do submenu, e um rodapé de submenu pode ser exibido opcionalmente abaixo do conteúdo do submenu. Se o conteúdo do submenu for rolável, o Shell tentará respeitar o comportamento de rolagem do cabeçalho do submenu.

Os itens do menu podem ser opcionalmente adicionados ao submenu, e cada item do menu é representado por um objeto MenuItem. A posição dos objetos MenuItem no submento depende da ordem de declaração deles na hierarquia visual do Shell. Portanto, todos os objetos MenuItem declarados antes dos objetos FlyoutItemaparecerão antes dos objetos FlyoutItem no submenu, e todos os objetos MenuItemdeclarados após os objetos FlyoutItem aparecerão após os objetos FlyoutItem no submenu.

A classe MenuItem tem um evento Clicked e uma propriedade Command. Portanto, os objetos MenuItem permitem cenários que executam uma ação em resposta ao MenuItem que está sendo tocado.

Os objetos MenuItem podem ser adicionados ao submenu, conforme mostrado no exemplo a seguir:

<Shell ...>
    ...            
    <MenuItem Text="Help"
              IconImageSource="help.png"
              Command="{Binding HelpCommand}"
              CommandParameter="https://learn.microsoft.com/xamarin/xamarin-forms/app-fundamentals/shell" />    
</Shell>

Este exemplo adiciona um MenuItem objeto ao submenu, abaixo de todos os itens de submenu:

Captura de tela do submenu que contém um objeto MenuItem, no iOS e no Android

O MenuItem objeto executa um ICommand chamado HelpCommand, que abre a URL especificada pela CommandParameter propriedade no navegador da Web do sistema.

Observação

O BindingContext de cada MenuItem é herdado do objeto Shell na subclasse.

Definir a aparência do MenuItem

A aparência de cada MenuItem pode ser personalizada definindo a propriedade anexada Shell.MenuItemTemplate como um DataTemplate:

<Shell ...>
    <Shell.MenuItemTemplate>
        <DataTemplate>
            <Grid ColumnDefinitions="0.2*,0.8*">
                <Image Source="{Binding Icon}"
                       Margin="5"
                       HeightRequest="45" />
                <Label Grid.Column="1"
                       Text="{Binding Text}"
                       FontAttributes="Italic"
                       VerticalTextAlignment="Center" />
            </Grid>
        </DataTemplate>
    </Shell.MenuItemTemplate>
    ...
    <MenuItem Text="Help"
              IconImageSource="help.png"
              Command="{Binding HelpCommand}"
              CommandParameter="https://learn.microsoft.com/xamarin/xamarin-forms/app-fundamentals/shell" />  
</Shell>

Este exemplo anexa o DataTemplate a cada MenuItem objeto, exibindo o título do MenuItem objeto em itálico:

Captura de tela de objetos MenuItem com modelo, no iOS e no Android

Como Shell.MenuItemTemplate é uma propriedade anexada, modelos diferentes podem ser anexados a objetos específicos MenuItem .

Observação

O Shell fornece as propriedades Text e IconImageSource para o BindingContext do MenuItemTemplate. Você também pode usar Title no lugar de Text e Icon no lugar do IconImageSource qual permitirá reutilizar o mesmo modelo para itens de menu e itens de submenu.

O modelo padrão para FlyoutItem objetos também pode ser usado para MenuItem objetos . Para obter mais informações, consulte Modelo padrão para FlyoutItems.

Objetos Style FlyoutItem e MenuItem

O Shell inclui três classes de estilo, que são aplicadas automaticamente aos FlyoutItem objetos e MenuItem . Os nomes de classe de estilo são FlyoutItemLabelStyle, FlyoutItemImageStylee FlyoutItemLayoutStyle.

O XAML a seguir mostra um exemplo de definição de estilos para essas classes de estilo:

<Style TargetType="Label"
       Class="FlyoutItemLabelStyle">
    <Setter Property="TextColor"
            Value="Black" />
    <Setter Property="HeightRequest"
            Value="100" />
</Style>

<Style TargetType="Image"
       Class="FlyoutItemImageStyle">
    <Setter Property="Aspect"
            Value="Fill" />
</Style>

<Style TargetType="Layout"
       Class="FlyoutItemLayoutStyle"
       ApplyToDerivedTypes="True">
    <Setter Property="BackgroundColor"
            Value="Teal" />
</Style>

Esses estilos serão aplicados automaticamente aos FlyoutItem objetos e MenuItem , sem precisar definir suas StyleClass propriedades para os nomes de classe de estilo.

Além disso, classes de estilo personalizado podem ser definidas e aplicadas a FlyoutItem objetos e MenuItem . Para obter mais informações sobre classes de estilo, consulte Xamarin.Forms Classes de estilo.

Cabeçalho do submenu

O cabeçalho do submenu é o conteúdo que, opcionalmente, aparece na parte superior do submenu, com sua aparência sendo definida por um object que pode ser definido com a propriedade associável Shell.FlyoutHeader :

<Shell ...>
    <Shell.FlyoutHeader>
        <controls:FlyoutHeader />
    </Shell.FlyoutHeader>
</Shell>

O tipo FlyoutHeader é mostrado no exemplo a seguir:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Xaminals.Controls.FlyoutHeader"
             HeightRequest="200">
    <Grid BackgroundColor="Black">
        <Image Aspect="AspectFill"
               Source="xamarinstore.jpg"
               Opacity="0.6" />
        <Label Text="Animals"
               TextColor="White"
               FontAttributes="Bold"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />
    </Grid>
</ContentView>

Como resultado, teremos o cabeçalho do submenu a seguir:

Captura de tela do cabeçalho do submenu

Como alternativa, a aparência do cabeçalho de submenu pode ser definida definindo a Shell.FlyoutHeaderTemplate propriedade associável como um DataTemplate:

<Shell ...>
    <Shell.FlyoutHeaderTemplate>
        <DataTemplate>
            <Grid BackgroundColor="Black"
                  HeightRequest="200">
                <Image Aspect="AspectFill"
                       Source="xamarinstore.jpg"
                       Opacity="0.6" />
                <Label Text="Animals"
                       TextColor="White"
                       FontAttributes="Bold"
                       HorizontalTextAlignment="Center"
                       VerticalTextAlignment="Center" />
            </Grid>            
        </DataTemplate>
    </Shell.FlyoutHeaderTemplate>
</Shell>

Por padrão, o cabeçalho do submenu ficará fixo no submenu enquanto o conteúdo abaixo poderá ser rolado se houver itens suficientes. No entanto, esse comportamento pode ser alterado definindo-se a propriedade associável Shell.FlyoutHeaderBehavior como um dos membros da enumeração FlyoutHeaderBehavior:

  • Default – indica que o comportamento padrão da plataforma será usado. Este é o valor padrão da propriedade FlyoutHeaderBehavior.
  • Fixed – indica que o cabeçalho do submenu permanece sempre inalterado e visível.
  • Scroll – indica que o cabeçalho do submenu rola para fora da exibição conforme o usuário rola os itens.
  • CollapseOnScroll – indica que o cabeçalho do submenu é recolhido, tornando-se apenas um título à medida que o usuário rola os itens.

O exemplo a seguir mostra como recolher o cabeçalho do submenu à medida que o usuário rola a tela:

<Shell ...
       FlyoutHeaderBehavior="CollapseOnScroll">
    ...
</Shell>

O rodapé de submenu é o conteúdo que, opcionalmente, aparece na parte inferior do submenu, com sua aparência sendo definida por um object que pode ser definido com a Shell.FlyoutFooter propriedade associável:

<Shell ...>
    <Shell.FlyoutFooter>
        <controls:FlyoutFooter />
    </Shell.FlyoutFooter>
</Shell>

O tipo FlyoutFooter é mostrado no exemplo a seguir:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sys="clr-namespace:System;assembly=netstandard"
             x:Class="Xaminals.Controls.FlyoutFooter">
    <StackLayout>
        <Label Text="Xaminals"
               TextColor="GhostWhite"
               FontAttributes="Bold"
               HorizontalOptions="Center" />
        <Label Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat='{0:MMMM dd, yyyy}'}"
               TextColor="GhostWhite"
               HorizontalOptions="Center" />
    </StackLayout>
</ContentView>

Isso resulta no seguinte rodapé de submenu:

Captura de tela do rodapé do submenu

Como alternativa, a aparência do rodapé de submenu pode ser definida definindo a Shell.FlyoutFooterTemplate propriedade como :DataTemplate

<Shell ...>
    <Shell.FlyoutFooterTemplate>
        <DataTemplate>
            <StackLayout>
                <Label Text="Xaminals"
                       TextColor="GhostWhite"
                       FontAttributes="Bold"
                       HorizontalOptions="Center" />
                <Label Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat='{0:MMMM dd, yyyy}'}"
                       TextColor="GhostWhite"
                       HorizontalOptions="Center" />
            </StackLayout>
        </DataTemplate>
    </Shell.FlyoutFooterTemplate>
</Shell>

O rodapé de submenu é fixo na parte inferior do submenu e pode ser qualquer altura. Além disso, o rodapé nunca obscurece nenhum item de menu.

Largura e altura do submenu

A largura e a altura do submenu podem ser personalizadas definindo as Shell.FlyoutWidth propriedades e Shell.FlyoutHeight anexadas a double valores:

<Shell ...
       FlyoutWidth="400"
       FlyoutHeight="200">
    ...
</Shell>

Isso permite cenários como expandir o submenu por toda a tela ou reduzir a altura do submenu para que ele não obscureça a barra de tabulação.

Ícone de submenu

Por padrão, os aplicativos Shell têm um ícone de hambúrguer que, quando pressionado, abre o submenu suspenso. Esse ícone pode ser alterado definindo a propriedade associável Shell.FlyoutIcon, do tipo ImageSource, como um ícone apropriado:

<Shell ...
       FlyoutIcon="flyouticon.png">
    ...       
</Shell>

Plano de fundo do submenu

A cor da tela de fundo do submenu pode ser definida com a Shell.FlyoutBackgroundColor propriedade associável:

<Shell ...
       FlyoutBackgroundColor="AliceBlue">
    ...
</Shell>

Observação

O Shell.FlyoutBackgroundColor também pode ser definido a partir de uma CSS (Folha de Estilos em Cascata). Para obter mais informações, consulte Xamarin.Forms Propriedades específicas do Shell.

Como alternativa, a tela de fundo do submenu pode ser especificada definindo a Shell.FlyoutBackground propriedade associável como um Brush:

<Shell ...
       FlyoutBackground="LightGray">
    ...
</Shell>

Neste exemplo, a tela de fundo do submenu é pintada com um cinza SolidColorBrushclaro.

O exemplo a seguir mostra a configuração da tela de fundo do submenu como um LinearGradientBrush:

<Shell ...>
    <Shell.FlyoutBackground>
        <LinearGradientBrush StartPoint="0,0"
                             EndPoint="1,1">
            <GradientStop Color="#8A2387"
                          Offset="0.1" />
            <GradientStop Color="#E94057"
                          Offset="0.6" />
            <GradientStop Color="#F27121"
                          Offset="1.0" />
        </LinearGradientBrush>
    </Shell.FlyoutBackground>
    ...
</Shell>

Para obter mais informações sobre pincéis, consulte Xamarin.Forms Pincéis.

Imagem da tela de fundo do submenu

O submenu pode ter uma imagem de plano de fundo opcional, que aparece sob o cabeçalho do submenu e atrás de qualquer item de submenu, itens de menu e o rodapé de submenu. A imagem da tela de fundo pode ser especificada definindo a propriedade associável FlyoutBackgroundImage, do tipo ImageSource, para um arquivo, recurso inserido, URI ou fluxo.

A taxa de proporção da imagem da tela de fundo pode ser configurada definindo a propriedade associável FlyoutBackgroundImageAspect, do tipo Aspect para um dos membros da enumeração Aspect:

  • AspectFill – Recorta a imagem para que preencha a área de exibição e preserve a taxa de proporção.
  • AspectFit – Coloca a imagem em um formato letterbox, se necessário, para que ela caiba na área de exibição, e adiciona um espaço em branco à parte superior/inferior ou aos lados, de acordo com a largura ou a altura da imagem. Este é o valor padrão da propriedade FlyoutBackgroundImageAspect.
  • Fill – Alonga a imagem para preencher a área de exibição de modo completo e exato. Isso pode resultar em distorção de imagem.

O exemplo a seguir mostra a definição dessas propriedades:

<Shell ...
       FlyoutBackgroundImage="photo.jpg"
       FlyoutBackgroundImageAspect="AspectFill">
    ...
</Shell>

Isso resulta em uma imagem de plano de fundo aparecendo no submenu, abaixo do cabeçalho do submenu:

Captura de tela de uma imagem de plano de fundo do submenu

Cenário de submenu

O pano de fundo do submenu, que é a aparência da sobreposição do submenu, pode ser especificado definindo a Shell.FlyoutBackdrop propriedade anexada como um Brush:

<Shell ...
       FlyoutBackdrop="Silver">
    ...
</Shell>

Neste exemplo, o pano de fundo do submenu é pintado com uma prata SolidColorBrush.

Importante

A FlyoutBackdrop propriedade anexada pode ser definida em qualquer elemento Shell, mas só será aplicada quando estiver definida em Shellobjetos , FlyoutItemou TabBar .

O exemplo a seguir mostra a configuração do cenário de submenu como um LinearGradientBrush:

<Shell ...>
    <Shell.FlyoutBackdrop>
        <LinearGradientBrush StartPoint="0,0"
                             EndPoint="1,1">
            <GradientStop Color="#8A2387"
                          Offset="0.1" />
            <GradientStop Color="#E94057"
                          Offset="0.6" />
            <GradientStop Color="#F27121"
                          Offset="1.0" />
        </LinearGradientBrush>
    </Shell.FlyoutBackdrop>
    ...
</Shell>

Para obter mais informações sobre pincéis, consulte Xamarin.Forms Pincéis.

Comportamento do submenu

O submenu por ser acessado pelo ícone de hambúrguer ou passando o dedo na lateral da tela. No entanto, esse comportamento pode ser alterado definindo a propriedade anexada Shell.FlyoutBehavior como um dos membros de enumeração FlyoutBehavior:

  • Disabled – indica que o submenu não pode ser aberto pelo usuário.
  • Flyout – indica que o submenu pode ser aberto e fechado pelo usuário. Este é o valor padrão para a propriedade de FlyoutBehavior .
  • Locked – indica que o submenu não pode ser fechado pelo usuário, e o submenu não se sobrepõe ao conteúdo.

O exemplo a seguir mostra como desabilitar o submenu:

<Shell ...
       FlyoutBehavior="Disabled">
    ...
</Shell>

Observação

A propriedade anexada FlyoutBehavior pode ser definida em Shell, FlyoutItem, ShellContent e em objetos da página para substituir o comportamento padrão do submenu.

Rolagem vertical do submenu

Por padrão, um submenu pode ser rolado verticalmente quando os itens de submenu não cabem no submenu. Esse comportamento pode ser alterado definindo a Shell.FlyoutVerticalScrollMode propriedade associável para um dos membros de ScrollMode enumeração:

  • Disabled – indica que a rolagem vertical será desabilitada.
  • Enabled – indica que a rolagem vertical será habilitada.
  • Auto – indica que a rolagem vertical será habilitada se os itens de submenu não se ajustarem ao submenu. Este é o valor padrão da propriedade FlyoutVerticalScrollMode.

O exemplo a seguir mostra como desabilitar a rolagem vertical:

<Shell ...
       FlyoutVerticalScrollMode="Disabled">
    ...
</Shell>

Ordem de tabulação do FlyoutItem

Por padrão, a ordem de tabulação dos objetos FlyoutItem é a mesma ordem em que eles são listados no XAML ou em que são adicionados de maneira programática a uma coleção filha. Essa é a ordem em que ocorrerá a navegação dos objetos FlyoutItem por meio do teclado e, geralmente, essa ordem padrão é a melhor ordem.

A ordem de tabulação padrão pode ser alterada definindo a propriedade FlyoutItem.TabIndex, que indica a ordem em que os objetos FlyoutItem recebem o foco quando o usuário navega pelos itens ao pressionar a tecla Tab. O valor padrão da propriedade é 0 e ela pode ser definida como qualquer valor de int.

As seguintes regras se aplicam ao usar a ordem de tabulação padrão ou ao definir a propriedade TabIndex:

  • Os objetos FlyoutItem com um TabIndex igual a 0 são adicionados à ordem de tabulação com base em sua ordem de declaração no XAML ou nas coleções filhas.
  • Os objetos FlyoutItem com um TabIndex maior que 0 são adicionados à ordem de tabulação com base em seu valor do TabIndex.
  • Os objetos FlyoutItem com um TabIndex menor que 0 são adicionados à ordem de tabulação e aparecem antes de qualquer valor zero.
  • Conflitos em um TabIndex são resolvidos pela ordem de declaração.

Após definir uma ordem de tabulação, ao pressionar a tecla Tab, o foco passará pelos objetos FlyoutItem na ordem ascendente do TabIndex e voltam ao início quando o último objeto é atingido.

Além de definir a ordem de tabulação dos objetos FlyoutItem, pode ser necessário excluir alguns objetos da ordem de tabulação. Isso pode ser feito usando a propriedade FlyoutItem.IsTabStop, que indica se um FlyoutItem está incluído na navegação por tabulação. Seu valor padrão é true, e quando o valor é false, o FlyoutItem é ignorado pela infraestrutura da navegação por tabulação, independentemente de TabIndex estar definido.

Seleção de FlyoutItem

Quando um aplicativo Shell que usa um submenu for executado pela primeira vez, a Shell.CurrentItem propriedade será definida como o primeiro FlyoutItem objeto no objeto subclasse Shell . No entanto, a propriedade pode ser definida para outro FlyoutItem, conforme mostrado no exemplo a seguir:

<Shell ...
       CurrentItem="{x:Reference aboutItem}">
    <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
        ...
    </FlyoutItem>
    <ShellContent x:Name="aboutItem"
                  Title="About"
                  Icon="info.png"
                  ContentTemplate="{DataTemplate views:AboutPage}" />
</Shell>

Este exemplo define a CurrentItem propriedade para o ShellContent objeto chamado aboutItem, o que resulta na seleção e exibição dela. Nesse exemplo, uma conversão implícita é usada para encapsular o objeto ShellContent em um objeto Tab, que é encapsulado em um objeto FlyoutItem.

O código C# equivalente, dado um ShellContent objeto chamado aboutItem, é:

CurrentItem = aboutItem;

Neste exemplo, a CurrentItem propriedade é definida na classe subclasse Shell . Como alternativa, a CurrentItem propriedade pode ser definida em qualquer classe por meio da Shell.Current propriedade estática:

Shell.Current.CurrentItem = aboutItem;

Observação

Um aplicativo pode inserir um estado em que selecionar um item de submenu não é uma operação válida. Nesses casos, o FlyoutItem pode ser desabilitado definindo sua IsEnabled propriedade como false. Isso impedirá que os usuários possam selecionar o item de submenu.

Visibilidade do FlyoutItem

Os itens de submenu são visíveis no submenu por padrão. No entanto, um item pode ser oculto no submenu com a FlyoutItemIsVisible propriedade e removido do submenu com a IsVisible propriedade :

  • FlyoutItemIsVisible, do tipo bool, indica se o item está oculto no submenu, mas ainda é acessível com o GoToAsync método de navegação. O valor padrão dessa propriedade é true.
  • IsVisible, do tipo bool, indica se o item deve ser removido da árvore visual e, portanto, não aparece no submenu. Seu valor padrão é true.

O exemplo a seguir mostra como ocultar um item no submenu:

<Shell ...>
    <FlyoutItem ...
                FlyoutItemIsVisible="False">
        ...
    </FlyoutItem>
</Shell>

Observação

Também há uma Shell.FlyoutItemIsVisible propriedade anexada, que pode ser definida em FlyoutItemobjetos , MenuItem, Tabe ShellContent .

Abrir e fechar o submenu programaticamente

O submenu pode ser aberto e fechado programaticamente definindo a Shell.FlyoutIsPresented propriedade associável como um boolean valor que indica se o submenu está aberto no momento:

<Shell ...
       FlyoutIsPresented="{Binding IsFlyoutOpen}">
</Shell>

Como alternativa, isso pode ser executado no código:

Shell.Current.FlyoutIsPresented = false;