Xamarin.Forms Página de submenu
Uma página de submenu normalmente exibe uma lista de itens, conforme mostrado nas seguintes capturas de tela:
A localização da lista de itens é idêntico em cada plataforma e selecionar um dos itens navegará até a página de detalhes correspondente. Além disso, a página de submenu também apresenta uma barra de navegação que contém um botão que pode ser usado para navegar até a página de detalhes ativa:
- No iOS, a barra de navegação está presente na parte superior da página e tem um botão que navega até a página de detalhes. Além disso, a página de detalhes ativa pode ser navegada deslizando o submenu para a esquerda.
- No Android, a barra de navegação está presente na parte superior da página e exibe um título, um ícone e um botão que navega até a página de detalhes. O ícone é definido no atributo
[Activity]
que decora a classeMainActivity
no projeto específico da plataforma Android. Além disso, a página de detalhes ativa pode ser navegada deslizando a página do submenu para a esquerda, tocando na página de detalhes na extremidade direita da tela e tocando no botão Voltar na parte inferior da tela. - Na UWP (Plataforma Universal do Windows), a barra de navegação está presente na parte superior da página e tem um botão que navega até a página de detalhes.
Uma página de detalhes exibe dados que correspondem ao item selecionado na página de submenu e os principais componentes da página de detalhes são mostrados nas seguintes capturas de tela:
A página de detalhes contém uma barra de navegação, cujo conteúdo dependem da plataforma:
- No iOS, a barra de navegação está presente na parte superior da página e exibe um título e tem um botão que retorna à página de submenu, desde que a instância da página de detalhes seja encapsulada
NavigationPage
na instância. Além disso, a página do submenu pode ser acessada deslizando a página de detalhes para a direita. - No Android, uma barra de navegação está presente na parte superior da página e exibe um título, um ícone e um botão que retorna à página do submenu. O ícone é definido no atributo
[Activity]
que decora a classeMainActivity
no projeto específico da plataforma Android. - Na UWP, a barra de navegação está presente na parte superior da página e exibe um título e tem um botão que retorna à página de submenu.
Comportamento de navegação
O comportamento da experiência de navegação entre as páginas de submenu e de detalhes depende da plataforma:
- No iOS, a página de detalhes desliza para a direita enquanto a página de submenu desliza da esquerda e a parte esquerda da página de detalhes ainda está visível.
- No Android, as páginas de detalhes e submenu são sobrepostas umas às outras.
- Na UWP, a página de submenu desliza da parte esquerda da página de detalhes, desde que a
FlyoutLayoutBehavior
propriedade esteja definida comoPopover
.
Um comportamento semelhante será observado no modo paisagem, exceto que a página de submenu no iOS e no Android tem uma largura semelhante à página de submenu no modo retrato, portanto, mais da página de detalhes ficará visível.
Para obter informações sobre como controlar o comportamento de navegação, consulte Controlar o comportamento do layout da página de detalhes.
Criar uma página de submenu
A FlyoutPage
contém Flyout
e Detail
propriedades que são do tipo Page
, que são usadas para obter e definir as páginas de submenu e detalhes, respectivamente.
Importante
Um FlyoutPage
foi criado para ser uma página raiz e usá-la como uma página filho em outros tipos de página pode resultar em comportamento inesperado e inconsistente. Além disso, é recomendável que a página de submenu de a FlyoutPage
seja sempre uma ContentPage
instância e que a página de detalhes seja preenchida apenas com TabbedPage
, NavigationPage
e instâncias ContentPage
. Isso ajudará a garantir uma experiência do usuário consistente em todas as plataformas.
O exemplo de código XAML a seguir mostra um FlyoutPage
que define as propriedades Flyout
e Detail
:
<FlyoutPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FlyoutPageNavigation;assembly=FlyoutPageNavigation"
x:Class="FlyoutPageNavigation.MainPage">
<FlyoutPage.Flyout>
<local:FlyoutMenuPage x:Name="flyoutPage" />
</FlyoutPage.Flyout>
<FlyoutPage.Detail>
<NavigationPage>
<x:Arguments>
<local:ContactsPage />
</x:Arguments>
</NavigationPage>
</FlyoutPage.Detail>
</FlyoutPage>
O seguinte exemplo de código mostra a FlyoutPage
equivalente criada em C#:
public class MainPageCS : FlyoutPage
{
FlyoutMenuPageCS flyoutPage;
public MainPageCS()
{
flyoutPage = new FlyoutMenuPageCS();
Flyout = flyoutPage;
Detail = new NavigationPage(new ContactsPageCS());
...
}
...
}
A propriedade Flyout
está definida como uma instância ContentPage
. A propriedade Detail
está definida como uma NavigationPage
que contém uma instância ContentPage
.
Criar a página de submenu
O exemplo de código XAML a seguir mostra a declaração do objeto FlyoutMenuPage
, referenciado por meio da propriedade Flyout
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="using:FlyoutPageNavigation"
x:Class="FlyoutPageNavigation.FlyoutMenuPage"
Padding="0,40,0,0"
IconImageSource="hamburger.png"
Title="Personal Organiser">
<StackLayout>
<ListView x:Name="listView" x:FieldModifier="public">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:FlyoutPageItem}">
<local:FlyoutPageItem Title="Contacts" IconSource="contacts.png" TargetType="{x:Type local:ContactsPage}" />
<local:FlyoutPageItem Title="TodoList" IconSource="todo.png" TargetType="{x:Type local:TodoListPage}" />
<local:FlyoutPageItem Title="Reminders" IconSource="reminders.png" TargetType="{x:Type local:ReminderPage}" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1" Text="{Binding Title}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
A página consiste em um ListView
que é preenchido com dados em XAML, definindo sua ItemsSource
propriedade como uma matriz de FlyoutPageItem
objetos. Cada FlyoutPageItem
define propriedades Title
, IconSource
e TargetType
.
Um DataTemplate
é atribuído à propriedade ListView.ItemTemplate
, para exibir cada FlyoutPageItem
. O DataTemplate
contém um ViewCell
que consiste em um Image
e em um Label
. O Image
exibe o valor da propriedade IconSource
, e o Label
exibe o valor da propriedade Title
, para cada FlyoutPageItem
.
A página tem seu conjunto de propriedades Title
e IconImageSource
. O ícone será exibido na página de detalhes, desde que ela tenha uma barra de título. Isso deve ser habilitado no iOS encapsulando a instância da página de detalhes em uma instância NavigationPage
.
O exemplo de código a seguir mostra a página equivalente criada em C#:
public class FlyoutMenuPageCS : ContentPage
{
ListView listView;
public ListView ListView { get { return listView; } }
public FlyoutMenuPageCS()
{
var flyoutPageItems = new List<FlyoutPageItem>();
flyoutPageItems.Add(new FlyoutPageItem
{
Title = "Contacts",
IconSource = "contacts.png",
TargetType = typeof(ContactsPageCS)
});
flyoutPageItems.Add(new FlyoutPageItem
{
Title = "TodoList",
IconSource = "todo.png",
TargetType = typeof(TodoListPageCS)
});
flyoutPageItems.Add(new FlyoutPageItem
{
Title = "Reminders",
IconSource = "reminders.png",
TargetType = typeof(ReminderPageCS)
});
listView = new ListView
{
ItemsSource = flyoutPageItems,
ItemTemplate = new DataTemplate(() =>
{
var grid = new Grid { Padding = new Thickness(5, 10) };
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(30) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star });
var image = new Image();
image.SetBinding(Image.SourceProperty, "IconSource");
var label = new Label { VerticalOptions = LayoutOptions.FillAndExpand };
label.SetBinding(Label.TextProperty, "Title");
grid.Children.Add(image);
grid.Children.Add(label, 1, 0);
return new ViewCell { View = grid };
}),
SeparatorVisibility = SeparatorVisibility.None
};
IconImageSource = "hamburger.png";
Title = "Personal Organiser";
Padding = new Thickness(0, 40, 0, 0);
Content = new StackLayout
{
Children = { listView }
};
}
}
As capturas de tela a seguir mostram a página de submenu em cada plataforma:
Criar e exibir a página de detalhes
A FlyoutMenuPage
instância contém uma ListView
propriedade que expõe sua ListView
instância para que a MainPage
FlyoutPage
instância possa registrar um manipulador de eventos para manipular o ItemSelected
evento. Isso permite que a instância MainPage
defina a propriedade Detail
como a página que representa o item ListView
selecionado. O exemplo de código a seguir mostra o manipulador de eventos:
public partial class MainPage : FlyoutPage
{
public MainPage()
{
...
flyoutPage.listView.ItemSelected += OnItemSelected;
}
void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as FlyoutPageItem;
if (item != null)
{
Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
flyoutPage.listView.SelectedItem = null;
IsPresented = false;
}
}
}
O método OnItemSelected
executa as seguintes ações:
- Ele recupera o
SelectedItem
da instânciaListView
e, contanto que não sejanull
, define a página de detalhes como uma nova instância do tipo de página armazenado na propriedadeTargetType
doFlyoutPageItem
. O tipo de página é encapsulado em uma instânciaNavigationPage
para garantir que o ícone referenciado por meio da propriedadeIconImageSource
noFlyoutMenuPage
seja mostrado na página de detalhes no iOS. - O item selecionado no
ListView
é definido comonull
para garantir que nenhum dos itensListView
serão selecionados na próxima vez em que oFlyoutMenuPage
for apresentado. - A página de detalhes é apresentada ao usuário definindo a propriedade
FlyoutPage.IsPresented
comofalse
. Essa propriedade controla se o submenu ou a página de detalhes é apresentada. Ele deve ser definido comotrue
para exibir a página de submenu e parafalse
exibir a página de detalhes.
As capturas de tela a seguir mostram a ContactPage
página de detalhes, que é mostrada depois que ela é selecionada na página de submenu:
Controlar o comportamento do layout da página de detalhes
A forma como o FlyoutPage
gerencia o submenu e as páginas de detalhes depende se o aplicativo está sendo executado em um telefone ou tablet, da orientação do dispositivo e do valor da FlyoutLayoutBehavior
propriedade. Essa propriedade determina como a página de detalhes será exibida. Os valores possíveis são:
Default
– As páginas são exibidas usando o padrão da plataforma.Popover
– A página de detalhes cobre ou cobre parcialmente a página de submenu.Split
– A página do submenu é exibida à esquerda e a página de detalhes está à direita.SplitOnLandscape
– Uma tela dividida é usada quando o dispositivo está na orientação paisagem.SplitOnPortrait
– Uma tela dividida é usada quando o dispositivo está na orientação retrato.
O exemplo de código XAML a seguir demonstra como definir a propriedade FlyoutLayoutBehavior
em um FlyoutPage
:
<FlyoutPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FlyoutPageNavigation.MainPage"
FlyoutLayoutBehavior="Popover">
...
</FlyoutPage>
O seguinte exemplo de código mostra a FlyoutPage
equivalente criada em C#:
public class MainPageCS : FlyoutPage
{
FlyoutMenuPageCS flyoutPage;
public MainPageCS()
{
...
FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover;
}
}
Importante
O valor da propriedade afeta apenas os aplicativos em execução em tablets ou na área de FlyoutLayoutBehavior
trabalho. Os aplicativos executados em telefones sempre têm o Popover
comportamento.