TabbedPage в Xamarin.Forms. Страница с вкладками

Автор:

learn.microsoft.com

TabbedPage Xamarin.Forms состоит из списка вкладок и более крупной детальной области, причем каждая вкладка загружает содержимое в детальную область. На следующих скриншотах показана страница TabbedPage на iOS и Android:

На iOS список вкладок отображается в нижней части экрана, а область деталей находится выше. Каждая вкладка состоит из заголовка и значка, который должен представлять собой PNG-файл с альфа-каналом. В книжной ориентации значки панели вкладок отображаются над заголовками вкладок. В альбомной ориентации значки и заголовки отображаются рядом. Кроме того, в зависимости от устройства и ориентации может отображаться обычная или компактная панель вкладок. Если имеется более пяти вкладок, появится вкладка More, с помощью которой можно получить доступ к дополнительным вкладкам.

На Android список вкладок отображается в верхней части экрана, а область подробностей – ниже. Каждая вкладка состоит из заголовка и значка, который должен представлять собой файл PNG с альфа-каналом. Однако вкладки могут быть перемещены в нижнюю часть экрана с помощью конкретной платформы. Если вкладок больше пяти, а список вкладок находится в нижней части экрана, появится вкладка More, с помощью которой можно получить доступ к дополнительным вкладкам. Информацию о перемещении вкладок в нижнюю часть экрана см. в разделе Настройка размещения и цвета панели инструментов страницы вкладок.

На Universal Windows Platform (UWP) список вкладок отображается в верхней части экрана, а область подробностей находится ниже. Каждая вкладка состоит из заголовка. Однако к каждой вкладке можно добавить значки, зависящие от платформы. Для получения дополнительной информации см. раздел TabbedPage Icons для Windows.

Совет. Файлы масштабируемой векторной графики (SVG) могут отображаться в виде значков вкладок на странице с вкладками.

Класс iOS TabbedRenderer имеет переопределяемый метод GetIcon, который можно использовать для загрузки иконок вкладок из указанного источника. Кроме того, при необходимости можно предоставить выбранную и невыбранную версии значка.

Класс Android AppCompat TabbedPageRenderer имеет переопределяемый метод SetTabIconImageSource, который можно использовать для загрузки иконок вкладок из пользовательского Drawable. В качестве альтернативы файлы SVG можно преобразовать в векторные ресурсы drawable, которые могут автоматически отображаться в Xamarin.Forms. Для получения дополнительной информации о преобразовании SVG-файлов в векторные рисуемые ресурсы см. раздел Добавление векторной графики различной плотности на developer.android.com.

Создание страницы TabbedPage Xamarin

Для создания страницы TabbedPage можно использовать два подхода:

  • Наполнить страницу с вкладками коллекцией дочерних объектов Page, например, коллекцией объектов ContentPage. Для получения дополнительной информации смотрите раздел «Наполнить вкладку TabbedPage коллекцией страниц».
  • Назначить коллекцию свойству ItemsSource и DataTemplate свойству ItemTemplate, чтобы вернуть страницы для объектов коллекции.

При обоих подходах страница TabbedPage будет отображать каждую страницу по мере выбора пользователем каждой вкладки.

Важно. Рекомендуется заполнять TabbedPage только экземплярами NavigationPage и ContentPage. Это поможет обеспечить согласованный пользовательский опыт на всех платформах.

Кроме того, TabbedPage определяет следующие свойства:

  • BarBackgroundColor, тип Color, цвет фона панели вкладок.
  • BarTextColor, тип Color, цвет текста на панели вкладок.
  • SelectedTabColor, тип Color, цвет вкладки, когда она выбрана.
  • UnselectedTabColor, тип Color, цвет вкладки, когда она не выбрана.

Все эти свойства поддерживаются объектами BindableProperty, что означает, что их можно стилизовать, и свойства могут быть объектами привязки данных.

Предупреждение. В TabbedPage каждый объект Page создается при построении TabbedPage. Это может привести к плохому пользовательскому опыту, особенно если TabbedPage является корневой страницей приложения. Однако Xamarin.Forms Shell позволяет создавать страницы, доступные через панель вкладок, по требованию, в ответ на навигацию. Для получения дополнительной информации см. раздел Xamarin.Forms Shell.

Наполнение TabbedPage коллекцией страниц

Страница с вкладками может быть заполнена коллекцией дочерних объектов Page, например, коллекцией объектов ContentPage. Это достигается путем добавления объектов Page в коллекцию TabbedPage.Children. В XAML это выполняется следующим образом:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
           xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
           xmlns:local="clr-namespace:TabbedPageWithNavigationPage;assembly=TabbedPageWithNavigationPage"
           x:Class="TabbedPageWithNavigationPage.MainPage">
   <local:TodayPage />
   <NavigationPage Title="Schedule" IconImageSource="schedule.png">
       <x:Arguments>
           <local:SchedulePage />
       </x:Arguments>
   </NavigationPage>
</TabbedPage>

Примечание. Свойство Children класса MultiPage, от которого происходит TabbedPage, является свойством ContentProperty класса MultiPage. Поэтому в XAML нет необходимости явно присваивать объекты Page свойству Children.

