在 Xamarin 中使用 tvOS 导航和焦点

本文介绍 Focus 的概念及其用于演示和处理 Xamarin.tvOS 应用中的导航的方式。

本文介绍 Focus 的概念及其用于处理 Xamarin.tvOS 应用用户界面中的导航的方式。 我们将研究内置 tvOS 导航控件如何使用焦点、突出显示和选择来提供 Xamarin.tvOS 应用的用户界面导航。

tvOS apps User Interface Navigation

接下来,我们将了解焦点如何与视差分层图像一起使用,以便为最终用户提供当前导航状态的视觉线索。

最后,我们将了解如何使用焦点、焦点汇报、焦点参考线、集合中的焦点和在 Xamarin.tvOS 应用中启用图像视图的视差

Xamarin.tvOS 应用的用户不会直接与其界面交互,就像在 iOS 中点击设备屏幕上的图像一样,而是使用 Siri 远程从房间间接交互。 设计应用的用户界面时,需要记住这一点,以便它自然流动,但仍使用户沉浸于 Apple TV 体验中。

成功的 tvOS 应用以流畅地支持应用的目的和它呈现的数据结构的方式实现导航,而无需引起对导航本身的注意。 设计导航,使其感觉自然而熟悉,而无需主宰用户界面或从内容和应用用户体验中吸引焦点。

The tvOS settings app

使用 Apple TV 时,用户通常会浏览一组堆积的屏幕,每个屏幕都呈现一组给定的内容。 反过来,每个新屏幕都可能导致一个或多个使用标准 UI 控件(如按钮、制表、集合视图或拆分视图)的内容子屏幕。

使用每个新数据屏幕时,用户会更深入地导航到此屏幕堆栈。 通过使用 Siri Remote 上的“菜单” 按钮,他们可以在堆栈中向后导航,返回到上一个屏幕或主菜单。

Apple 建议在设计 tvOS 应用的导航时记住以下几点:

  • 将导航布局为快速轻松地 查找内容 - 用户希望尽可能少地访问应用中的内容,只需点击次数、单击和轻扫即可。 简化导航并将内容组织到最少数量的屏幕。
  • 使用触摸创建 Fluid Interface - 确保用户可以使用尽可能少的手势在可聚焦项目之间移动,同时尽量减少摩擦。
  • 在 Mind 中使用焦点进行设计 - 由于用户与会议室中的内容交互,因此他们需要在使用 Siri 远程交互之前将焦点移动到用户界面项。 如果用户需要太多手势才能达到自己的目标,用户会对你的应用感到沮丧。
  • 通过菜单按钮提供向后导航 - 若要创建轻松熟悉的体验,允许用户使用 Siri 远程菜单按钮向后导航。 按“菜单”按钮应始终返回到上一个屏幕或返回到应用的“主菜单”。 在应用的顶层,按 “菜单” 按钮应返回到 Apple TV 主屏幕。
  • 通常避免显示后退按钮 - 因为 按 Siri 远程上的菜单 按钮在屏幕堆栈中向后导航,因此避免显示重复此行为的额外控件。 此规则的例外情况是购买具有破坏性操作的屏幕或屏幕(例如删除内容), 其中还应显示“取消” 按钮。
  • 在单个屏幕上显示大型集合,而不是许多 - Siri 远程版旨在通过大量内容快速轻松地使用手势移动。 如果你的应用适用于大量可聚焦项,请考虑将它们保留在单个屏幕上,而不是将它们分解成许多屏幕,这需要用户部分的更多导航。
  • 使用标准控件导航 - 同样,可以创建一个简单熟悉的用户体验,尽可能使用内置 UIKit 控件,如页面控件、制表条、分段控件、表视图、集合视图和拆分视图,以便应用导航。 由于用户已经熟悉这些元素,因此他们可以直观地导航应用。
  • 偏向水平内容导航 - 由于苹果电视的性质,在 Siri 远程上向右轻扫比上下更自然。 在为应用设计内容布局时,请考虑此选项。

焦点和选择

在 Apple TV 上,当图像、按钮或其他 UI 元素是当前导航的目标时,它被视为 焦点

Focus and Selection example

与 iOS 设备不同,如果用户直接与设备上的触摸屏上的元素交互,则用户使用 Siri 远程从房间内与 tvOS 元素进行交互。 为了呈现和处理此用户交互,Apple TV 使用 基于焦点 的模型。

使用 Siri Remote 上的手势和按钮按下,用户将焦点从一个 UI 元素移动到另一个 UI 元素。 焦点转移到所需元素后,用户单击以选择内容或激活该元素表示的操作。

随着焦点的变化,微妙的动画和效果(如图像上的视差效果)用于清楚地标识当前具有焦点的用户界面项。

