某些使用 Android 设备的用户具有不同于他人的无障碍功能需求。为了帮助具有共同的无障碍功能需求的特定人群,Android 框架为开发者创建无障碍服务提供了相关功能,这种服务可将应用的内容呈现给此类用户,并代表他们在应用中执行操作。

Android 提供了一些系统无障碍服务,其中包括:

  • TalkBack: 帮助视力低下或失明的人。通过合成语音读出内容,并在应用中执行操作以响应用户手势。

  • 开关控制: 帮助有运动障碍的人。突出显示互动元素,并执行操作以响应用户按某个按钮的动作。用户只使用 1 个或 2 个按钮就能控制设备。

  • TalkBack
    https://support.google.com/accessibility/android/answer/6283677

  • 开关控制
    https://support.google.com/accessibility/android/answer/6122836

为了帮助具有无障碍功能需求的用户顺利使用您的应用,应用应遵循本页中介绍的最佳做法,这些做法基于让应用使用起来更没有障碍中所述的关键准则。

以下各种最佳做法可以进一步改进应用的无障碍功能:

  • 标签元素: 用户应该能够理解应用中每个有意义的互动界面元素的内容和用途。

  • 使用或扩展系统微件: 基于框架包含的视图元素构建,而不是创建您自己的自定义视图。框架的视图和微件类已经提供了应用所需的大多数无障碍功能。

  • 使用除颜色之外的提示: 用户应该能够明确区分界面中的各类元素。为此,除了颜色之外,还应使用图案和位置表示这些差异。

  • 让媒体内容使用起来更没有障碍: 尝试向应用的视频或音频内容添加说明,这样使用这些内容的用户就无需完全依靠视觉或听觉提示。

标签元素

请务必针对应用中的每个互动界面元素,为用户提供实用且描述性的标签。每个标签都应说明特定元素的含义和用途。TalkBack 等屏幕阅读器可以向依靠这些服务的用户读出这些标签。

在大多数情况下,您可以在包含给定界面元素的布局资源文件中指定该元素的说明。虽然您通常使用 contentDescription 属性添加标签,如让应用使用起来更没有障碍指南中所述,但还需要牢记一些其他标签添加方法,如下面几部分所述。

可修改的元素

为可修改的元素 (如 EditText 对象) 添加标签时,您可以列举有效输入的示例,除了让相应的示例文字可由屏幕阅读器读出之外,最好还在元素本身中显示这些文字。在这些情况下,您可以使用 android:hint 属性,如以下代码段所示:

<!-- The hint text for en-US locale would be"Apartment, suite, or building". -->
<EditTextandroid:id="@+id/addressLine2"android:hint="@string/aptSuiteBuilding" ... />

在这种情况下,View 对象的 android:labelFor 属性应设为 EditText 元素的 ID。如需了解详情,请参阅下文中介绍如何为相互描述的元素对添加标签的部分。

  • EditText
    https://developer.android.google.cn/reference/android/widget/EditText

相互描述的元素对

给定的 EditText 元素通常会有一个相应的 View 对象,该对象描述了用户应在 EditText 元素中输入的内容。在搭载 Android 4.2 (API 级别 17) 或更高版本的设备上,您可以通过设置 View 对象的 android:labelFor 属性来指明这种关系。

  • View
    https://developer.android.google.cn/reference/android/view/View

下面的代码段显示了为此类元素对添加标签的示例:

<!-- Label text for en-US locale would be "Username:" -->
<TextViewandroid:id="@+id/usernameLabel" ...android:text="@string/username"android:labelFor="@+id/usernameEntry" /><EditTextandroid:id="@+id/usernameEntry" ... /><!-- Label text for en-US locale would be "Password:" -->
<TextViewandroid:id="@+id/passwordLabel" ...android:text="@string/passwordandroid:labelFor="@+id/passwordEntry" /><EditTextandroid:id="@+id/passwordEntry"android:inputType="textPassword" ... />

集合中的元素

向集合中的元素添加标签时,每个标签都应该是唯一的。这样,系统的无障碍服务在读出标签时就可以特指屏幕上的 1 个元素。这种对应关系可让用户知道他们何时循环浏览界面,或何时将焦点移到了已经发现的元素。