Эквивалентный код на C# выглядит следующим образом:

public class MainPageCS : TabbedPage
{
 public MainPageCS ()
 {
   NavigationPage navigationPage = new NavigationPage (new SchedulePageCS ());
   navigationPage.IconImageSource = "schedule.png";
   navigationPage.Title = "Schedule";
 
   Children.Add (new TodayPageCS ());
   Children.Add (navigationPage);
 }
}

В этом примере страница TabbedPage заполнена двумя объектами Page. Первым дочерним объектом является объект ContentPage, а вторым – NavigationPage, содержащая объект ContentPage.

На следующих скриншотах показан объект ContentPage в TabbedPage:

tabbedpage xamarin

При выборе другой вкладки отображается объект ContentPage, представляющий эту вкладку:

На вкладке Расписание объект ContentPage обернут в объект NavigationPage.

Предупреждение. Хотя NavigationPage можно поместить в TabbedPage, не рекомендуется помещать TabbedPage в NavigationPage. Это связано с тем, что в iOS UITabBarController всегда действует как обертка для UINavigationController. Для получения дополнительной информации см. раздел Комбинированные интерфейсы контроллера представления в Библиотеке разработчика iOS.

Навигация внутри вкладки

Навигация может быть выполнена внутри вкладки при условии, что объект ContentPage обернут в объект NavigationPage. Это достигается путем вызова метода PushAsync для свойства Navigation объекта ContentPage:

await Navigation.PushAsync (new UpcomingAppointmentsPage ());

Страница, на которую осуществляется навигация, указывается в качестве аргумента метода PushAsync. В этом примере страница UpcomingAppointmentsPage перемещается в стек навигации, где она становится активной страницей:

tabbed page xamarin

Наполнение страницы TabbedPage шаблоном

TabbedPage можно заполнить страницами, назначив коллекцию данных свойству ItemsSource и назначив DataTemplate свойству ItemTemplate, которое шаблонизирует данные как объекты Page. Это достигается в XAML следующим образом:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:local="clr-namespace:TabbedPageDemo;assembly=TabbedPageDemo"
           x:Class="TabbedPageDemo.TabbedPageDemoPage"
           ItemsSource="{x:Static local:MonkeyDataModel.All}">           
 <TabbedPage.Resources>
   <ResourceDictionary>
     <local:NonNullToBooleanConverter x:Key="booleanConverter" />
   </ResourceDictionary>
 </TabbedPage.Resources>
 <TabbedPage.ItemTemplate>
   <DataTemplate>
     <ContentPage Title="{Binding Name}" IconImageSource="monkeyicon.png">
       <StackLayout Padding="5, 25">
         <Label Text="{Binding Name}" Font="Bold,Large" HorizontalOptions="Center" />
         <Image Source="{Binding PhotoUrl}" WidthRequest="200" HeightRequest="200" />
         <StackLayout Padding="50, 10">
           <StackLayout Orientation="Horizontal">
             <Label Text="Family:" HorizontalOptions="FillAndExpand" />
             <Label Text="{Binding Family}" Font="Bold,Medium" />
           </StackLayout>
           ...
         </StackLayout>
       </StackLayout>
     </ContentPage>
   </DataTemplate>
 </TabbedPage.ItemTemplate>
</TabbedPage>

Эквивалентным кодом на C# является:

public class TabbedPageDemoPageCS : TabbedPage
{
 public TabbedPageDemoPageCS ()
 {
   var booleanConverter = new NonNullToBooleanConverter ();
 
   ItemTemplate = new DataTemplate (() =>
   {
     var nameLabel = new Label
     {
       FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
       FontAttributes = FontAttributes.Bold,
       HorizontalOptions = LayoutOptions.Center
     };
     nameLabel.SetBinding (Label.TextProperty, "Name");
 
     var image = new Image { WidthRequest = 200, HeightRequest = 200 };
     image.SetBinding (Image.SourceProperty, "PhotoUrl");
 
     var familyLabel = new Label
     {
       FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
       FontAttributes = FontAttributes.Bold
     };
     familyLabel.SetBinding (Label.TextProperty, "Family");
     ...
 
     var contentPage = new ContentPage
     {
       IconImageSource = "monkeyicon.png",
       Content = new StackLayout {
         Padding = new Thickness (5, 25),
         Children =
         {
           nameLabel,
           image,
           new StackLayout
           {
             Padding = new Thickness (50, 10),
             Children =
             {
               new StackLayout
               {
                 Orientation = StackOrientation.Horizontal,
                 Children =
                 {
                   new Label { Text = "Family:", HorizontalOptions = LayoutOptions.FillAndExpand },
                   familyLabel
                 }
               },
               // ...
             }
           }
         }
       }
     };
     contentPage.SetBinding (TitleProperty, "Name");
     return contentPage;
   });
   ItemsSource = MonkeyDataModel.All;
 }
}

В этом примере каждая вкладка состоит из объекта ContentPage, который использует объекты Image и Label для отображения данных для вкладки:

При выборе другой вкладки отображается объект ContentPage, представляющий эту вкладку.

Материалы по теме