Xamarin.Forms TabbedPage

Состоит Xamarin.FormsTabbedPage из списка вкладок и более крупной области сведений с каждой загрузкой содержимого вкладки в область сведений. На снимках экрана ниже показана страница TabbedPage в iOS и Android.

Снимок экрана TabbedPage с тремя вкладками в iOS и Android

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

В Android список вкладок отображается в верхней части экрана, а также в области данных ниже. У каждой вкладки есть заголовок и значок, который должен быть PNG-файлом с альфа-каналом. Но эти вкладки можно переместить в нижнюю часть экрана в зависимости от конкретной платформы. При наличии более пяти вкладок, список которых отображается внизу экрана, появляется вкладка Дополнительно, которую можно использовать для доступа к дополнительным вкладкам. Дополнительные сведения о требованиях к значкам см. в разделах о вкладках на сайте material.io и поддержке разных значений плотности пикселей на сайте developer.android.com. Дополнительные сведения о перемещении вкладок в нижнюю часть экрана см. в статье TabbedPage Toolbar Placement and Color on Android (Цвет и размещение значков на панели TabbedPage в Android).

На универсальной платформе Windows (UWP) список вкладок отображается в верхней части экрана, а также в области данных ниже. У каждой вкладки есть заголовок. Тем не менее на каждую вкладку можно добавлять значки в зависимости от платформы. Дополнительные сведения см. в статье о значках TabbedPage в Windows.

Совет

Файлы SVG (Scalable Vector Graphic) могут отображаться в виде значков вкладок на TabbedPage.

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

Создание объекта TabbedPage

Создать TabbedPage можно двумя способами:

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

Внимание

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

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

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

Предупреждение

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

Заполнение TabbedPage коллекцией Page

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<T>, из которого происходит TabbedPage, – это свойство ContentPropertyMultiPage<T>. Таким образом, в 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 с тремя вкладками в iOS и Android

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

Снимок экрана TabbedPage со вкладками в iOS и Android

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

Предупреждение

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

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

await Navigation.PushAsync (new UpcomingAppointmentsPage ());

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

Снимок экрана: перемещение в пределах вкладки в iOS и Android

Дополнительные сведения об осуществлении навигации с помощью класса NavigationPage см. в статье Иерархическая навигация.

Заполнение 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 для вывода данных на вкладку:

Снимок экрана шаблона TabbedPage в iOS и Android

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