Xamarin.iOS 中的选项卡栏和选项卡栏控制器

选项卡式应用程序在 iOS 中使用,以支持用户界面,其中多个屏幕不能按特定顺序进行访问。 通过 UITabBarController 此类,应用程序可以轻松包含对此类多屏幕方案的支持。 UITabBarController 负责多屏管理,使应用程序开发人员能够专注于每个屏幕的详细信息。

通常,选项卡式应用程序生成时,UITabBarController 是主窗口的 RootViewController。 但是,通过一些额外的代码,选项卡式应用程序还可以连续使用到其他一些初始屏幕,例如应用程序首次显示登录屏幕的方案,后跟选项卡式界面。

本页讨论了这两种情况:当选项卡位于应用程序视图层次结构的根目录下,以及非 RootViewController 方案中。

UITabBarController 简介

UITabBarController 支持按选项卡式应用程序开发,如下所示:

  • 允许将多个控制器添加到其中。
  • 通过 UITabBar 类提供选项卡式用户界面,以允许用户在控制器与其视图之间切换。

控制器通过其 ViewControllers 属性(即 UIViewController 数组)添加到 UITabBarControllerUITabBarController 本身处理加载正确的控制器,并根据所选选项卡显示其视图。

选项卡是 UITabBarItem 类的实例,包含在 UITabBar 实例中。 每个 UITabBar 实例都可以通过每个选项卡中控制器的 TabBarItem 属性进行访问。

若要了解如何使用 UITabBarController,让我们逐步了解如何构建使用的简单应用程序。

选项卡式应用程序演练

在本演练中,我们将创建以下应用程序:

示例选项卡式应用

尽管 Visual Studio for Mac 中已经有一个选项卡式应用程序模板,但对于此示例,这些说明适用于空项目,以便更好地了解应用程序的构造方式。

创建应用程序

首先创建新的应用程序。

在 Visual Studio for Mac 中选择“文件”新建”“解决方案”>>菜单项,然后选择“iOS”“应用”“空项目”模板>>,将项目命名为 TabbedApplication,如下所示:

选择空项目模板

将项目命名为 TabbedApplication

添加 UITabBarController

接下来,通过选择“文件”“新建文件”>并选择“常规:空类”模板来添加空类。 将文件命名为 TabController,如下所示:

添加 TabController 类

TabController 类将包含将管理 UIViewControllers 数组的 UITabBarController 的实现。 当用户选择选项卡时,UITabBarController 将负责为相应的视图控制器显示视图。

若要实现 UITabBarController,需要执行以下操作:

  1. TabController 的基类设置为 UITabBarController
  2. 创建要添加到 TabControllerUIViewController 实例。
  3. UIViewController 实例添加到分配给 TabControllerViewControllers 属性的数组。

将以下代码添加到 TabController 类以实现以下步骤:

using System;
using UIKit;

namespace TabbedApplication {
    public class TabController : UITabBarController {

        UIViewController tab1, tab2, tab3;

        public TabController ()
        {
            tab1 = new UIViewController();
            tab1.Title = "Green";
            tab1.View.BackgroundColor = UIColor.Green;

            tab2 = new UIViewController();
            tab2.Title = "Orange";
            tab2.View.BackgroundColor = UIColor.Orange;

            tab3 = new UIViewController();
            tab3.Title = "Red";
            tab3.View.BackgroundColor = UIColor.Red;

            var tabs = new UIViewController[] {
                tab1, tab2, tab3
            };

            ViewControllers = tabs;
        }
    }
}

请注意,对于每个 UIViewController 实例,我们设置 UIViewControllerTitle 属性。 将控制器添加到 UITabBarController时,UITabBarController 将读取每个控制器的 Title,并将其显示在关联的选项卡标签上,如下所示:

示例应用运行

将 TabController 设置为 RootViewController

控制器放置在选项卡中的顺序与它们添加到 ViewControllers 数组的顺序相对应。

若要获取作为第一个屏幕加载的 UITabController,我们需要将其设置为窗口的 RootViewController,如以下 AppDelegate 代码所示:

[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
    UIWindow window;
    TabController tabController;

    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        window = new UIWindow (UIScreen.MainScreen.Bounds);

        tabController = new TabController ();
        window.RootViewController = tabController;

        window.MakeKeyAndVisible ();

        return true;
    }
}

如果现在运行应用程序,则 UITabBarController 将加载默认选择的第一个选项卡。 选择任何其他选项卡会导致 UITabBarController, 呈现关联的控制器视图,如下所示,最终用户选择了第二个选项卡:

显示的第二个选项卡

修改 TabBarItems

现在,我们有了一个正在运行的选项卡应用程序,让我们修改 TabBarItem 以更改显示的图像和文本,以及向其中一个选项卡添加锁屏提醒。

设置系统项

首先,设置第一个选项卡以使用系统项。 在 TabController 的构造函数中,删除为 tab1 实例设置控制器 Title 的行,并将其替换为以下代码来设置控制器的 TabBarItem 属性:

tab1.TabBarItem = new UITabBarItem (UITabBarSystemItem.Favorites, 0);

使用 UITabBarSystemItem 创建 UITabBarItem 时,iOS 会自动提供标题和图像,如以下屏幕截图中所示,第一个选项卡上的收藏夹图标和标题:

带有星形图标的第一个选项卡

设置图像

除了使用系统项,UITabBarItem 的标题和图像还可以设置为自定义值。 例如,更改设置 tab2 控制器 TabBarItem 属性的代码,如下所示:

tab2 = new UIViewController ();
tab2.TabBarItem = new UITabBarItem ();
tab2.TabBarItem.Image = UIImage.FromFile ("second.png");
tab2.TabBarItem.Title = "Second";
tab2.View.BackgroundColor = UIColor.Orange;

上述代码假定已将名为 second.png 的图像添加到项目的根目录(或“资源”目录)。 若要支持所有屏幕密度,需要三个图像,如下所示:

添加到项目的图像

建议的大小因图像的样式而异(圆形、方形、宽或高)。

Image 属性只需设置为 second.png 文件名,iOS 将在需要时自动加载更高分辨率的文件。 可以在使用图像指南中详细了解这一点。 默认情况下,选项卡栏项为灰色,选中时为蓝色色调。

重写标题

直接在 TabBarItem 上设置 Title 属性时,它将替代控制器本身上为 Title 设置的任何值。

此屏幕截图中的第二个(中间)选项卡显示自定义标题和图像:

带有正方形图标的第二个选项卡

设置锁屏提醒值

选项卡还可以显示锁屏提醒。 例如,添加以下代码行以设置第三个选项卡上的锁屏提醒:

tab3.TabBarItem.BadgeValue = "Hi";

运行此结果会生成一个红色标签,其中选项卡左上角的字符串为“Hi”,如下所示:

带有“你好”锁屏提醒的第二个选项卡

锁屏提醒通常用于显示数字指示未读的新项。 若要删除锁屏提醒,请将 BadgeValue 设置为 null,如下所示:

tab3.TabBarItem.BadgeValue = null;

非 RootViewController 方案中的选项卡

在上面的示例中,我们演示了如何在窗口 RootViewController 时使用 UITabBarController。 在此示例中,我们将检查当 UITabBarController 不是 RootViewController 时如何使用,并演示如何使用 Storyboard。

初始屏幕示例

对于这种情况,初始屏幕从不是 UITabBarController 的控制器加载。 当用户通过点击按钮与屏幕交互时,相同的视图控制器将加载到 UITabBarController 中,然后向用户显示。 以下屏幕截图显示了应用程序流:

此屏幕截图显示了应用程序流

