Xamarin.Forms: TabbedPage

Download Sample Das Beispiel herunterladen

Das Xamarin.FormsTabbedPage besteht aus einer Liste von Registerkarten und einem größeren Detailbereich, wobei jeder Registerkarte Inhalt in den Detailbereich lädt. Die folgenden Screenshots zeigen eine TabbedPage unter iOS und Android:

Screenshot of a TabbedPage containing three tabs, on iOS and Android

Unter iOS wird die Liste der Registerkarten am unteren Rand des Bildschirms angezeigt, und der Detailbereich befindet sich darüber. Jede Registerkarte besteht aus einem Titel und einem Symbol, bei dem es sich um eine PNG-Datei mit einem Alphakanal handeln sollte. Im Hochformat werden die Symbole der Registerkartenleiste über den Registerkartentiteln angezeigt. Im Querformat werden die Symbole und Titel nebeneinander angezeigt. Außerdem kann je nach Gerät und Ausrichtung eine reguläre oder kompakte Registerkartenleiste angezeigt werden. Wenn mehr als fünf Registerkarten vorhanden sind, wird die Registerkarte More (Weitere) angezeigt, die verwendet werden kann, um auf die zusätzlichen Registerkarten zuzugreifen.

Unter Android wird die Liste der Registerkarten am oberen Rand des Bildschirms angezeigt, und der Detailbereich befindet sich darunter. Jede Registerkarte besteht aus einem Titel und einem Symbol, bei dem es sich um eine PNG-Datei mit einem Alphakanal handeln sollte. Die Registerkarten können jedoch mit einem plattformspezifischen Element an den unteren Rand des Bildschirms verschoben werden. Wenn mehr als fünf Registerkarten vorhanden sind und die Registerkartenliste sich am unteren Rand des Bildschirms befindet, wird eine Registerkarte More (Weitere) angezeigt, die für den Zugriff auf zusätzliche Registerkarten verwendet werden kann. Weitere Informationen zu den Symbolanforderungen finden Sie unter Tabs (Registerkarten) auf material.io und Support different pixel densities (Unterstützung verschiedener Pixeldichten) auf developer.android.com. Weitere Informationen zum Verschieben der Registerkarten an den unteren Bildschirmrand finden Sie unter Setting TabbedPage Toolbar Placement and Color (Festlegen der TabbedPage-Symbolleistenanordnung und -farbe).

Auf der universellen Windows-Plattform (UWP) wird die Liste der Registerkarten am oberen Rand des Bildschirms angezeigt, und der Detailbereich befindet sich darunter. Jede Registerkarte umfasst einen Titel. Den Registerkarten können allerdings mit einem plattformspezifischen Element Symbole hinzugefügt werden. Weitere Informationen finden Sie unter TabbedPage Icons on Windows (TabbedPage-Symbole unter Windows).

Tipp

SVG-Dateien (skalierbare Vektorgrafik) können als Registerkartensymbole auf einem TabbedPage-Element angezeigt werden:

  • Die iOS-Klasse TabbedRenderer enthält eine überschreibbare GetIcon-Methode, die verwendet werden kann, um Registerkartensymbole aus einer angegebenen Quelle zu laden. Darüber hinaus können die ausgewählten und nicht ausgewählten Versionen eines Symbols bei Bedarf zur Verfügung gestellt werden.
  • Die AppCompat-Klasse TabbedPageRenderer unter Android enthält eine überschreibbare SetTabIconImageSource-Methode, die verwendet werden kann, um Registerkartensymbole aus einer benutzerdefinierten Drawable-Klasse zu laden. Alternativ dazu können SVG-Dateien in zeichenbare Vektorressourcen konvertiert werden, die automatisch von Xamarin.Forms angezeigt werden können. Weitere Informationen zum Konvertieren von SVG-Dateien in zeichenbare Vektorressourcen finden Sie auf „developer.android.com“ unter Add multi-density vector graphics (Hinzufügen von Vektorgrafiken mit mehreren Dichten).

Weitere Informationen finden Sie unter Xamarin.Forms: TabbedPage mit SVG-Registerkartensymbolen.

Erstellen einer TabbedPage

Es gibt zwei Ansätze zum Erstellen einer TabbedPage-Klasse:

Durch beide Ansätze zeigt die TabbedPage-Klasse die entsprechende Seite an, wenn der Benutzer eine Registerkarte auswählt.

Wichtig

Es wird empfohlen, die TabbedPage-Klasse nur mit NavigationPage- und ContentPage-Instanzen aufzufüllen. Dadurch wird eine konsistente Benutzerumgebung auf allen Plattformen gewährleistet.

