Xamarin 中 tvOS 的 Siri Remote 和蓝牙控制器

Xamarin.tvOS 应用程序的用户不会像 iOS 用户那样直接在设备屏幕上点击图像与界面进行交互,而是通过 Siri Remote 在房间的另一端进行间接交互。

如果应用是一个游戏,你也可选择在应用中内置对第三方 Made For iOS (MFI) 蓝牙游戏控制器的支持。

蓝牙远程和游戏控制器

本文介绍 Siri RemoteTouch Surface 手势Siri Remote 按钮,并演示如何通过手势和情节提要手势和代码以及低级别事件处理来处理它们。 最后讨论了在 Xamarin.tvOS 应用中使用游戏控制器

Siri Remote

用户与 Apple TV 和 Xamarin.tvOS 应用交互的主要方式是通过包含的 Siri Remote。 Apple 设计这款遥控器是为了拉近坐在沙发上的用户和房间另一端显示在电视屏幕上的 Apple TV 用户界面之间的距离。

作为 tvOS 应用开发者,你的挑战在于创建一个快速、易用且视觉上吸引人的用户界面,充分利用 Siri Remote 的触控表面、加速度计、陀螺仪和按钮。

Siri Remote

Siri Remote 在 tvOS 应用中具有以下功能和预期用途:

功能 常规应用使用情况 游戏应用使用情况
Touch Surface
轻扫以导航,按下以选择,按住则显示上下文菜单。
点击/轻扫
可聚焦项之间的 UI 导航。

单击
激活所选的(焦点)项。
点击/轻扫
根据游戏设计,可以通过点击边缘将其用作 D-Pad。

单击
执行主按钮函数。
菜单
按下以返回到上一屏幕或菜单。
返回到上一个屏幕,然后从主应用屏幕退出 Apple TV 主屏幕。 暂停和恢复游戏,返回到上一个屏幕,然后从主应用屏幕退出 Apple TV 主屏幕。
Siri/搜索
在使用 Siri 的国家/地区,按下并按住会显示语音控件,在所有其他国家/地区则显示搜索屏幕。
不适用 不适用
播放/暂停
播放和暂停媒体或在应用中提供辅助功能。
启动媒体播放并暂停/恢复播放。 执行辅助按钮函数或跳过简介视频(如果存在)。
主页
按下可返回到主屏幕,双击可显示正在运行的应用,按住则使设备进入睡眠状态。
不适用 不适用
体积
控制附加的音频/视频设备音量。
不适用 不适用

触摸表面手势

Siri Remote 的 Touch Surface 能够检测可在 Xamarin.tvOS 应用中响应的各种单指手势:

轻扫 单击 点击
移动所选内容 激活所选项 方向按钮
在屏幕上的 UI 元素之间(向上、向下、向右)移动所选内容(焦点)。 轻扫可用于使用惯性快速浏览大型内容列表。 激活所选的(焦点)项或在游戏中充当主键的作用。 单击并按住可以激活上下文菜单或辅助函数。 轻触 Touch Surface 边缘的作用类似于 D-Pad 上的方向按钮,根据点击的区域向上、向下、向左或向右移动焦点。 根据应用,可用于显示隐藏的控件。

Apple 提供了以下有关使用 Touch Surface 手势的建议:

  • 区分单击和点击 - 单击是用户有意的操作,适合选择、激活和游戏的主要按钮。 点击更微妙,应谨慎使用,因为用户经常手拿 Siri Remote,可能意外激活“点击”事件。
  • 不要重新定义标准手势 - 用户期望特定手势将执行特定操作,不应在应用中重新定义这些手势的含义或功能。 一个例外是活动游戏期间的游戏应用。
  • 谨慎定义新手势 - 同样,用户期望特定手势将执行特定操作。 应避免定义自定义手势来执行标准操作。 同样,游戏是最常见的例外,自定义手势可以添加有趣的沉浸式游戏体验。
  • 适当时响应 D-Pad 点击 - 轻击 Touch Surface 的边角将像游戏控制器上的 D-Pad 在游戏控制器上移动焦点,或者向上、向下、向左或向右移动。 如果适用,应在应用或游戏中响应这些手势。

