Xamarin.Forms の TabbedPage
Xamarin.Forms の TabbedPage
は、タブのリストと大きな詳細エリアで構成されており、各タブでは、コンテンツが詳細エリアに読み込まれます。 次のスクリーンショットは、iOS と Android での TabbedPage
を示しています。
iOS では、タブのリストが画面の下部に表示され、その上に詳細エリアが表示されます。 各タブは、タイトルとアイコンで構成されます。これは、アルファ チャネルを含む PNG ファイルです。 縦長の向きでは、タブ バーのアイコンがタブ タイトルの上に表示されます。 横長の向きでは、アイコンとタイトルが横に並んで表示されます。 また、デバイスと向きに応じて、ノーマルまたはコンパクトなタブ バーが表示される場合があります。 6 個以上のタブがある場合、[その他] タブが表示され、これを使用して追加のタブにアクセスできます。
Android では、タブのリストが画面の上部に表示され、その下に詳細エリアが表示されます。 各タブは、タイトルとアイコンで構成されます。これは、アルファ チャネルを含む PNG ファイルです。 タブは、プラットフォーム固有で画面の下部に移動できます。 6 個以上のタブがあり、画面の下部にタブ リストがある場合、[その他] タブが表示され、これを使用して追加のタブにアクセスできます。 アイコン要件の詳細については、material.io のタブに関するページと、developer.android.com の「各種のセル密度をサポートする」を参照してください。 タブを画面の下部に移動する方法については、TabbedPage ツール バーの配置と色の設定に関する記事を参照してください。
Universal Windows Platform (UWP) では、タブのリストが画面の上部に表示され、その下に詳細エリアが表示されます。 各タブは、タイトルで構成されます。 ただし、各タブにはプラットフォーム固有のアイコンを追加できます。 詳細については、「Windows 上の TabbedPage アイコン」を参照してください。
ヒント
スケーラブル ベクター グラフィック (SVG) ファイルは、TabbedPage
にタブ アイコンとして表示することができます。
- iOS の
TabbedRenderer
クラスには、指定されたソースからタブ アイコンを読み込むために使用できるオーバーライド可能なGetIcon
メソッドがあります。 さらに、必要に応じて、アイコンの選択バージョンと未選択バージョンも提供することができます。 - Android AppCompat の
TabbedPageRenderer
クラスには、カスタムDrawable
からタブ アイコンを読み込むために使用できるオーバーライド可能なSetTabIconImageSource
メソッドがあります。 また、SVG ファイルをベクター ドローアブル リソースに変換して、Xamarin.Forms で自動的に表示されるようにすることもできます。 SVG ファイルをドローアブル リソースに変換する方法の詳細については、developer.android.com にある 「さまざまな密度に適用可能なベクター グラフィックの追加」を参照してください。
TabbedPage を作成する
TabbedPage
を作成するには、次の 2 つの方法を使用することができます。
- 子
Page
オブジェクトのコレクション (ContentPage
オブジェクトのコレクションなど) を使ってTabbedPage
を作成する。 詳細については、「ページ コレクションを使って TabbedPage を作成する」を参照してください。 - コレクションを
ItemsSource
プロパティに割り当て、DataTemplate
をItemTemplate
プロパティに割り当てて、コレクション内のオブジェクト用のページを返すようにする。 詳細については、「テンプレートを使って TabbedPage を作成する」を参照してください。
どちらの方法を使用する場合も、ユーザーが各タブを選択すると、TabbedPage
に各ページが表示されます。
重要
TabbedPage
を NavigationPage
インスタンスおよび ContentPage
インスタンスのみで作成することをお勧めします。 こうすることにより、すべてのプラットフォームで一貫したユーザー エクスペリエンスを提供することができます。
また、TabbedPage
では次のプロパティが定義されます。
- タイプが
Color
のBarBackgroundColor
(タブ バーの背景色)。 - タイプが
Color
のBarTextColor
(タブ バーのテキストの色)。 - タイプが
Color
のSelectedTabColor
(タブが選択されているときの色)。 - タイプが
Color
のUnselectedTabColor
(タブが選択されていないときの色)。
これらのプロパティはすべて、BindableProperty
オブジェクトを基盤としています。つまり、スタイルを指定でき、プロパティがデータ バインディングの対象になる場合があります。
警告
TabbedPage
では、TabbedPage
の構築時に各 Page
オブジェクトが作成されます。 これにより、特に TabbedPage
がアプリケーションのルート ページである場合に、ユーザー エクスペリエンスが低下する可能性があります。 ただし、Xamarin.Forms シェルを使用すると、ナビゲーションに応じて、タブ バーを介してアクセスされるページをオン デマンドで作成できます。 詳細は、「Xamarin.Forms シェル」を参照してください。
ページ コレクションを使って TabbedPage を作成する
子 Page
オブジェクトのコレクション (ContentPage
オブジェクトのコレクションなど) を使って TabbedPage
を作成できます。 これは、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>
Note
TabbedPage
の派生元である、MultiPage<T>
クラスの Children
プロパティは、MultiPage<T>
の ContentProperty
です。 そのため、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
に 2 つの Page
オブジェクトが設定されています。 最初の子は ContentPage
オブジェクトで、2 番目の子は、ContentPage
オブジェクトを含む NavigationPage
です。
次のスクリーンショットは、TabbedPage
内の ContentPage
オブジェクトを示しています。
別のタブを選択すると、タブを表す ContentPage
オブジェクトが表示されます。
[スケジュール] タブで、ContentPage
オブジェクトが NavigationPage
オブジェクト内にラップされます。
警告
NavigationPage
を TabbedPage
に配置することはできますが、TabbedPage
を NavigationPage
に配置することはお勧めしません。 これは、iOS では、UITabBarController
が常に UINavigationController
のラッパーとして機能するためです。 詳細については、iOS 開発者ライブラリの「Combined View Controller Interfaces」 (View Controller インターフェイスの結合) を参照してください。
タブ内での移動
ナビゲーションは、ContentPage
オブジェクトが NavigationPage
オブジェクト内にラップされている場合に、タブ内で実行できます。 これを行うには、ContentPage
オブジェクトの Navigation
プロパティに対して PushAsync
メソッドを呼び出します。
await Navigation.PushAsync (new UpcomingAppointmentsPage ());
移動先のページは、PushAsync
メソッドへの引数として指定されます。 この例では、UpcomingAppointmentsPage
ページがナビゲーション スタックにプッシュされるようになり、そこがアクティブ ページとなります。
NavigationPage
クラスを使用してナビゲーションを実行する方法の詳細については、「階層ナビゲーション」を参照してください。
テンプレートを使って TabbedPage を作成する
データのコレクションを ItemsSource
プロパティに割り当て、データを Page
オブジェクトとしてテンプレート化する ItemTemplate
プロパティに DataTemplate
オブジェクトを割り当てることにより、TabbedPage
を作成できます。 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;
}
}
この例では、各タブは、Image
および Label
オブジェクトを使用してタブのデータを表示する ContentPage
オブジェクトで構成されています。
別のタブを選択すると、タブを表す ContentPage
オブジェクトが表示されます。