需要特别注意的是,您应在重用布局内的元素 (如 RecyclerView 对象) 中添加更多文字或上下文信息,以便能够唯一标识每个子元素。

  • RecyclerView
    https://developer.android.google.cn/reference/androidx/recyclerview/widget/RecyclerView

为此,请在适配器实现中设置内容说明,如以下代码段所示

data class MovieRating(val title: String, val starRating: Integer)class MyMovieRatingsAdapter(private val myData: Array<MovieRating>):RecyclerView.Adapter<MyMovieRatingsAdapter.MyRatingViewHolder>() {class MyRatingViewHolder(val ratingView: ImageView) :RecyclerView.ViewHolder(ratingView)override fun onBindViewHolder(holder: MyRatingViewHolder, position: Int) {val ratingData = myData[position]holder.ratingView.contentDescription = "Movie ${position}: " +"${ratingData.title}, ${ratingData.starRating} stars"}
}

相关内容组

如果应用显示的多个界面元素构成一个自然组 (如歌曲的详细信息或消息的属性),应将这些元素整理到一个容器中,该容器通常是 ViewGroup 的子类。将容器对象的 android:screenReaderFocusable 属性设为 true,并将每个内部对象的 android:focusable 属性设为 false。这样,无障碍服务就可以在单次语音中逐个读出内部元素的内容说明。这样整合相关元素有助于使用辅助技术的用户更高效地发现屏幕上的信息。

  • android:screenReaderFocusable
    https://developer.android.google.cn/reference/android/view/View#attr_android:screenReaderFocusable

  • android:focusable
    https://developer.android.google.cn/reference/android/view/View#attr_android:focusable

注意: 在 Android 8.1 (API 级别 27) 及更低版本中,android:screenReaderFocusable 属性不可用,因此应改为设置容器的 android:focusable 属性

以下代码段包含彼此相关的内容片段,因此容器元素 (即 ConstraintLayout 的实例) 的 android:screenReaderFocusable 属性设为 true,每个内部 TextView 元素的 android:focusable 属性设为 false:

<!-- In response to a single user interaction, accessibility services announceboth the title and the artist of the song. -->
<ConstraintLayoutandroid:id="@+id/song_data_container" ...android:screenReaderFocusable="true"><TextViewandroid:id="@+id/song_title" ...android:focusable="false"android:text="@string/my_song_title" /><TextViewandroid:id="@+id/song_artist"android:focusable="false"android:text="@string/my_songwriter" />
</ConstraintLayout>

由于无障碍服务在单次语音中读出内部元素的说明,因此务必确保每条说明都简明扼要地传达出元素的含义。

自定义组标签

如果需要,您可以通过为某个组本身提供内容说明,替换平台中该组的内部元素说明的默认分组和排序。

以下代码段展示了一个示例自定义组说明:

<!-- In response to a single user interaction, accessibility servicesannounce the custom content description for the group. -->
<ConstraintLayoutandroid:id="@+id/song_data_container" ...android:screenReaderFocusable="true"android:contentDescription="@string/title_artist_best_song"><TextViewandroid:id="@+id/song_title" ...<!-- Content ignored by accessibility services -->android:text="@string/my_song_title" /><TextViewandroid:id="@+id/song_artist"<!-- Content ignored by accessibility services -->android:text="@string/my_songwriter" />
</ConstraintLayout>

嵌套组

如果应用的界面显示多维信息 (如节日活动的每日列表),应对内部组容器使用 android:screenReaderFocusable 属性。这种标签添加方案可以很好地平衡发现屏幕内容所需的语音条数与每条语音的长度。

以下代码段展示了一种为较大的组内的组添加标签的方法:

<!-- In response to a single user interaction, accessibility servicesannounce the events for a single stage only. -->
<ConstraintLayoutandroid:id="@+id/festival_event_table" ... ><ConstraintLayoutandroid:id="@+id/stage_a_event_column"android:screenReaderFocusable="true"><!-- UI elements that describe the events on Stage A. --></ConstraintLayout><ConstraintLayoutandroid:id="@+id/stage_b_event_column"android:screenReaderFocusable="true"><!-- UI elements that describe the events on Stage B. --></ConstraintLayout>
</ConstraintLayout>

文字中的标题