Siri Remote 按钮

除了 Touch Surface 上的手势外,应用还可以响应用户单击 Touch Surface 或按“播放/暂停”按钮。 如果使用游戏控制器框架访问 Siri Remote,还可以检测按下的“菜单”按钮。

此外,还可以使用具有标准 UIKit 元素的手势识别器来检测菜单按钮按下操作。 如果你拦截了按下菜单按钮的操作,你将负责关闭当前视图和视图控制器并返回到前一个。

重要

务必向遥控器上的“播放/暂停”按钮分配功能。 如果按钮不能正常工作,会让你的应用程序在最终用户看来似乎出现了故障。 如果没有适用于此按钮的功能,请分配与主按钮相同的功能(Touch Surface 单击)。

手势和情节提要

在 Xamarin.tvOS 应用中使用 Siri Remote 的最简单方法是将手势识别器添加到 Interface Designer 中的视图。

若要添加手势识别器,请执行以下操作:

  1. 解决方案资源管理器中,双击 Main.storyboard 文件打开它以编辑 Interface Designer。

  2. 拖动点击手势识别器并将其拖放到视图上:

    点击手势识别器

  3. 属性检查器按钮部分中检查选择

    检查 选择

  4. 选择意味着手势将响应用户单击 Siri Remote 上的 Touch Surface。 也有响应菜单播放/暂停向上向下向左向右按钮的选项。

  5. 接下来,从点击手势识别器连接操作,并将其命名为 TouchSurfaceClicked

    点击手势识别器中的操作

  6. 保存更改并返回到 Visual Studio for Mac。

编辑视图控制器(示例 FirstViewController.cs)文件,并添加以下代码来处理触发的手势:

using System;
using UIKit;

namespace tvRemote
{
    public partial class FirstViewController : UIViewController
    {
        ...

        #region Custom Actions
        partial void TouchSurfaceClicked (Foundation.NSObject sender) {
            // Handle click here
            ...
        }
        #endregion
    }
}

有关使用情节提要的详细信息,请参阅你好,tvOS 快速入门指南。 具体而言,创建用户界面使用出口和操作编写代码部分。

手势和代码

或者,直接以 C# 代码中创建手势,并将其添加到用户界面中的视图。 例如,若要添加一系列轻扫手势识别器,请编辑视图控制器并添加以下代码:

using System;
using UIKit;

namespace tvRemote
{
    public partial class SecondViewController : UIViewController
    {
        #region Constructors
        public SecondViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Wire-up gestures
            var upGesture = new UISwipeGestureRecognizer (() => {
                RemoteView.ArrowPressed = "Up";
                ButtonLabel.Text = "Swiped Up";
            }) {
                Direction = UISwipeGestureRecognizerDirection.Up
            };
            this.View.AddGestureRecognizer (upGesture);

            var downGesture = new UISwipeGestureRecognizer (() => {
                RemoteView.ArrowPressed = "Down";
                ButtonLabel.Text = "Swiped Down";
            }) {
                Direction = UISwipeGestureRecognizerDirection.Down
            };
            this.View.AddGestureRecognizer (downGesture);

            var leftGesture = new UISwipeGestureRecognizer (() => {
                RemoteView.ArrowPressed = "Left";
                ButtonLabel.Text = "Swiped Left";
            }) {
                Direction = UISwipeGestureRecognizerDirection.Left
            };
            this.View.AddGestureRecognizer (leftGesture);

            var rightGesture = new UISwipeGestureRecognizer (() => {
                RemoteView.ArrowPressed = "Right";
                ButtonLabel.Text = "Swiped Right";
            }) {
                Direction = UISwipeGestureRecognizerDirection.Right
            };
            this.View.AddGestureRecognizer (rightGesture);
        }
        #endregion
    }
}

低级别事件处理

如果要根据 Xamarin.tvOS 应用中的 UIKit 创建自定义类型(例如 UIView),则还可以通过 UIPress 事件提供按钮按下的低级别处理。

UIPress 事件对于 tvOS 的重要性相当于 UITouch 事件对于 iOS 的重要性,只不过 UIPress 会返回关于 Siri Remote 或其他已连接的蓝牙设备(如游戏控制器)上按钮按下的信息。 UIPress 事件描述按下的按钮及其状态(已开始、已取消、已更改或已结束)。

