Xamarin 中的 watchOS 表控件

watchOS WKInterfaceTable 控件比 iOS 控件简单得多,但两者的作用类似。 它创建一个可以采用自定义布局并响应触摸事件的滚动行列表。

监视表列表监视表详细信息

添加表

将“表”控件拖放到场景中。 默认情况下,其外观如下(显示单个未指定的行布局):

添加表

在“属性”面板的“名称”框中为表命名,以便可以在代码中引用它

添加行控制器

该表自动包含一行,该行默认由包含“组”控件的行控制器表示

若要设置行控制器的“类”,请选择“文档大纲”中的行,然后在“属性”面板中键入类名称

在 Properties Pad 中输入类名

设置行控制器的类后,IDE 将在项目中创建相应的 C# 文件。 将控件(例如标签)拖放到行上,并为其命名,以便可以在代码中引用它们。

创建并填充行

SetNumberOfRows 为每一行创建行控制器类,并使用 Identifier 选择正确的类。 如果为行控制器提供了自定义 Identifier,请将以下代码片段中的 default 更改为你使用的标识符。 每一行的 RowController 是在调用 SetNumberOfRows 和显示表时创建的

myTable.SetNumberOfRows ((nint)rows.Count, "default");
    // loads row controller by identifier

重要

表行不像在 iOS 中那样被虚拟化。 请尽量限制行数(Apple 建议少于 20 个)。

创建行后,需要填充每个单元格(就像 iOS 中的 GetCell 所做的那样)。 此代码片段更新每行中的标签:

for (var i = 0; i < rows.Count; i++) {
    var elementRow = (RowController)myTable.GetRowController (i);
    elementRow.myRowLabel.SetText (rows [i]);
}

重要

使用 SetNumberOfRows,然后使用 GetRowController 进行循环访问会导致将整个表发送到手表。 在表的后续视图中,如果需要添加或删除特定行,请使用 InsertRowsAtRemoveRowsAt 以获得更好的性能。

响应点击

可以通过两种不同的方式响应行选择:

  • 在接口控制器上实现 DidSelectRow 方法,或者
  • 如果你希望行选择操作打开另一个场景,请在情节提要上创建一个 Segue 并实现 GetContextForSegue

DidSelectRow

若要以编程方式处理行选择,请实现 DidSelectRow 方法。 若要打开新场景,请使用 PushController 并传递场景的标识符以及要使用的数据上下文:

public override void DidSelectRow (WKInterfaceTable table, nint rowIndex)
{
    var rowData = rows [(int)rowIndex];
    Console.WriteLine ("Row selected:" + rowData);
    // if selection should open a new scene
    PushController ("secondInterface", rows[(int)rowIndex]);
}

GetContextForSegue

将情节提要上的 Segue 从表行拖放到另一个场景(拖动时按住 Ctrl 键)。 请务必选择 Segue 并在“属性”面板中为其指定一个标识符(例如以下示例中的 secondLevel)。

在接口控制器中,实现 GetContextForSegue 方法并返回应提供给 Segue 呈现的场景的数据上下文。

public override NSObject GetContextForSegue (string segueIdentifier, WKInterfaceTable table, nint rowIndex)
{
    if (segueIdentifier == "secondLevel") {
        return new NSString (rows[(int)rowIndex]);
    }
    return null;
}

此数据通过其 Awake 方法传递给目标情节提要场景。

多行类型

默认情况下,表控件具有可设计的单行类型。 若要添加更多行“模板”,请使用“属性”面板中的“行”框来创建更多行控制器

设置原型行数

将“行数”属性设置为 3 会创建额外的行占位符,供你将控件拖入其中。 对于每一行,请在“属性”面板中设置类名称,以确保创建行控制器类

设计器中的原型行

若要使用不同的行类型填充表,请使用 SetRowTypes 方法指定表中每行要使用的行控制器类型。 使用行的标识符指定每行应使用哪个行控制器。

此数组中的元素数量应与表中预期的行数匹配:

myTable.SetRowTypes (new [] {"type1", "default", "default", "type2", "default"});

使用多个行控制器填充表时,需要在填充 UI 时跟踪预期的类型:

for (var i = 0; i < rows.Count; i++) {
    if (i == 0) {
        var elementRow = (Type1RowController)myTable.GetRowController (i);
        // populate UI controls
    } else if (i == 3) {
        var elementRow = (Type2RowController)myTable.GetRowController (i);
        // populate UI controls
    } else {
        var elementRow = (DefaultRowController)myTable.GetRowController (i);
        // populate UI controls
    }
}

垂直详细信息分页

watchOS 3 为表引入了一项新功能:能够滚动浏览与每行相关的详细信息页,而无需返回表并选择另一行。 可以通过上下滑动或使用 Digital Crown 来滚动详细信息屏幕。

垂直详细信息分页示例垂直分页详细信息

重要

目前只能通过在 Xcode Interface Builder 中编辑情节提要来使用此功能。

若要启用此功能,请选择设计图面上的 WKInterfaceTable,并勾选“垂直详细信息分页”选项

选择“垂直详细信息分页”选项

如 Apple 所解释的那样,表导航必须使用 Segues 才能使分页功能发挥作用。 重写任何使用 PushController 的现有代码以改用 Segue。

附录:行控制器代码示例

在设计器中创建行控制器时,IDE 将自动创建两个代码文件。 下面显示了这些生成的文件中的代码以供参考。

第一个文件根据类命名,例如 RowController.cs,如下所示

using System;
using Foundation;

namespace WatchTablesExtension
{
    public partial class RowController : NSObject
    {
        public RowController ()
        {
        }
    }
}

另一个 .designer.cs 文件是一个分部类定义,其中包含在设计器图面上创建的输出口和操作,例如此示例包含一个 WKInterfaceLabel 控件:

using Foundation;
using System;
using System.CodeDom.Compiler;
using UIKit;

namespace WatchTables.OnWatchExtension
{
    [Register ("RowController")]
    partial class RowController
    {
        [Outlet]
        [GeneratedCode ("iOS Designer", "1.0")]
        public WatchKit.WKInterfaceLabel MyLabel { get; set; }

        void ReleaseDesignerOutlets ()
        {
            if (MyLabel != null) {
                MyLabel.Dispose ();
                MyLabel = null;
            }
        }
    }
}

然后可以在代码中引用此处声明的输出口和操作 - 但不要直接编辑 .designer.cs 文件