Darüber hinaus definiert TabbedPage die folgenden Eigenschaften:

Alle diese Eigenschaften werden durch BindableProperty-Objekte gestützt, was bedeutet, dass die Eigenschaften formatiert werden können und die Ziele von Datenverbindungen sein können.

Warnung

In einer TabbedPage wird jedes Page-Objekt bei der Erstellung von TabbedPage erstellt. Dies kann insbesondere dann das Benutzererlebnis beeinträchtigen, wenn die TabbedPage die Stammseite der Anwendung ist. Die Xamarin.Forms-Shell ermöglicht es aber, dass Seiten, auf die über eine Registerkartenleiste zugegriffen wird, bei Bedarf als Reaktion auf die Navigation erstellt werden. Weitere Informationen finden Sie unter Xamarin.Forms-Shell.

Auffüllen einer TabbedPage mit einer Seitensammlung

Sie können eine TabbedPage mit einer Sammlung von untergeordneten Page-Objekten auffüllen, z. B. einer Sammlung von ContentPage-Objekten. Dies wird erreicht, indem der TabbedPage.Children-Sammlung die Page-Objekte hinzugefügt werden. Dies kann in XAML folgendermaßen durchgeführt werden:

<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>

Hinweis

Die Children-Eigenschaft der MultiPage<T>-Klasse, von der TabbedPage abgeleitet ist, ist die ContentProperty von MultiPage<T>. Daher ist es in XAML nicht notwendig, die Page-Objekte explizit der Children-Eigenschaft zuzuweisen.

Der entsprechende C#-Code lautet:

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);
  }
}

In diesem Beispiel wird die TabbedPage mit zwei Page-Objekten aufgefüllt. Beim ersten untergeordneten Objekt handelt es sich um ein ContentPage-Objekt, und beim zweiten um eine NavigationPage, die ein ContentPage-Objekt enthält.

Die folgenden Screenshots zeigen ein ContentPage-Objekt in einer TabbedPage:

Screenshot of a TabbedPage containing three tabs, on iOS and Android

Durch das Auswählen einer anderen Registerkarte wird das ContentPage-Objekt angezeigt, das die Registerkarte darstellt:

Screenshot of a TabbedPage containing tabs, on iOS and Android

Auf der Registerkarte Schedule (Zeitplan) ist das ContentPage-Objekt von einem NavigationPage-Objekt umschlossen.

Warnung

Während eine NavigationPage in eine TabbedPage eingefügt werden kann, wird davon abgeraten, eine TabbedPage in eine NavigationPage einzufügen. Dies liegt darin begründet, dass UITabBarController unter iOS immer als Wrapper für UINavigationController fungiert. Weitere Informationen finden Sie unter Combined View Controller Interfaces (Kombinierte Schnittstellen für View Controller) in der iOS Developer Library.

Die Navigation kann auf einer Registerkarte ausgeführt werden, wenn das ContentPage-Objekt von einem NavigationPage-Objekt umschlossen wird. Dies wird durch die Aufrufen der PushAsync-Methode in der Navigation-Eigenschaft des ContentPage-Objekts erreicht:

await Navigation.PushAsync (new UpcomingAppointmentsPage ());

Die Seite, die das Ziel der Navigation ist, wird der PushAsync-Methode als Argument angegeben. In diesem Beispiel wird die Seite UpcomingAppointmentsPage auf den Navigationsstapel gepusht und dort zur aktiven Seite:

Screenshot of navigation within a tab, on iOS and Android

Weitere Informationen zur Navigation mithilfe der NavigationPage-Klasse finden Sie unter Hierarchical Navigation (Hierarchische Navigation).

Auffüllen einer TabbedPage mithilfe einer Vorlage

Eine TabbedPage kann mit Seiten aufgefüllt werden, indem der ItemsSource-Eigenschaft eine Sammlung von Daten zugewiesen wird. Dazu wird der ItemTemplate-Eigenschaft eine DataTemplate zugewiesen, die als Vorlage der Daten in Form von Page-Objekten fungiert. Dies kann in XAML folgendermaßen durchgeführt werden:

<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>

Der entsprechende C#-Code lautet:

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;
  }
}

In diesem Beispiel enthält jede Registerkarte ein ContentPage-Objekt, das Image-Objekte und Label-Objekte für das Anzeigen von Daten für die Registerkarte verwendet:

Screenshot of a templated TabbedPage, on iOS and Android

Durch das Auswählen einer anderen Registerkarte wird das ContentPage-Objekt angezeigt, das die Registerkarte darstellt.