对于蓝牙游戏控制器等设备上的模拟按钮,UIPress 还返回对该按钮施加的力量。 UIPress 事件的 Type 属性定义哪些物理按钮已更改状态,而其余属性描述发生的更改。

以下代码演示了处理 UIView 的低级别 UIPress事件的示例:

using System;
using Foundation;
using UIKit;

namespace tvRemote
{
    public partial class EventView : UIView
    {
        #region Computed Properties
        public override bool CanBecomeFocused {
            get {
                return true;
            }
        }
        #endregion

        #region
        public EventView (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void PressesBegan (NSSet<UIPress> presses, UIPressesEvent evt)
        {
            base.PressesBegan (presses, evt);

            foreach (UIPress press in presses) {
                // Was the Touch Surface clicked?
                if (press.Type == UIPressType.Select) {
                    BackgroundColor = UIColor.Red;
                }
            }
        }

        public override void PressesCancelled (NSSet<UIPress> presses, UIPressesEvent evt)
        {
            base.PressesCancelled (presses, evt);

            foreach (UIPress press in presses) {
                // Was the Touch Surface clicked?
                if (press.Type == UIPressType.Select) {
                    BackgroundColor = UIColor.Clear;
                }
            }
        }

        public override void PressesChanged (NSSet<UIPress> presses, UIPressesEvent evt)
        {
            base.PressesChanged (presses, evt);
        }

        public override void PressesEnded (NSSet<UIPress> presses, UIPressesEvent evt)
        {
            base.PressesEnded (presses, evt);

            foreach (UIPress press in presses) {
                // Was the Touch Surface clicked?
                if (press.Type == UIPressType.Select) {
                    BackgroundColor = UIColor.Clear;
                }
            }
        }
        #endregion
    }
}

UITouch 事件一样,如果需要实现任何 UIPress 事件的替代,则应该实现所有四个替代。

蓝牙游戏控制器

除了与 Apple TV 一起提供的标准 Siri Remote 之外,还可以将第三方制造的适用于 iOS (MFI) 的蓝牙游戏控制器与 Apple TV 配对,用来控制你的 Xamarin.tvOS 应用。

蓝牙游戏控制器

游戏控制器可用于增强游戏玩法,并提供游戏中的沉浸感。 它们还可用于控制标准 Apple TV 接口,因此用户不必在遥控模式和控制器之间切换。

重要

蓝牙游戏控制器是最终用户可以购买的可选商品,你的应用无法强制用户购买一个。 如果你的应用支持游戏控制器,它还必须支持 Siri 遥控,以便游戏可由所有 Apple TV 用户使用。

游戏控制器在 tvOS 应用中具有以下功能和预期用途:

功能 常规应用使用情况 游戏应用使用情况
D-Pad 浏览 UI 元素(更改焦点)。 取决于游戏。
A 激活所选的(焦点)项。 执行主要按钮功能并确认对话操作。
B 返回到上一个屏幕或退出主屏幕(如果位于应用的主屏幕上)。 执行次要按钮功能或返回到上一个屏幕。
X 启动媒体播放或暂停/恢复播放。 取决于游戏。
Y 不适用 取决于游戏。
菜单 返回到上一个屏幕或退出主屏幕(如果位于应用的主屏幕上)。 暂停/恢复游戏,返回到上一个屏幕,或者退出主屏幕(如果位于应用的主屏幕上)。
左肩按钮 向左导航。 取决于游戏。
左触发器 向左导航。 取决于游戏。
右肩按钮 向右导航。 取决于游戏。
右触发器 向右导航 取决于游戏。
左操纵杆 浏览 UI 元素(更改焦点)。 取决于游戏。
右操纵杆 不适用 取决于游戏。

Apple 提供了以下使用游戏控制器的建议:

  • 确认游戏控制器连接 - 最终用户可以随时启动和停止 tvOS 应用。 应始终在应用程序启动或唤醒时检查游戏控制器的存在情况,并根据需要采取行动。
  • 确保你的应用同时支持 Siri Remote 和游戏控制器 - 不要求用户在 Siri Remote 和游戏控制器之间切换才能使用你的应用。 使用这两种类型的控制器经常测试应用,确保一切易于导航并按预期工作。
  • 提供返回方式 - 按菜单按钮应始终返回到上一屏幕。 如果用户位于主应用屏幕,“菜单”按钮应将其返回到 Apple TV 主屏幕。 在玩游戏期间,菜单按钮应显示一个警报,让用户能够暂停/恢复游戏或返回到主菜单。

使用游戏控制器

如上所述,除了与 Apple TV 一起提供的标准 Siri Remote 之外,用户还可以选择连接第三方制造的适用于 iOS (MFI) 的蓝牙游戏控制器,并用来控制你的 Xamarin.tvOS 应用。

如果你的应用需要低级别控制器输入,则可以使用 Apple 的 Game Controller Framework,该框架对 tvOS 进行了以下修改:

  • 已添加了面向 Siri Remote 的 Micro Game Controller 配置文件 (GCMicroGamepad)。
  • 新的 GCEventViewController 类可用于通过应用路由游戏控制器事件。 有关详细信息,请参阅下面的确定游戏控制器输入部分。

游戏控制器支持要求

如果 Xamarin.tvOS 应用支持游戏控制器,Apple 必须满足以下几个特定要求:

  • 必须支持 Siri Remote - 必须始终支持 Siri Remote。 你的游戏不能要求第三方游戏控制器可玩。
  • 必须支持扩展控件布局 - 所有 tvOS 游戏控制器都是非固定式、扩展式控制器。
  • 游戏必须使用独立控制器 - 如果你的应用支持扩展游戏控制器,那么它必须只能使用那个游戏控制器来操作。
  • 必须支持“播放/暂停”按钮 - 在玩游戏期间,如果用户按下“播放/暂停”按钮,则应显示一个警报,让用户能够暂停/恢复游戏或返回到主菜单。

启用游戏控制器支持

若要在 Xamarin.tvOS 应用中启用游戏控制器支持,请双击解决方案资源管理器中的 Info.plist 文件,打开它进行编辑:

Info.plist 编辑器

“游戏控制器” 部分下,勾选“启用游戏控制器”,然后检查应用支持的所有游戏控制器类型。

将 Siri Remote 用作游戏控制器

Apple TV 附带的 Siri Remote 服务器可用作有限的游戏控制器。 与其他游戏控制器一样,它作为 GCController 对象显示在游戏控制器框架中,同时支持 GCMotionGCMicroGamepad 配置文件。

Siri Remote 在用作游戏控制器时具有以下特征:

  • Touch Surface 可用作提供模拟输入数据的 D-Pad。
  • 遥控器可以垂直或水平使用,你的应用决定配置文件对象是否应自动翻转输入数据。
  • 单击 Touch Surface 类似于在游戏控制器上按下按钮 A
  • “播放/暂停”按钮的作用类似于游戏控制器上的按钮 X
  • 菜单按钮应显示一个警报,让用户能够暂停/恢复游戏或返回到主菜单。

确定游戏控制器输入

与 iOS 不同,在 iOS 中,游戏控制器事件可以与触摸事件并行接收,而 tvOS 会处理所有低级别事件以传递高级别的 UIKit 事件。 因此,如果需要访问低级别游戏控制器事件,则需要关闭 UIKit 的默认行为。

在 tvOS 上,如果要直接处理游戏控制器输入,则需要使用 GCEventViewController(或子类)来显示游戏的用户界面。 当 GCEventViewController第一响应方时,游戏控制器的输入将被捕获并通过 Game Controller Framework 传递给你的应用。

可以使用 GCEventViewController 类的 UserInteractionEnabled 属性来切换事件的处理方式。

有关实现游戏控制器支持的信息,请参阅 Apple 的 tvOS 应用编程指南中的使用游戏控制器部分和游戏控制器编程指南

总结

本文介绍了 Apple TV、Touch Surface 手势和 Siri Remote 按钮随附的新 Siri Remote。 接下来,它介绍了如何使用手势和情节提要、手势和代码以及低级别事件。 最后讨论了如何使用游戏控制器。