某些应用使用标题总结屏幕上显示的多组文字。如果特定的 View 元素表示一个标题,您可以通过将该元素的 android:accessibilityHeading 属性设为 true,表明它的无障碍服务用途。

  • android:accessibilityHeading
    https://developer.android.google.cn/reference/android/view/View#attr_android:accessibilityHeading

无障碍服务的用户可以选择浏览标题,而不是浏览段落或字词。这种灵活性可改善文字浏览体验。

无障碍窗格标题

在 Android 9 (API 级别 28) 及更高版本中,您可以为屏幕的窗格提供使用起来没有障碍的标题。出于无障碍目的,窗格是窗口中能够从视觉上加以区分的部分,如 Fragment 的内容。为了让无障碍服务能够理解与窗口行为类似的窗格行为,您应该为应用的窗格指定描述性标题。这样一来,当窗格的外观或内容发生变化时,无障碍服务就可以为用户提供更精细的信息。

如需指定窗格的标题,请使用 android:accessibilityPaneTitle 属性,如以下代码段所示:

<!-- Accessibility services receive announcements about content changesthat are scoped to either the "shopping cart view" section (top) or"browse items" section (bottom) -->
<MyShoppingCartViewandroid:id="@+id/shoppingCartContainer"android:accessibilityPaneTitle="@string/shoppingCart" ... /><MyShoppingBrowseViewandroid:id="@+id/browseItemsContainer"android:accessibilityPaneTitle="@string/browseProducts" ... />
  • android:accessibilityPaneTitle
    https://developer.android.google.cn/reference/android/R.attr#accessibilityPaneTitle

装饰性元素

如果界面中某个元素的存在只是为了让内容看起来间距合理或布局美观,请将其 android:contentDescription 属性设为 "null":

https://developer.android.google.cn/reference/android/view/View#attr_android:contentDescriptionandroid:contentDescription

如果应用仅支持搭载 Android 4.1 (API 级别 16) 或更高版本的设备,您可以将这些纯装饰性元素的 android:importantForAccessibility 属性设为 "no"。

扩展系统微件

要点: 在设计应用的界面时,请使用或扩展位于 Android 类层次结构中尽可能靠下位置的系统微件。位于层次结构最下方的系统微件已经具备应用所需的大多数无障碍功能。扩展系统提供的这些微件比根据更通用的 ViewViewCompatCanvasCanvasCompat 类创建您自己的微件更容易。

如果您必须直接扩展 ViewCanvas (这可能是高度个性化体验或游戏关卡所必需的),请参阅让自定义视图使用起来更没有障碍。

  • View
    https://developer.android.google.cn/reference/kotlin/android/view/View

  • ViewCompat
    https://developer.android.google.cn/reference/kotlin/androidx/core/view/ViewCompat

  • Canvas
    https://developer.android.google.cn/reference/kotlin/android/graphics/Canvas

  • CanvasCompat
    https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/canvas/CanvasCompat.java

  • 让自定义视图使用起来更没有障碍
    https://developer.android.google.cn/guide/topics/ui/accessibility/custom-views

本部分介绍了如何实现一种特殊类型的 Switch,称为 TriSwitch。TriSwitch 对象的工作方式与 Switch 对象类似,不同之处在于,TriSwitch 的每个实例允许用户在 3 种可能的状态之间切换。

  • Switch
    https://developer.android.google.cn/reference/android/widget/Switch

从类层次结构最下方扩展

Switch 对象从其层次结构中的几个框架界面类继承一些属性:

View
↳ TextView↳ Button↳ CompoundButton↳ Switch

新的 TriSwitch 类最好直接从 Switch 类扩展。这样,Android 无障碍功能框架就可以提供 TriSwitch 类所需的大多数无障碍功能:

  • 无障碍操作: 告知系统无障碍服务如何模拟在 TriSwitch 对象上执行的各种可能的用户输入。(继承自 View。)

  • 无障碍事件: 告知无障碍服务当屏幕刷新或更新时,TriSwitch 对象的外观会发生的各种可能的变化方式。(继承自 View。)

  • 特征: 有关每个 TriSwitch 对象的详细信息,例如其显示的任何文字的内容。(继承自 TextView。)

  • 状态信息: TriSwitch 对象的当前状态的说明,如 "选中" 或 "未选中"。(继承自 CompoundButton。)

  • 状态的文字说明: 文字类说明,解释了各种状态的含义。(继承自 Switch。)