Apple 提供以下使用焦点和选择的建议:

  • 对动作效果 使用内置 UI 控件 - 通过使用 UIKit 用户界面中的焦点 API,焦点模型将自动将默认动作和视觉效果应用于 UI 元素。 这使你的应用对 Apple TV 平台的用户感到本机和熟悉,并允许在可聚焦项目之间流畅直观地移动。
  • 在预期方向 移动焦点 - 在 Apple TV 上,几乎每个元素都使用间接操作。 例如,用户使用 Siri Remote 移动焦点,并且系统会自动滚动界面,使当前聚焦的项目保持可见。 如果你的应用实现了这种类型的交互,请确保焦点在用户手势的方向移动。 因此,如果用户向右轻扫 Siri 远程焦点应向右移动(这可能导致屏幕向左滚动)。 此规则的一个例外是使用直接操作的全屏项(其中向上轻扫将元素向上移动)。
  • 确保重点项是显而易见 的 - 由于用户从远处与 UI 元素交互,因此当前重点项突出至关重要。通常,内置元素会自动 UIKit 处理此问题。 对于自定义控件,请使用项目大小或阴影等功能来显示焦点。
  • 使用视差使重点项目响应 - Siri 远程上的小型圆形手势导致焦点项的温和实时移动。 此视差效果内置于分层图像UIKit,使用户能够与焦点项建立连接。
  • 创建适当大小的 可聚焦项 - 具有足够间距的大型项更易于选择和导航,而不是较小的项目。
  • 将 UI 元素设计为“聚焦”或“未聚焦 ”-通常,Apple TV 通过增加其大小来表示重点项。 确保应用的 UI 元素在任何演示文稿大小上看起来都很棒,如果需要,请为较大的元素提供资产。
  • 代表焦点更改流畅 - 使用动画在焦点未聚焦状态之间平滑淡化,以保持转换不和谐。
  • 不要显示光标 - 用户希望使用焦点导航应用的 UI,而不是通过在屏幕上移动光标来导航你的 UI。 用户界面应始终使用焦点模型来呈现一致的用户体验。

使用焦点

有时你可能想要创建自定义控件,该控件可以成为可聚焦项。 如果是,则 CanBecomeFocused 重写属性并返回 true,否则返回 false。 例如:

public class myView : UIView
{
    public override bool CanBecomeFocused {
        get {return true;}
    }
}

随时可以使用 Focused 控件的属性 UIKit 来查看它是否为当前项。 如果 true UI 项当前具有焦点,则不具有焦点。 例如:

// Is my view in focus?
if (myView.Focused) {
    // Do something
    ...
}

虽然不能通过代码直接将焦点移动到另一个 UI 元素,但可以通过将屏幕属性设置为 true<a0/> 来指定哪个 UI 元素首先获得焦点。 例如:

// Make the play button the starting focus item
playButton.PreferredFocusedView = true;

使用焦点汇报

当用户使焦点从一个 UI 元素转移到另一个 UI 元素(例如,响应 Siri 远程上的手势) 时,焦点更新事件 将发送到失去焦点的项目和获得焦点的项目。

对于继承自 UIViewUIViewController继承的自定义元素,可以重写多个方法来处理焦点更新事件:

  • DidUpdateFocus - 每当视图获得或失去焦点时,都会调用此方法。
  • ShouldUpdateFocus - 使用此方法定义允许焦点移动的位置。

若要请求焦点引擎将焦点移回到 PreferredFocusedView UI 元素,请调用 SetNeedsUpdateFocus 视图控制器的方法。

重要

SetNeedsUpdateFocus仅当正在对其调用视图控制器的视图控制器包含当前具有焦点的视图时,调用才有效。

使用焦点指南

内置于 tvOS 中的焦点引擎非常适合处理位于水平网格和垂直网格上的项之间的移动。 通常,只需将 UI 元素添加到界面设计中,焦点引擎会自动处理这些元素之间的移动,而无需开发人员干预。

但是,有时,由于 UI 设计的必要条件,UI 元素不位于水平网格和垂直网格上,并且可能无法访问,因为它们彼此对角。 发生这种情况是因为焦点引擎旨在仅处理 UI 项之间的简单向上、向下、向左和向右移动。

以以下 UI 布局为例:

Working with Focus Guides example

由于“更多信息”按钮不会落在水平网格和垂直网格上,因此用户无法访问它。 但是,可以使用焦点指南轻松更正此问题,以便向焦点引擎提供移动提示。

焦点指南 (UIFocusGuide) 将视图的非可见区域公开为焦点引擎,从而允许将焦点重定向到另一个视图。

因此,若要解决上述示例,可以将以下代码添加到视图控制器,以在“详细信息”和“购买”按钮之间创建焦点指南:

public UIFocusGuide FocusGuide = new UIFocusGuide ();
...

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // Add Focus Guide to layout
    View.AddLayoutGuide (FocusGuide);

    // Define Focus Guide that will allow the user to move
    // between the More Info and Buy buttons.
    FocusGuide.LeftAnchor.ConstraintEqualTo (BuyButton.LeftAnchor).Active = true;
    FocusGuide.TopAnchor.ConstraintEqualTo (MoreInfoButton.TopAnchor).Active = true;
    FocusGuide.WidthAnchor.ConstraintEqualTo (BuyButton.WidthAnchor).Active = true;
    FocusGuide.HeightAnchor.ConstraintEqualTo (MoreInfoButton.HeightAnchor).Active = true;
}

