第二十五章:页面变化(五)

简介: TabbedPage TabbedPage派生自抽象类MultiPage 。它维护一个Page类型的子集合,其中只有一个一次完全可见。 TabbedPage通过页面顶部或底部的一系列选项卡标识每个子项。

TabbedPage

TabbedPage派生自抽象类MultiPage 。它维护一个Page类型的子集合,其中只有一个一次完全可见。 TabbedPage通过页面顶部或底部的一系列选项卡标识每个子项。使用TabbedPage的iOS应用程序必须包含每个选项卡的图标;否则,Apple将不接受App Store的程序。此图标通过每个页面的Icon属性设置。
MultiPage 定义TabbedPage的所有重要属性和事件,其中最重要的是:

  • IList类型的子属性。

通常,您使用页面对象填充此Children集合。
但是,您可以通过观察MultiPage 与ListView的基类ItemsView 非常相似来以稍微不同的方式使用TabbedPage,因为它定义了:

  • IEnnumerable类型的ItemsSource属性,和
  • DataTemplate类型的ItemTemplate属性。

如果提供具有适合数据绑定的公共属性的IEnumerable对象集合,以及具有页面类型作为根元素的模板,则会动态生成子项。该
每个生成的页面的BindingContext设置为等于ItemsSource中的特定对象。
MultiPage 定义了两个属性,可以帮助您的应用程序跟踪用户当前正在查看的Children集合中的哪个页面:

  • T类型的CurrentPage(TabbedPage的页面)。
  • 类型为object的SelectedItem,引用ItemsSource集合中的对象。两个属性都是gettable和settable。

MultiPage 还定义了两个事件:

  • TartsSource集合更改时触发PagesChanged
  • 查看的页面更改时会触发CurrentPageChanged。

最常见的是,您将直接将ContentPage衍生物添加到Children集合中。 如果要使用TabbedPage基于数据集合显示类似页面的集合,您可以选择将ItemsSource属性设置为该集合并使用ItemTemplate定义页面,但在iOS上应避免使用此方法。
离散标签页
TabbedPage的最常见用途是在应用程序中的不同功能之间导航,这通常意味着每个选项卡呈现不同类型的页面。 这些页面通常以某种方式相关 - 也许是应用程序设置的多个页面 - 即使它们看起来不一样。
DiscreteTabbedColors程序有三个选项卡:第一个显示内置Xamarin.Forms颜色的列表,第二个显示Xamarin.FormsBook.Toolkit(前面章节中介绍)中NamedColor类的颜色列表,第三个选项卡 包含颜色测试仪(您可以使用它选择任意RGB值进行预览)。
DiscreteTabbedColors程序以三个ContentPage衍生物开头。 第一个是codeonly,由一个简单的标准Xamarin.Forms颜色列表组成。

class BuiltInColorsPage : ContentPage
{
    public BuiltInColorsPage()
    {
        Title = "Built-in";
        Icon = Device.OnPlatform("ic_action_computer.png", null, null);
        Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5);
        double fontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label));
        Content = new ScrollView
        {
            Content = new StackLayout
            {
                Spacing = 0,
                Children =
                {
                    new Label
                    {
                        Text = "White",
                        TextColor = Color.White,
                        FontSize = fontSize
                    },
                    __
                    new Label
                    {
                        Text = "Purple",
                        TextColor = Color.Purple,
                        FontSize = fontSize
                    }
                }
            }
        };
    }
}