继承自 Switch 及其父类的这种聚合行为几乎就是 TriSwitch 对象的预期行为。因此,您的实现可以着重于将可能的状态数从 2 种扩展到 3 种。

定义自定义事件

当您扩展某个系统微件时,可能会改变用户与该微件互动方式的某一方面。请务必定义这些互动变化,以便无障碍服务可以更新应用的微件,就像用户直接与微件互动一样。

一般准则是,对于您替换的每个基于视图的回调,您还需要通过替换 ViewCompat.replaceAccessibilityAction() 来重新定义相应的无障碍操作。在应用的测试中,您可以通过调用 ViewCompat.performAccessibilityAction() 来验证这些重新定义的操作的行为。

  • ViewCompat.replaceAccessibilityAction()
    https://developer.android.google.cn/reference/androidx/core/view/ViewCompat#replaceAccessibilityAction(android.view.View,%20androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat,%20java.lang.CharSequence,%20androidx.core.view.accessibility.AccessibilityViewCommand)

  • ViewCompat.performAccessibilityAction()
    https://developer.android.google.cn/reference/androidx/core/view/ViewCompat#performAccessibilityAction(android.view.View,%20int,%20android.os.Bundle)

此原则如何对 TriSwitch 对象起作用

与普通的 Switch 对象不同,点按 TriSwitch 对象可以循环切换 3 种可能的状态。因此,需要更新相应的 ACTION_CLICK 无障碍操作:

class TriSwitch(context: Context) : Switch(context) {// 0, 1, or 2.var currentState: Int = 0private setinit {updateAccessibilityActions()}private fun updateAccessibilityActions() {ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,action-label) {view, args -> moveToNextState()})}private fun moveToNextState() {currentState = (currentState + 1) % 3}
}

使用除颜色之外的提示

为了帮助有色觉缺陷的用户,请使用除颜色之外的提示区分应用屏幕中的界面元素。具体方法包括采用不同的形状或大小、提供文字或视觉图案,或者添加基于音频的反馈或基于轻触手势的触感反馈来表示元素的差异。

下图显示了一个 Activity 的两个版本。一个版本仅使用颜色区分工作流程中两种可能的操作。另一个版本采用了最佳做法: 除了颜色之外,还使用了形状和文字来突出两个选项之间的差异:

△ 仅使用颜色创建界面元素的示例 (左图),

以及使用颜色、形状和文字创建界面元素的示例 (右图)

让媒体内容使用起来更没有障碍

如果您开发的应用包含视频剪辑或音频录音等媒体内容,应设法为具有不同类型的无障碍功能需求的用户提供支持,让他们能够理解此类内容。特别是,我们建议您做到以下几点:

  • 添加可让用户暂停或停止播放媒体、调整音量以及切换字幕的控件。

  • 如果视频提供的信息对于完成工作流程至关重要,应以其他格式提供相同的内容,如转录内容。

其他资源

如需详细了解如何让您的应用使用起来更没有障碍,请参阅下面列出的其他资源:

  • Codelab: 基本的 Android 无障碍功能

    https://developer.android.google.cn/codelabs/starting-android-accessibility#0

  • 博文: 无障碍功能: 是否所有用户都能使用您的应用?

    https://android-developers.googleblog.com/2012/04/accessibility-are-you-serving-all-your.html

欢迎您持续关注我们,及时了解更多开发技术和产品更新等资讯动态。

推荐阅读

如页面未加载,请刷新重试

 点击屏末 阅读原文 | 即刻了解无障碍功能更多相关内容