首先, UIFocusGuide 使用 AddLayoutGuide 该方法创建并添加到视图的布局指南集合中。

接下来,焦点参考线的顶部、左侧、宽度和高度定位点相对于 “详细信息 ”和 “购买 ”按钮进行调整,使其放置在它们之间。 请参阅:

Example Focus Guide

此外,请务必注意,新约束正在激活,因为它们是通过将其 Active 属性设置为 true

FocusGuide.LeftAnchor.ConstraintEqualTo (...).Active = true;

建立并添加到视图的新焦点指南后,可以重写视图控制器DidUpdateFocus的方法,并添加以下代码以在“详细信息”和“购买”按钮之间移动:

public override void DidUpdateFocus (UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
    base.DidUpdateFocus (context, coordinator);

    // Get next focusable item from context
    var nextFocusableItem = context.NextFocusedView;

    // Anything to process?
    if (nextFocusableItem == null) return;

    // Decide the next focusable item based on the current
    // item with focus
    if (nextFocusableItem == MoreInfoButton) {
        // Move from the More Info to Buy button
        FocusGuide.PreferredFocusedView = BuyButton;
    } else if (nextFocusableItem == BuyButton) {
        // Move from the Buy to the More Info button
        FocusGuide.PreferredFocusedView = MoreInfoButton;
    } else {
        // No valid move
        FocusGuide.PreferredFocusedView = null;
    }
}

首先,此代码从传入的 () 获取NextFocusedViewUIFocusUpdateContextcontext 如果此视图是 null,则不需要处理并且方法已退出。

接下来,将评估该 nextFocusableItem 操作。 如果它与“更多信息”或“购买”按钮匹配,则焦点将使用焦点指南的属性发送到相反的PreferredFocusedView按钮。 例如:

// Move from the More Info to Buy button
FocusGuide.PreferredFocusedView = BuyButton;

如果两个按钮都不是焦点移位的源,则会 PreferredFocusedView 清除该属性:

// No valid move
FocusGuide.PreferredFocusedView = null;

在集合中使用焦点

在确定单个项是否可以在某个或某个UITableView项中UICollectionView可聚焦时,将分别替代UICollectionViewDelegate方法UITableViewDelegate。 例如:

public class CardHandDelegate : UICollectionViewDelegateFlowLayout
{
    ...
    public override bool CanFocusItem (UICollectionView collectionView, NSIndexPath indexPath)
    {
        if (indexPath == null) {
            return false;
        } else {
            var controller = collectionView as CardHandViewController;
            return !controller.Hand [indexPath.Row].IsFaceDown;
        }
    }
}

此方法 CanFocusItem 返回 true 当前项是否可以处于焦点状态,否则返回 false

如果要UICollectionViewUITableView在失去焦点并重新获得焦点时将焦点记住并还原到最后一个项目,请将RemembersLastFocusedIndexPath该属性设置为 true

焦点和视差

如上所述,当用户界面元素是导航事件期间的当前项时,该元素被视为 焦点 。 通常,当项目进入焦点时,它的大小会略有增加,并且使用阴影以视觉方式提升。

如果用户在 Siri 远程上做出缓慢的圆形手势,重点项目将实时响应此移动。 随着摇摆的发生,一个照亮的希恩应用于其图像,使表面似乎闪耀。 在给定数量的非活动状态后,任何失焦的内容都会变暗,焦点项将增大。

这些效果协同工作,在电视屏幕上的内容与从沙发上与苹果电视交互的用户之间提供心理连接。

在 Apple TV 上,此视差效果在整个系统中使用,以传达 3D 深度和动态感到焦点项。 tvOS 使用一系列透明 分层图像 ,它动态移动和缩放以创建此效果。

tvOS 应用的图标需要分层图像,并且支持动态 Top Shelf 内容。 虽然不需要,但 Apple 强烈建议在应用 UI 中的任何其他可聚焦项中实现分层图像。

启用视差

控件 UIImageView (或继承自 UIImageView的任何控件)自动支持视差效果。 默认情况下,此支持处于禁用状态,若要启用它,请使用以下代码:

myImageView.AdjustsImageWhenAncestorFocused = true;

将此属性设置为 true该属性后,图像视图将在用户选中并处于焦点时自动获取视差效果。

总结

本文介绍了 Focus 的概念及其用于在 Xamarin.tvOS 应用的用户界面中处理导航的方式。 它检查内置 tvOS 导航控件如何使用焦点、突出显示和选择来提供导航。 接下来,它探讨了焦点如何与视差和分层图像一起使用,以便为最终用户提供当前导航状态的视觉线索。 最后,它检查了如何使用焦点、焦点汇报、集合中的焦点和启用视差。