让我们为此示例启动一个新的应用程序。 同样,我们将使用 iPhone > 应用 > 空项目 (C#) 模板,这次命名项目 InitialScreenDemo

在此示例中,情节提要用于布局视图控制器。 添加情节提要:

  • 右键单击项目名称,然后选择“添加”“新文件”>

  • 出现“新建文件”对话框时,导航到 iOS > 空 iPhone 情节提要

让我们调用这个新的情节提要 MainStoryboard,如下所示:

将 MainStoryboard 文件添加到项目

将情节提要添加到以前非情节提要文件时,需要注意一些重要步骤,这些文件在情节提要简介指南中进行了介绍。 这些功能是:

  1. 将情节提要名称添加到 Info.plist 的“主接口”部分:

    将 Main 接口设置为 MainStoryboard

  2. App Delegate 中,使用以下代码重写 Window 方法:

    public override UIWindow Window {
        get;
        set;
    }
    

本示例需要三个视图控制器。 名为 ViewController1的一个将用作初始视图控制器,并在第一个选项卡中使用。另外两个名称分别为 ViewController2ViewController3,分别用于第二个和第三个选项卡。

双击 MainStoryboard.storyboard 文件打开设计器,然后将三个视图控制器拖到设计图面。 我们希望每个视图控制器都有其自己的类对应于上述名称,因此,在标识>类下,键入其名称,如以下屏幕截图所示:

将类设置为 ViewController1

Visual Studio for Mac 将自动生成所需的类和设计器文件,这可在 Solution Pad 中看到,如下所示:

项目中自动生成的文件

创建 UI

接下来,我们将使用 Xamarin iOS 设计器为每个 ViewController 视图创建一个简单的用户界面。

我们希望将 LabelButton 从右侧的工具箱拖到 ViewController1 上。 接下来,我们将使用 Properties Pad 将控件的名称和文本编辑为以下内容:

  • 标签Text = One
  • 按钮Title = 用户执行一些初始操作

我们将在 TouchUpInside 事件中控制按钮的可见性,我们需要在代码隐藏中引用它。 让我们使用 Properties Pad 中的名称aButton来标识它,如以下屏幕截图所示:

在 Properties Pad 中将“名称”设置为 aButton

设计图面现在应类似于以下屏幕截图:

设计图面现在应类似于此屏幕截图

让我们添加一些更多详细信息来 ViewController2ViewController3,方法是向每个标签添加一个标签,并将文本分别更改为“Two”和“Three”。 这突出显示了要查看的用户的选项卡/视图。

连接按钮

在应用程序首次启动时,我们将加载 ViewController1。 当用户点击该按钮时,我们将隐藏该按钮,并使用第一个选项卡中的 ViewController1 实例加载 UITabBarController

当用户释放 aButton 时,我们希望触发 TouchUpInside 事件。 让我们选择该按钮,然后在 Properties pad 的“事件”选项卡中,声明事件处理程序 InitialActionCompleted,以便可以在代码中引用它。 以下屏幕截图对此进行了说明:

当用户释放 aButton 时,触发 TouchUpInside 事件

现在,我们需要告诉视图控制器在事件触发 InitialActionCompleted 时隐藏按钮。 在 ViewController1 中添加以下分部方法:

partial void InitialActionCompleted (UIButton sender)
{
    aButton.Hidden = true;  
}

保存文件并运行应用程序。 应看到屏幕一出现,按钮在“触摸上”上消失。

添加选项卡栏控制器

我们现在有一个初始视图按预期工作。 接下来,我们希望将其添加到 UITabBarController,以及视图 2 和 3。 让我们在设计器中打开情节提要。

工具箱中,在控制器和对象下搜索“选项卡栏控制器”,并将其拖到设计图面上。 如下面的屏幕截图所示,选项卡栏控制器无 UI,因此默认会引入两个视图控制器:

将选项卡栏控制器添加到布局

通过选择底部的黑色条并按 Delete 键来删除这些新的视图控制器。

在我们的情节提要中,可以使用 Segues 处理 TabBarController 和视图控制器之间的转换。 与初始视图交互后,我们希望将其加载到向用户显示的 TabBarController 中。 让我们在设计器中设置此值。

按住 Ctrl 键单击并从按钮拖动到 TabBarController。 鼠标往上时,将显示上下文菜单。 我们希望使用模式 segue。

要设置每个标签页,请按住 Ctrl 键,从 TabBarController 依次点击视图控制器,然后从上下文菜单中选择“关系”“标签页”,如下图所示:

选择选项卡关系

情节提要应类似于下面的屏幕截图:

情节提要应类似于此屏幕截图

如果我们单击其中一个选项卡栏项并浏览属性面板,可以看到许多不同的选项,如下所示:

在属性资源管理器中设置选项卡选项

我们可以使用它来编辑某些属性,例如锁屏提醒、标题和 iOS 标识符等。

如果现在保存并运行应用程序,则会发现当 ViewController1 实例加载到 TabBarController 中时,按钮会重新出现。 让我们通过检查当前视图是否具有父视图控制器来解决此问题。 如果确实如此,我们知道我们位于 TabBarController 中,因此应该隐藏该按钮。 让我们将下面的代码添加到 ViewController1 类:

public override void ViewDidLoad ()
{
    if (ParentViewController != null){
        aButton.Hidden = true;
    }
}

当应用程序运行时,用户点击第一个屏幕上的按钮时,将加载 UITabBarController,第一个选项卡中的第一个屏幕中的视图如下所示:

示例应用输出

总结

本文介绍了如何在应用程序中使用 UITabBarController。 我们演练了如何将控制器加载到每个选项卡中,以及如何在诸如标题、图像和锁屏提醒等选项卡上设置属性。 然后,我们使用情节提要检查,如何在不是窗口的 RootViewController 时在运行时加载 UITabBarController