最佳实践 | 助您提升应用的无障碍功能相关推荐

  1. 7项最佳实践助您利用媒体转换不断发展数据中心网络

    任何数据中心网络的基础都是物理层;是光纤和铜缆将用户.服务器.存储以及当前物联网时代的各种设备连接起来的.而在这些网络上不断增涨的需求,需要数据中心不断进行升级.本文中,我们将为广大读者诸君介绍7项最 ...

  2. 【Redis最佳实践】使用DCS Redis实现排行榜功能

    本节基于华为云DCS Redis实践所编写,用于指导您在以下场景使用DCS Redis实现排行榜功能. 目录 场景介绍 代码示例 实践指导 运行结果 华为云DCS Redis介绍 场景介绍 在网页和A ...

  3. CODING 最佳实践:快课网研发效能提升之路

    快课企业移动学习平台是上海快微网络科技有限公司自主研发的企业级 SaaS 平台,提供移动学习.考试练习.培训管理.知识分享.统计分析等学习和培训功能,为员工.经销商及客户等全价值链合作伙伴提供全面的知 ...

  4. 提升Web应用程序性能的最佳实践

    2019独角兽企业重金招聘Python工程师标准>>> 导读:作为开发人员,Web页面加载或刷新的速度对其网站至关重要.在浏览器中调整性能问题比在Java应用程 序中更难.开发人员在 ...

  5. 提升Android开发效率的最佳实践

    本文属于Android入门与最佳实践系列,有兴趣的可以围观笔者的前一篇关于Android实践建议的文章:2016里一些Android最佳实践列表--Opinionated 原文地址 软件工程师的工作效 ...

  6. SQLServer · 最佳实践 · RDS for SQL Server 2012 权限限制的提升与改善

    title: SQLServer · 最佳实践 · RDS for SQL Server 2012 权限限制的提升与改善 author: 石沫 背景 SQL Server 作为一种强大的关系型数据库, ...

  7. 研发效能提升最佳实践的探索

    GIAC(GLOBAL INTERNET ARCHITECTURE CONFERENCE)是长期关注互联网技术与架构的高可用架构技术社区和msup推出的,面向架构师.技术负责人及高端技术从业人员的年度 ...

  8. 提升研发效能没那么难,看优酷的最佳实践!

    作者 | 阿里文娱技术专家 成文 责编 | 屠敏 研发效能期望 随着敏捷.DevOps 等概念的兴起,研发效能成为企业关注的重点,但是研发效能面临的问题和挑战也与日俱增.尤其在互联网行业,版本需要快速 ...

  9. CODING 最佳实践:快课网研发效能提升之路 1

    快课企业移动学习平台是上海快微网络科技有限公司自主研发的企业级 SaaS 平台,提供移动学习.考试练习.培训管理.知识分享.统计分析等学习和培训功能,为员工.经销商及客户等全价值链合作伙伴提供全面的知 ...

最新文章

  1. [转载红鱼儿]kbmmw 开发点滴:ErrorTable用法
  2. 【Codeforces】1136C Nastya Is Transposing Matrices (矩阵转置)
  3. 机器学习/数据挖掘/算法岗位面试题汇总
  4. [原创]一起来做网页游戏---前言
  5. 从本地上传项目到 github 以及从github 下载项目到本地环境
  6. esp32 rtc 时钟设置不对_STM32入门系列-STM32时钟系统,STM32时钟树
  7. 图片太多加载过慢?学学图片懒加载吧
  8. 简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏
  9. Windows平台下动态链接库的总结
  10. 误泄露公司代码、疫情期间被裁,一个“菜鸟”程序员的生存日记
  11. 普通人如何站在时代风口学好AI?这是我看过最好的答案
  12. 字节跳动入局外卖赛道 美团饿了么怕了吗?
  13. double to string 损失精度的问题
  14. 常用的python内置方法
  15. 阵列信号处理及matlab实现_球形麦克风阵列设计
  16. 基于机器学习中KNN算法的车牌字符识别
  17. ArcGIS——计算几何——面积/周长禁用
  18. 第2节:支持向量机SVM即numpy
  19. 高速数据线缆自动化测试系统软件NSAT-1000
  20. mx250是什么_分析mx250显卡什么级别

热门文章

  1. 解决Virtua Box 中的XP系统虚拟机连不上网问题
  2. 分享搭建脚手架的一些经验
  3. 3.MySQL数据类型
  4. netstat命令常用参数
  5. 英伟达发布ChatGPT专用GPU,性能提升10倍,还推出云服务,普通企业也能训练LLM...
  6. matlab 工具箱 GATBX 的安装,安装Sheffield Matlab遗传算法工具箱的建议
  7. R语言学习——plot函数
  8. EasyUI/TopJUI可编辑表格的列根据返回数据判断是使用 combobox 还是 numberbox
  9. 《构建之法》第十二章 用户体验
  10. 期货公司编码和期货公司排名分类评级(2022年最新)