TV 设备为应用提供了一组有限的导航控件。为 TV 应用创建有效的导航方案取决于了解这些有限的控件以及用户在操作应用时的限制。在构建 Android TV 应用时,请特别注意用户使用遥控器按钮(而非触摸屏)时的导航方式。
原则
我们的目标是让用户感觉自然、熟悉,同时又不会占据界面,也不会转移用户对内容的注意力。以下原则有助于设定基准,以便在 TV 应用中提供一致且直观的用户体验。
让用户能够快速轻松地访问内容。用户希望通过最少的点击次数快速访问内容。以所需的屏幕最少的方式整理信息。
遵循最佳实践和建议,让用户能够预测导航体验。请勿在不必要的情况下重新设计导航模式,因为这会导致混淆和不可预测。
让导航足够简单,可以无缝支持广泛采用的用户行为。不要添加不必要的导航层,以免过于复杂。
控制器
控制器有多种样式,从极简的遥控器到复杂的游戏控制器。所有控制器都包含一个方向键、选择按钮、主屏幕按钮和返回按钮。其他按钮因型号而异。
![示例遥控器](https://developer.android.google.cn/static/training/tv/images/tv-nav-controller.png?authuser=5&hl=da)
方向键
电视上的主要导航方法是通过方向键,其中包括向上、向下、向左和向右方向硬件按钮。方向键会按照所按下按钮的方向将焦点从一个对象转移到最近的对象。
“选择”按钮
选择屏幕上获得焦点的项。
主屏幕按钮
将用户转到系统主屏幕。
返回按钮
为用户提供了返回上一视图的方式。
麦克风按钮
调用 Google 助理或语音输入。
方向键导航
在 TV 设备上,用户可使用方向键或箭头键进行导航。这种类型的控件将移动限定在上、下、左、右四个方向。如需构建一款针对 TV 优化的出色应用,您必须提供一种导航架构,让用户能够快速了解如何使用这些有限的控件在应用中导航。
Android 框架会自动处理布局元素之间的方向导航,因此您通常无需对应用执行任何额外的操作。不过,您应该对通过方向键控制器进行导航进行全面测试,以发现任何导航问题。
请遵循以下准则来测试应用的导航系统能否在 TV 设备上与方向键顺畅配合:
- 确保使用方向键控制器的用户能够导航到屏幕上的所有可见控件。
- 对于获得焦点的滚动列表,请确保使用方向键的向上和向下按钮可滚动列表,并且选择按钮会选择列表中的某项。验证用户是否可以选择列表中的元素,并且选择元素时列表是否仍会滚动。
- 确保控件间的切换简单明了并且可以预测。
修改方向导航
Android 框架会根据布局中可聚焦元素的相对位置自动应用方向导航架构。使用方向键控制器在应用中测试生成的导航架构。测试后,如果您决定希望用户以特定方式在布局中移动,则可以为控件设置显式方向导航。
以下代码示例展示了如何定义下一个获得 TextView
布局对象焦点的控件:
<TextView android:id="@+id/Category1" android:nextFocusDown="@+id/Category2" />
下表列出了 Android 界面 widget 的所有可用导航属性:
属性 | 功能 |
---|---|
nextFocusDown |
定义当用户向下导航时下一个获得焦点的视图。 |
nextFocusLeft |
定义当用户向左导航时下一个获得焦点的视图。 |
nextFocusRight |
定义当用户向右导航时下一个获得焦点的视图。 |
nextFocusUp |
定义当用户向上导航时下一个获得焦点的视图。 |
如需使用其中一个显式导航属性,请将值设置为布局中另一个 widget 的 android:id
。请务必将导航顺序设置为循环,以便最后一个控件能够将焦点移回到第一个控件。
提供明确的焦点和选择
应用的导航架构能否在 TV 设备上取得成功,取决于用户确定获得焦点的界面元素的难易程度。如果您没有明确指示获得焦点的项(进而导致用户可以对哪个项执行操作),用户可能很快就会因失望而退出您的应用。出于同样的原因,请务必在应用启动后或任何处于空闲状态时,始终让一个项目获得焦点,使用户能够立即对其执行操作。
在应用布局和实现中,请使用颜色、尺寸、动画或这些属性的组合来帮助用户轻松确定他们接下来可以执行的操作。请使用统一的方案在整个应用中指示焦点。
Android 提供了可绘制对象状态列表资源来实现针对获得焦点的控件和选定控件的突出显示。以下代码示例演示了如何为按钮启用视觉行为,以表明用户已导航到该控件并随后选择了它:
<!-- res/drawable/button.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/button_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="@drawable/button_focused" /> <!-- focused -->
<item android:state_hovered="true"
android:drawable="@drawable/button_focused" /> <!-- hovered -->
<item android:drawable="@drawable/button_normal" /> <!-- default -->
</selector>
以下布局 XML 示例代码将上一状态列表可绘制对象应用于 Button
:
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/button" />
请务必在可聚焦控件和可选择控件内提供足够的内边距,使其周围的突出显示元素清晰可见。
返回按钮导航
为了在平台上的应用之间保持一致,请确保返回按钮的行为遵循以下准则。
使用可预测的返回按钮行为
为了打造简单且可预测的导航体验,当用户按遥控器的返回按钮时,请将其转到上一个目的地。
![描述使用顶部导航栏时导航流程的图片](https://developer.android.google.cn/static/training/tv/images/tv-nav-top.png?authuser=5&hl=da)
![描述使用侧边导航栏时的导航流程的图片](https://developer.android.google.cn/static/training/tv/images/tv-nav-left.png?authuser=5&hl=da)
如果用户从菜单项导航到页面中间的卡片,然后按返回按钮,结果取决于应用是使用顶部导航栏还是左侧导航栏:
- 应用使用顶部导航栏:通过快速滚动并激活菜单上的焦点,让用户返回到页面顶部。
- 应用使用左侧导航栏:激活左侧菜单,并聚焦于当前处于活动状态的菜单项。
确保返回按钮没有被确认屏幕或无限循环部分控制。
![显示询问用户是否要退出的对话框的屏幕截图](https://developer.android.google.cn/static/training/tv/images/tv-nav-back-button-dialog.png?authuser=5&hl=da)
错误做法。
避免退出门控。让用户不经过确认就退出应用。
![显示导航循环的屏幕截图](https://developer.android.google.cn/static/training/tv/images/tv-nav-loop.gif?authuser=5&hl=da)
错误做法。
切勿陷入关闭和打开菜单的无限循环。理想情况下,按返回按钮会退出应用。除非是特殊情况(例如儿童个人资料),否则不要在菜单上显示退出按钮。
不显示向上或返回按钮
与手持设备不同,遥控器上的返回按钮用于在电视上向后导航。您无需在屏幕上显示虚拟返回按钮:
![屏幕上显示软返回按钮的屏幕截图](https://developer.android.google.cn/static/training/tv/images/tv-nav-no-soft-back.png?authuser=5&hl=da)
错误做法。
如有必要,显示取消按钮
如果唯一可见的操作是确认、破坏性或购买操作,最好使用能够返回先前目的地的 Cancel 按钮:
![屏幕上显示软取消按钮的屏幕截图](https://developer.android.google.cn/static/training/tv/images/tv-nav-cancel.png?authuser=5&hl=da)
正确做法。
实现返回导航
Android 框架通常可以很好地处理返回导航,就像处理方向键一样。如果您使用 Navigation 组件,则可以支持各种导航图。有时,您可能需要实现一些自定义行为,例如让返回按钮将焦点重置到长列表的开头。
借助 ComponentActivity
(FragmentActivity
和 AppCompatActivity
的基类),您可以使用其 OnBackPressedDispatcher
(可通过调用 getOnBackPressedDispatcher()
检索)来控制返回按钮的行为。
如需了解详情,请参阅提供自定义返回导航。
电视上的播放控件
视频播放是电视上最重要的功能之一。Android TV 上各应用中的视频播放器必须具有相同的行为。请参阅针对 TV 的播放控件准则。
“直播”标签页导航
除了符合 TV 应用质量要求之外,在“直播”标签页中集成了直播电视 Feed 的应用还必须满足流畅播放和直接返回要求,如以下部分所述。
流畅播放
流畅播放适用于 Google TV 和 Android TV 中任何直播/线性频道深层链接后的应用内行为。
用户在 Google TV 和 Android TV 中点击直播/线性频道深层链接后,必须直接跳转到频道播放,而不会屏蔽或延迟目标应用的屏幕。不允许登录流程、注册流程、品牌推广视频以及其他延迟。
不过,如果深层链接在冷启动过程中启动目标应用加载,则允许播放在播放之前的这一启动延迟。在这种情况下,也允许使用应用启动过程中的品牌塑造视频或动画。这种冷启动体验不太可能在每次会话中发生多次。
此外,如果调谐到深层链接频道需要几秒钟,则允许显示频道和/或服务品牌信息。不过,其时长应仅与加载频道所需的时长一样长(与应用中的平均频道加载时间类似)。
如果用户未登录或未订阅,您可以阻止播放付费频道以完成登录或注册流程。
直接返回
当用户从“直播”标签页上的深层链接启动应用,然后按返回按钮时,无论经过多长时间,用户都必须通过一次返回按钮返回“直播”标签页。Google TV 和 Android TV 上的所有“直播”标签页深层链接都需要这种直接返回行为。
“直播”标签页深层链接通过附加的深层链接参数区分开来:?exit_on_back=[true|false]
。应用必须解析此参数,以确定应用是否从“直播”标签页启动。如果 exit_on_back
为 true
,应用必须实现直接返回行为。
请注意,如果用户在深层链接之后按下第一个按钮时按返回按钮以外的任何按钮,则直接返回要求不适用,而只需要标准的返回按钮行为。
例如,假设用户在点击深层链接后,按下方向键的选择按钮,从而调出控件叠加层。用户等待叠加层消失,然后按返回按钮。由于在点击深层链接后按下的第一个按钮是方向键选择按钮,因此直接返回要求不适用。而是应用常规的应用返回堆栈逻辑。
重复按返回按钮必须将用户引导至应用根目录,然后返回到 Google TV 或 Android TV,而不会出现任何无限循环。如需了解详情,请参阅可预测的返回按钮行为部分。
导航架构
固定的起始目的地
用户从启动器启动应用时看到的第一个屏幕也是用户在按下返回按钮后返回启动器时看到的最后一个屏幕。
深层链接可模拟手动导航
无论是深层链接还是手动导航到特定目的地,用户都可以使用返回按钮在各目的地之间导航回起始目的地。
![显示指向应用中详情页面的深层链接的屏幕截图。按“返回”可返回到该应用的主屏幕,再按“返回”可返回原始屏幕。](https://developer.android.google.cn/static/training/tv/images/tv-nav-deeplink.png?authuser=5&hl=da)
从其他应用深层链接到某个应用可模拟手动导航。例如,如果用户从 Google TV 直接转到 Moviestar 应用的详情页面,然后按返回按钮,会转到 Moviestar 应用的首页。
所有可聚焦元素的清晰路径
为用户提供清晰的导航界面。如果没有直接前往某个控件的路径,请考虑重新放置该控件。
![可聚焦导航示例](https://developer.android.google.cn/static/training/tv/images/tv-nav-focusable-2.png?authuser=5&hl=da)
正确做法
将控件(如此处显示的搜索操作)放置在不与其他可点击元素重叠的位置。
![可聚焦导航示例](https://developer.android.google.cn/static/training/tv/images/tv-nav-focusable-1.png?authuser=5&hl=da)
错误做法。
避免让控件显示在很难触及的位置。使用方向键不容易找到此处显示的搜索操作。
轴
设计布局时应能充分利用水平轴和垂直轴。 为每个方向指定特定的函数,以便在大型层次结构中快速导航。
![导航轴示例](https://developer.android.google.cn/static/training/tv/images/tv-nav-axes-1.png?authuser=5&hl=da)
正确做法
您可以沿纵轴遍历类别,而各类别中的项目则可在横轴上浏览。
![导航轴示例](https://developer.android.google.cn/static/training/tv/images/tv-nav-axes-2.png?authuser=5&hl=da)
错误做法。
避免使用复杂和嵌套的布局层次结构。