Xamarin.Forms TabbedPage
Xamarin.FormsTabbedPage
包含一系列选项卡和较大的详细信息区域,其中每个选项卡都可将内容加载到详细信息区域。 以下屏幕截图显示 iOS 和 Android 上的 TabbedPage
:
在 iOS 上,选项卡的列表显示在屏幕的底部,而详细信息区域显示在上方。 每个选项卡都包含一个标题和一个图标,该图标应为带有 alpha 通道的 PNG 文件。 如以纵向显示,选项卡栏图标位于选项卡标题上方。 如以横向显示,图标与标题并排显示。 此外,根据设备和方向,选项卡栏或显示为标准版或显示为缩减版。 如果有五个以上的选项卡,会显示“更多”选项卡,可用于访问其他选项卡。
在 Android 上,选项卡列表显示在屏幕顶部,详细信息区域显示在下方。 每个选项卡都包含一个标题和一个图标,该图标应为带有 alpha 通道的 PNG 文件。 但是,可以使用特定于平台的操作将选项卡移动至屏幕底部。 如果有五个以上的选项卡,且选项卡列表位于屏幕底部,会显示“更多”选项卡,可用于访问其他选项卡。 有关图标要求的信息,请参阅 material.io 上的选项卡和 developer.android.com 上的支持不同的像素密度。 有关将选项卡移动到屏幕底部的信息,请参阅设置 TabbedPage 工具栏位置和颜色。
在通用 Windows 平台 (UWP) 上,选项卡列表显示在屏幕顶部,详细信息区域显示在下方。 每个选项卡都包含一个标题。 但是,可以使用特定于平台布局向每个选项卡添加图标。 有关详细信息,请参阅 Windows 上的 TabbedPage 图标。
提示
可缩放矢量图形 (SVG) 文件可在 TabbedPage
中显示为选项卡图标:
- iOS
TabbedRenderer
类具有可替代的GetIcon
方法,可用于从指定的源加载选项卡图标。 此外,必要时可提供选定和未选定版本的图标。 - Android AppCompat
TabbedPageRenderer
类具有可替代的SetTabIconImageSource
方法,可用于从自定义Drawable
加载选项卡图标。 或者,SVG 文件可转换为矢量可绘制资源,它们可由 Xamarin.Forms 自动显示。 若要详细了解如何将 SVG 文件转换为矢量可绘制资源,请参阅 developer.android.com 上的添加多密度矢量图形。
创建 TabbedPage
可以使用两种方法创建 TabbedPage
:
- 使用子
Page
对象的集合(例如ContentPage
的集合)来填充TabbedPage
。 有关详细信息,请参阅使用页面集合填充 TabbedPage。 - 将集合分配给
ItemsSource
属性,并将DataTemplate
分配给ItemTemplate
属性以返回集合中对象的页面。 有关详细信息,请参阅使用模板填充 TabbedPage。
使用这两种方法,TabbedPage
将在用户选择每个标签时显示每个页面。
重要
建议仅使用 NavigationPage
和 ContentPage
实例填充 TabbedPage
。 这将有助于确保在所有平台上都有一致的用户体验。
此外,TabbedPage
定义以下属性:
Color
类型的BarBackgroundColor
,选项卡栏的背景色。Color
类型的BarTextColor
,选项卡栏上文本的颜色。Color
类型的SelectedTabColor
,选定选项卡后选项卡的颜色。Color
类型的UnselectedTabColor
,未选定选项卡时选项卡的颜色。
所有这些属性都由 BindableProperty
对象提供支持,这意味着可设置他们的样式,并且这些属性可以作为数据绑定的目标。
警告
在 TabbedPage
中,每个 TabbedPage
对象在构造 Page
时创建。 这可能会导致用户体验不佳,尤其是在 TabbedPage
是应用程序的根页面时。 但是,Xamarin.Forms Shell 可以根据需要创建通过选项卡栏访问的页面,以响应导航。 有关详细信息,请参阅 Xamarin.Forms Shell。
使用页集合填充 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>
注意
派生出 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);
}
}
在此示例中,使用了两个 Page
对象填充 TabbedPage
。 第一个子级是 ContentPage
对象,第二个子级是包含 ContentPage
对象的 NavigationPage
。
以下屏幕截图显示 TabbedPage
中的 ContentPage
对象:
选择另一个选项卡将显示表示该选项卡的 ContentPage
对象:
在“计划”选项卡上,ContentPage
对象包装在 NavigationPage
对象中。
警告
虽然 NavigationPage
可以放置在 TabbedPage
中,但不建议将 TabbedPage
放置到 NavigationPage
中。 这是因为,在 iOS 上,UITabBarController
始终充当 UINavigationController
的包装器。 有关详细信息,请参阅 iOS 开发人员库中的组合的视图控制器接口。
在选项卡中导航
导航可以在选项卡中执行,前提是 ContentPage
对象包装在 NavigationPage
对象中。 可以通过在 ContentPage
对象的 Navigation
属性上调用 PushAsync
方法来实现此操作:
await Navigation.PushAsync (new UpcomingAppointmentsPage ());
要导航到的页面被指定为 PushAsync
方法的参数。 在此示例中,将 UpcomingAppointmentsPage
页推送到导航堆栈中,在堆栈中,它成为活动页:
有关使用 NavigationPage
类执行导航的详细信息,请参阅分层导航。
使用模板填充 TabbedPage
通过将数据集合分配给 ItemsSource
属性,并将 DataTemplate
分配给将数据模板化为 Page
对象的 ItemTemplate
属性,可以用页填充 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;
}
}
在此示例中,每个选项卡都包含一个 ContentPage
对象,该对象使用 Image
和 Label
对象来显示该选项卡的数据:
选择另一个选项卡将显示表示该选项卡的 ContentPage
对象。