请注意,Title属性已设置。 这对于所有平台上的选项卡文本都很重要。 该代码还为iOS设置了Icon属性。 特定图标是第13章“位图”中描述的Android图标集的一部分,并且是32像素的正方形。
NamedColorsPage由所有NamedColor对象的ListView组成。 再次注意iOS的Title属性和Icon属性:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit=
                 "clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
             x:Class="DiscreteTabbedColors.NamedColorsPage"
             Title="Toolkit">
    <ContentPage.Icon>
        <OnPlatform x:TypeArguments="FileImageSource"
                    iOS="ic_action_storage.png" />
    </ContentPage.Icon>
    <ListView ItemsSource="{x:Static toolkit:NamedColor.All}">
        <ListView.RowHeight>
            <OnPlatform x:TypeArguments="x:Int32"
                        iOS="80"
                        Android="80"
                        WinPhone="90" />
        </ListView.RowHeight>

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <ContentView Padding="5">
                        <StackLayout Orientation="Horizontal">
                            <BoxView x:Name="boxView"
                                     Color="{Binding Color}"
                                     WidthRequest="50"
                                     HeightRequest="50" />
                            <StackLayout>
                                <Label Text="{Binding Name}"
                                       FontSize="Medium"
                                       VerticalOptions="StartAndExpand" />
                                <Label Text="{Binding RgbDisplay, StringFormat='RGB = {0}'}"
                                       FontSize="Small"
                                       VerticalOptions="CenterAndExpand" />
                            </StackLayout>
                        </StackLayout>
                    </ContentView>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

第三页包含三个Slider元素来选择颜色,例如您之前见过的:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit=
                 "clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
             x:Class="DiscreteTabbedColors.ColorTestPage"
             Title="Test">
    <ContentPage.Icon>
        <OnPlatform x:TypeArguments="FileImageSource"
                    iOS="ic_action_gamepad.png" />
    </ContentPage.Icon>
    <StackLayout Padding="20, 40">
        <StackLayout.BindingContext>
            <toolkit:ColorViewModel Color="Gray" />
        </StackLayout.BindingContext>

        <Label Text="{Binding Red, StringFormat='Red = {0:F2}'}"
               HorizontalOptions="Center" />
        <Slider Value="{Binding Red}" />
        <Label Text="{Binding Green, StringFormat='Green = {0:F2}'}"
               HorizontalOptions="Center" />
        <Slider Value="{Binding Green}" />
        <Label Text="{Binding Blue, StringFormat='Blue = {0:F2}'}"
               HorizontalOptions="Center" />
        <Slider Value="{Binding Blue}" />
        <BoxView Color="{Binding Color}"
                 VerticalOptions="FillAndExpand" />
    </StackLayout>
</ContentPage>

这是DiscreteTabbedColorsPage。 注意TabbedPage的根元素。 此XAML文件只是将这三种页面类型的实例添加到TabbedPage的Children集合中:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:local="clr-namespace:DiscreteTabbedColors"
            x:Class="DiscreteTabbedColors.DiscreteTabbedColorsPage">
    <local:BuiltInColorsPage />
    <local:NamedColorsPage />
    <local:ColorTestPage />
</TabbedPage>

以下是三个平台上的三个选项卡:
2019_05_09_090941
在iOS上,选项卡位于底部,标有文本和图标,突出显示所选选项卡。 Android和Windows 10 Mobile都会在屏幕顶部显示选项卡,但会以不同方式突出显示所选选项卡。
StudentNotes程序有一个主页,列出ListView中的所有学生,但从该列表中选择一个学生会导致程序导航到TabbedPage。该页面有三个选项卡:第一个显示关于学生的文本信息,第二个显示学生的照片,第三个显示编辑器,允许教师或其他学校管理员输入关于学生的一些注释。 (此功能使用SchoolOfFineArt库中Student类的Notes属性。)
StudentNotes程序中的App类将Application定义的Properties字典传递给SchoolViewModel构造函数,并在程序进入休眠状态时将Properties字典传递给ViewModel的SaveNotes方法,可能是为了准备终止:

public class App : Application
{
    public App()
    {
        ViewModel = new SchoolViewModel(Properties);
        MainPage = new NavigationPage(new StudentNotesHomePage());
    }
    public SchoolViewModel ViewModel
    {
        private set; get;
    }
    protected override void OnStart()
    {
        // Handle when your app starts
    }
    protected override void OnSleep()
    {
        ViewModel.SaveNotes(Properties);
    }
    protected override void OnResume()
    {
        // Handle when your app resumes
    }
}

