适用于 Android TV 的无障碍功能最佳实践

本指南介绍了 Android TV 上无障碍功能的最佳实践,并针对原生应用和非原生应用提供了建议。

为什么无障碍功能对我的 TV 应用很重要?

在电视观看人群中,视觉障碍并不罕见。 据估计,全球有 22 亿人 有视力障碍, 世界卫生组织 (WHO) 发布。根据 2018 年全国健康访谈调查,在美国,有 3200 万年满 18 周岁的美国人出现了严重的视力损失。根据欧洲盲人联盟 (EBU) 的估算,欧洲有 3,000 万盲人和弱视人士。

最重要的是,视力受损的用户与正常视力的用户一样,都能畅享媒体内容。受 Comcast 委托,2017 年开展的一项问卷调查 96% 的失明或低视力用户经常观看 81% 的用户每天观看电视超过 1 小时。不过,65% 的受访者也表示在查找电视节目时遇到了问题。2020 年在英国开展的一项调查显示,80% 的残障人士表示,他们在使用视频点播在线媒体服务时遇到过无障碍问题。

虽然辅助技术确实可以帮助有视力障碍的用户, 在 TV 应用的内容发现历程中支持无障碍功能非常重要。 例如,要特别注意提供导航指导和 为元素添加适当的标签,并确保 TV 应用能够很好地与无障碍功能搭配使用 TalkBack 等重要功能这些步骤可以显著改善视障用户的体验。

提高无障碍功能的第一步是提高认识。本指南 可帮助您和您的团队发现 TV 应用的无障碍功能问题。

Android 无障碍功能资源

如需详细了解 Android 上的无障碍功能,请参阅我们的无障碍功能开发资源

文字缩放

Android TV 应用应支持不同的像素密度,以遵循用户对文本放大的偏好设置。

请特别注意以下事项:

  • 对界面组件中的尺寸使用 wrap_content
  • 确保布局会根据文本缩放比例调整组件的尺寸。
  • 确保组件在文字较大时仍能适应屏幕。
  • 不要为非灵活组件使用 sp 文字大小单位。
  • 检查 FONT_SCALE 的值,以便在自定义视图中进行调整:

    // Checking font scale with Context
    val scale = resources.configuration.fontScale
    Log.d(TAG, "Text scale is: " + scale)
    

您可以使用以下命令更改文本比例:

adb shell settings put system font_scale 1.2f

在 Android 12 及更高版本中,用户可以通过设备设置更改文本放大比例。

键盘布局

在 Android 13(API 级别 33)及更高版本中,您可以使用 getKeyCodeForKeyLocation() 为预期按键位置查找按键代码。如果用户重新映射了某些按键位置,或者使用的是布局不常规的键盘,则可能需要这样做。

语音描述

在 Android 13(API 级别 33)及更高版本中,新增了系统级无障碍功能偏好设置 允许用户在所有应用中启用语音描述。Android TV 应用可以: 检查用户的偏好设置 isAudioDescriptionRequested()

KotlinJava
private lateinit var accessibilityManager: AccessibilityManager

// In onCreate():
accessibilityManager = getSystemService(AccessibilityManager::class.java)

// Where your media player is initialized
if (am.isAudioDescriptionRequested) {
    // User has requested to enable audio descriptions
}
private AccessibilityManager accessibilityManager;

// In onCreate():
accessibilityManager = getSystemService(AccessibilityManager.class);

// Where your media player is initialized
if(accessibilityManager.isAudioDescriptionRequested()) {
    // User has requested to enable audio descriptions
}

Android TV 应用可以通过向 AccessibilityManager 添加监听器来监控用户偏好设置的更改时间:

KotlinJava
private val listener =
    AccessibilityManager.AudioDescriptionRequestedChangeListener { enabled ->
        // Preference changed; reflect its state in your media player
    }

override fun onStart() {
    super.onStart()

    accessibilityManager.addAudioDescriptionRequestedChangeListener(mainExecutor, listener)
}

override fun onStop() {
    super.onStop()

    accessibilityManager.removeAudioDescriptionRequestedChangeListener(listener)
}
private AccessibilityManager.AudioDescriptionRequestedChangeListener listener = enabled -> {
    // Preference changed; reflect its state in your media player
};

@Override
protected void onStart() {
    super.onStart();

    accessibilityManager.addAudioDescriptionRequestedChangeListener(getMainExecutor(), listener);
}

@Override
protected void onStop() {
    super.onStop();

    accessibilityManager.removeAudioDescriptionRequestedChangeListener(listener);
}