现在主页应该看起来很熟悉。 它只显示ListView中的所有学生:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:StudentNotes;assembly=StudentNotes"
             x:Class="StudentNotes.StudentNotesHomePage"
             Title="Students"
             BindingContext="{Binding Source={x:Static Application.Current},
                                      Path=ViewModel}">
    <StackLayout BindingContext="{Binding StudentBody}">
        <Label Text="{Binding School}"
               FontSize="Large"
               FontAttributes="Bold"
               HorizontalTextAlignment="Center" />
        <ListView x:Name="listView"
                  ItemsSource="{Binding Students}"
                  ItemSelected="OnListViewItemSelected">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ImageCell ImageSource="{Binding PhotoFilename}"
                               Text="{Binding FullName}"
                               Detail="{Binding GradePointAverage,
                                                StringFormat='G.P.A. = {0:F2}'}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

代码隐藏文件包含ListView的ItemSelected处理程序,用于导航到StudentNotesDataPage,将页面的BindingContext设置为选定的Student对象:

public partial class StudentNotesHomePage : ContentPage
{
    public StudentNotesHomePage()
    {
        InitializeComponent();
    }
    async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args)
    {
        if (args.SelectedItem != null)
        {
            listView.SelectedItem = null;
            await Navigation.PushAsync(new StudentNotesDataPage
            {
                BindingContext = args.SelectedItem
            });
        }
    }
}

StudentNotesDataPage派生自TabbedPage。 在TabbedPage的开始和结束标记内,三个ContentPage定义被添加到TabbedPage的Children属性中。 每个都将其Title属性设置为要在选项卡中使用的文本,并为iOS包含Icon定义:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="StudentNotes.StudentNotesDataPage"
            Title="Student Data">
    <ContentPage Title="Info">
        <ContentPage.Icon>
            <OnPlatform x:TypeArguments="FileImageSource"
                        iOS="ic_action_about.png" />
        </ContentPage.Icon>

        <StackLayout>
            <Label Text="{Binding FullName}"
                   FontSize="Large"
                   HorizontalOptions="Center" />
            <StackLayout Spacing="12"
                         VerticalOptions="CenterAndExpand"
                         HorizontalOptions="Center">
                <StackLayout.Resources>
                    <ResourceDictionary> 
                        <Style TargetType="Label">
                            <Setter Property="FontSize" Value="Large" />
                        </Style>
                    </ResourceDictionary>
                </StackLayout.Resources>

                <Label Text="{Binding LastName, 
                                      StringFormat='Last name: {0}'}" />

                <Label Text="{Binding FirstName, 
                                      StringFormat='First name: {0}'}" />

                <Label Text="{Binding MiddleName, 
                                      StringFormat='Middle name: {0}'}" />

                <Label Text="{Binding Sex, 
                                      StringFormat='Sex: {0}'}" />

                <Label Text="{Binding GradePointAverage, 
                                      StringFormat='G.P.A. = {0:F2}'}" />
            </StackLayout>
        </StackLayout>
    </ContentPage>
    <ContentPage Title="Photo">
        <ContentPage.Icon>
            <OnPlatform x:TypeArguments="FileImageSource"
                        iOS="ic_action_person.png" />
        </ContentPage.Icon>

        <StackLayout>
            <Label Text="{Binding FullName}"
                   FontSize="Large"
                   HorizontalOptions="Center" />
            <Image Source="{Binding PhotoFilename}"
                   VerticalOptions="FillAndExpand" />
        </StackLayout>
    </ContentPage>
    <ContentPage Title="Notes">
        <ContentPage.Icon>
            <OnPlatform x:TypeArguments="FileImageSource"
                        iOS="ic_action_edit.png" />
        </ContentPage.Icon>

        <StackLayout>
            <Label Text="{Binding FullName}"
                   FontSize="Large"
                   HorizontalOptions="Center" />
            <Editor Text="{Binding Notes}"
                    Keyboard="Text"
                    VerticalOptions="FillAndExpand" />
        </StackLayout>
    </ContentPage>
</TabbedPage>

这可能不足以分散三页,但您可以轻松想象这种方法理想的情况。
以下是三个平台在三个平台上的外观:
2019_05_09_092319
您可以按正常方式导航回学生列表:点击iOS和Android屏幕顶部的左箭头,或者按Android和Windows 10 Mobile屏幕底部的后退箭头。

目录
相关文章
|
1月前
|
开发工具 索引
点击一个消除游戏图标时,背后都发生了什么
点击一个消除游戏图标时,背后都发生了什么
40 1
|
8月前
|
存储 小程序 前端开发
【易售小程序项目】小程序私聊页面完善(带尾巴聊天气泡组件封装、滑至顶端获取历史聊天数据逻辑优化)【后端基于若依管理系统开发】
【易售小程序项目】小程序私聊页面完善(带尾巴聊天气泡组件封装、滑至顶端获取历史聊天数据逻辑优化)【后端基于若依管理系统开发】
37 0
|
9月前
|
Web App开发 前端开发 JavaScript
使用函数节流思想避免 SAP UI5 应用里按钮短时间内被高频重复点击试读版
使用函数节流思想避免 SAP UI5 应用里按钮短时间内被高频重复点击试读版
聊天框(番外篇)—如何实现@功能的整体删除
上一篇文章中,我们已经初步实现了聊天输入框,但其@功能是不完善的,例如无法整体删除、无法获取除用户名以外的数据(假设用户名不是唯一的)。有问题就要想办法解决,在网上百度了一圈后,倒是有一些收获。本文就着重解决@的整体删除以及获取额外数据。
985 0
聊天框(番外篇)—如何实现@功能的整体删除
|
11月前
|
数据采集 监控 数据可视化
做出酷炫的动态统计图表,不一定要写代码
首先这个名字很长的,就是上面 GDP 图表的作者 Jannchie见齐 基于 D3.js 开发的 将历史数据排名转化为动态柱状图图表 的项目,并在 github 上开源了。
|
Java
手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏20之enemy被攻击显示后退动画(block效果)
手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏20之enemy被攻击显示后退动画(block效果)
142 0
|
前端开发
前端工作总结244-修改其他页面的时间逻辑
前端工作总结244-修改其他页面的时间逻辑
69 0
|
SQL JavaScript 前端开发
【自然框架】之鼠标点功能现(二):表单控件的“应用”—— 代码?只写需要的!
  【自然框架】之鼠标点功能现(一):单表的增删改查(即上次5月23日活动的一个主题)【Demo、源码下载】           看了大家的回复,好像不少人误会了,我为了突出“鼠标点,功能现”,所以没有说代码,没有贴代码,这就让一些人认为我想要完全抛弃VS,自己写一个“平台”来代替,不好意思,您高估我了,我可达不到。
850 0
|
Web App开发 SQL JavaScript
【自然框架】分享 n级联动下拉列表框
  特点:1、 使用js方法,把需要的数据一次性写入到页面里,然后用js来实现联动的效果。2、 支持n级。3、 封装成了服务器控件,所以使用非常简单。4、 支持在回发的时候保持状态。5、 支持修改记录的时候设置默认选项。
1234 0
|
Android开发 Windows iOS开发
第二十五章:页面变化(六)
使用ItemTemplateTabbedPage还可用于呈现小数据集,每个数据集是由选项卡标识的单独页面。 您可以通过设置TabbedPage的ItemsSource属性并指定用于呈现每个页面的ItemTemplate来完成此操作。
539 0