为视障者打造无障碍的 WinForms 应用程序
Posted 張賜榮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为视障者打造无障碍的 WinForms 应用程序相关的知识,希望对你有一定的参考价值。
如何在Windows Forms 应用程序中改善屏幕阅读器可访问性
屏幕阅读器是一种辅助技术,可以通过语音或者盲文显示器来读出屏幕上的内容,帮助视力障碍者使用计算机。Windows Forms 是一种基于.NET Framework 的桌面应用程序开发技术,提供了丰富的控件和组件,以及一些可访问性功能,可以让开发者创建更适合屏幕阅读器用户的应用程序。本文将介绍如何在Windows Forms 应用程序中改善屏幕阅读器可访问性,以及如何使用NVDA(NonVisual Desktop Access)这款免费的屏幕阅读器软件进行测试。
设计可访问的Windows Forms 应用程序
要设计一个可访问的Windows Forms 应用程序,需要考虑以下几个方面:
- 提供足够的对比度和清晰的视觉提示。屏幕阅读器用户可能会有不同程度的视力残留,因此应该使用高对比度的颜色方案,避免使用纯色或者渐变色作为背景。同时,应该为重要的元素(如按钮、链接、表单字段等)提供明显的视觉提示,例如边框、下划线、图标等,以便用户能够轻松地找到。
- 使用合适的控件和布局。Windows Forms 提供了多种控件和布局方式,可以帮助开发者创建符合用户期望和习惯的界面。例如,使用Label 控件来描述TextBox 控件的作用,并且让Label 控件在Tab 顺序中紧跟TextBox 控件;使用GroupBox 或者Panel 控件来对相关的控件进行分组和区分;使用TableLayoutPanel 或者FlowLayoutPanel 控件来实现自适应的布局等。
- 设置可访问性属性和事件。Windows Forms 的控件都继承了AccessibleObject 类,这个类提供了一些属性和事件,可以让开发者为控件提供更多的可访问性信息,以便屏幕阅读器能够正确地识别和读出它们。例如,设置AccessibleName 属性来为控件提供一个简短而有意义的名称;设置AccessibleDescription 属性来为控件提供一个更详细的描述;设置AccessibleRole 属性来为控件指定一个角色(如按钮、链接、列表框等);设置AccessibleDefaultActionDescription 属性来为控件指定一个默认的操作描述(如点击、选择、输入等);触发AccessibleEvents 事件来通知屏幕阅读器控件状态的变化(如选中、展开、聚焦等)。
- 支持键盘操作和导航。屏幕阅读器用户通常会使用键盘而不是鼠标来操作计算机,因此开发者应该确保Windows Forms 应用程序支持完整的键盘操作和导航。例如,使用Tab 键和Shift + Tab 键来在不同的控件之间切换焦点;使用Enter 键或者空格键来激活按钮或者链接;使用方向键或者Page Up / Page Down 键来在列表框或者表格中移动;使用Alt + 字母键来快速定位到具有助记符(&)的控件;使用Esc 键来关闭对话框或者取消操作等。
使用NVDA进行测试
NVDA 是一款免费、开源、易用的屏幕阅读器软件,它可以与多种浏览器和应用程序配合使用,包括Windows Forms 应用程序。使用NVDA进行测试可以帮助开发者发现并改进Windows Forms 应用程序中存在的可访问性问题。以下是一些使用NVDA进行测试的基本步骤:
- 下载并安装NVDA。NVDA 可以从NVDA 官方网站下载并安装到Windows 计算机上。安装过程中可以选择语言、语音引擎、语速等选项。
- 启动并配置NVDA。安装成功后,可以按快捷键Ctrl+Alt+N启动NVDA读屏软件。启动NVDA后,可以按下NVDA 键(默认是Insert 键或者Caps Lock 键)+ N 键来打开NVDA 菜单,在菜单中可以进入首选项->设置来调整NVDA 的各项参数,例如语音、键盘、鼠标、对象呈现等。
- 打开并运行Windows Forms 应用程序。打开并运行要测试的Windows Forms 应用程序,在应用程序界面上按下NVDA 键+ B 键来开始连续阅读所有内容。注意听NVDA 是否能够正确地读出控件的名称、描述、角色、状态等信息,以及是否能够按照预期的顺序进行阅读。
- 使用键盘操作和导航Windows Forms 应用程序。在应用程序界面上使用键盘进行操作和导航,例如使用Tab 键和Shift + Tab 键在不同的控件之间切换焦点;使用Enter 键或者空格键激活按钮或者链接;使用方向键或者Page Up / Page Down 键在列表框或者表格中移动;使用Alt + 字母键快速定位到具有助记符(&)的控件;使用Esc 键关闭对话框或者取消操作等。注意听NVDA 是否能够及时地反馈当前焦点所在的控件以及其相关信息,以及是否能够正确地执行各种操作。
- 记录并修复发现的可访问性问题。在测试过程中,如果发现了任何影响屏幕阅读器用户体验的可访问性问题,应该及时地记录并修复它们。例如,如果发现某个控件没有设置合适的AccessibleName 属性或者没有添加相应的Label 控件来描述它,就应该补充这些信息;如果发现某个控件没有触发相应的AccessibleEvents 事件来通知屏幕阅读器状态变化,就应该添加这些事件;如果发现某个控件无法通过键盘操作或者导航到达,就应该调整其Tab 顺序或者添加助记符等。
总结
本文介绍了如何在Windows Forms 应用程序中改善屏幕阅读器可访问性,以及如何使用NVDA 这款免费的屏幕阅读器软件进行测试。希望本文能够对想要创建更友好和包容的Windows Forms 应用程序的开发者有所帮助。
知乎: @张赐荣
赐荣博客: www.prc.cx
京喜小程序首页无障碍优化实践
前言
本文参考 WCAG 2.1 、WAI-ARIA 和 Web 可访问性与无障碍最佳实践,在京喜小程序首页无障碍优化开发中,总结了一些“无障碍优化”在小程序端的实践,希望以此推动无障碍在小程序更多地落地。
无障碍
无障碍是什么?
在了解无障碍之前,我们先来了解一些数据:
- 据中国盲协的最新数据显示,中国目前视障者有 1700 多万,随着老龄化的严重,视障群体有进一步扩大的趋势。
- 在中国,有着庞大的信息障碍群体,包括:8500 多万残障人士,两亿多老年人,大量认知障碍人士。
- …
无障碍
无障碍 (Accessibility),是指在发展过程中没有阻碍,活动能够顺利进行。从无障碍引申的相关词汇有,无障碍设施、信息无障碍、无障碍交流等等。
信息无障碍
对于信息无障碍,中国互联网协会给出了一个定义:任何人(无论是健全人还是残疾人,无论是年轻人还是老年人)在任何情况下都能平等地、方便地、无障碍地获取信息、利用信息。
以上释义,源自百度百科
无障碍设施
如果看不见、听不见,我们该怎么生活呢?
在生活中,我们常常会看到一些设施:缘石坡道、盲道、无障碍垂直电梯、无障碍扶手、人行横道的警示信号等等。这些给障碍群体使用的安全设施,就是无障碍设施 (Accessibility Facilities)。无障碍设施主要是为了让障碍群体能够自主、安全、方便地通行和活动,它是障碍群体生活顺畅的重要保证。除物质环境的无障碍设施,无障碍设施还可以扩展到信息和交流的无障碍,比如互联网中的网站设计、网上办事、购物交互等。
信息无障碍的现状
随着互联网不断发展,互联网应用已经融入到我们生活的各个方面,行动不便的障碍群体则更希望也更需要通过方便的互联网应用获取信息、学习和生活。因此,互联网应用进行无障碍优化,对障碍群体显得尤为重要。
早在 1997 年 2 月,万维网联盟 (W3C) 为了提升网络的无障碍性,成立了网络无障碍推动 (WAI)小组,并制定了一系列的关于网络无障碍的标准、规范、检测表、无障碍的技术,并与世界各地的组织携手合作,在全球范围推动无障碍网络运动。
但至今为止,互联网产品的无障碍优化进展仍然缓慢,很多网站建设和移动端 APP 的开发都还未考虑无障碍优化,即使是通过读屏软件,也很难获取想要的信息。
障碍群体调研
我们以电商平台购物 APP 为调研对象,同信息无障碍研究会合作做了一个调研。根据收集到的舆情反馈,我们了解到:
在消费降级的当下,低价商品火遍互联网的每个角落,障碍群体是其中需求度最大的人群之一。京喜,作为京东旗下的拼购电商平台,与拼多多和淘宝特价版一样,在障碍人士聚集的论坛和QQ中,有非常多的讨论。用户们对京喜没做无障碍表示遗憾,也期待京喜可以尽快开展无障碍优化,享受低价拼购的乐趣。
根据研究会信息无障碍工程师初步检测,目前影响障碍用户们使用缺陷集中在以下几类中:
- 按钮未加标签,用户难以了解对应按钮点按分别会触发哪些功能。
- 精简状态不提示或提示不符合障碍用户理解习惯,导致用户无法了解正确的信息,诸如是否已加入购物车等。
- 焦点逻辑混乱或没有遵循正确的读屏浏览模式,致使用户不能便捷、清晰地了解界面信息,严重影响操作效率。
- 活动信息或弹窗等页面,由于使用大量字绘架构且没有集成无障碍特性,用户无法便捷地参与平台营销活动。
以上几类属于障碍用户能够无障碍使用的基本支撑,部分或完全适配后将能促使 APP 实现较好的无障碍体验。
无障碍优化开发
在了解小程序的无障碍优化之前,首先需要了解 Web 无障碍开发的基础知识,及读屏软件的工作方式。
读屏软件
无障碍访问的关键点 —— 使用屏幕阅读器。
移动端 APP 访问无障碍特性,开启读屏模式的设置路径:
- iOS:
设置 -> 通用 -> 辅助功能 -> 旁白(VoiceOver)
。 - 安卓:
设置 -> 辅助功能 -> 无障碍 -> TalkBack
(不同机型路径可能不一样)
以下是一些主要的 VoiceOver 手势:
- 轻点:选择并朗读项目。
- 轻点两下:激活所选项目。
- 左右轻扫:选择下一项或上一项。
- 三个手指向上或向下轻扫:滑动屏幕上的列表或区。
- 双指搓擦:快速来回移动两个手指三次(形成“z”字形)以解除提醒,或者返回上一个屏幕。
- 更多手势可以查看 :VoiceOver - iPhone 使用手册。
安卓的 TalkBack 手势与 VoiceOver 有一些差异,后面还会提到……
WAI-ARIA
WAI-ARIA
通过浏览器把信息暴露给 accessibility APIs (无障碍API),作为读屏软件的信息源。
WAI-ARIA ( Accessible Rich Internet Applications (WAI-ARIA) 1.1) 是一项技术,它可以通过浏览器和一些辅助技术来帮助我们进一步地识别以及实现语义化,这样一来能帮助我们解决问题,也让用户可以了解发生了什么。WAI-ARIA 是 W3C 编写的规范,定义了一组可用于其他元素的 HTML 特性,用于提供额外的语义化以及改善缺乏的可访问性。
以下是规范中三个主要的特性:
- 角色 —— 定义元素是干什么的。如
role=\'button\'
表示元素是按钮,读屏软件会读作“按钮”、role=\'searchbox\'
表示元素用于搜索,读屏软件会读作"搜索"。 - 属性 —— 让元素具备更多的意义。如
aria-required=\'true\'
表示元素在表单上是必填的、aria-label=\'描述文字\'
用来给当前元素标签加上描述,用不可视的方式给元素加 label,接受字符串作为参数,读屏软件会将描述文字朗读出来。 - 状态 —— 用于表达元素当前条件的特殊属性。如
aria-disabled=\'true\'
表示表单禁止输入、aria-hidden=\'true\'
表示元素会被读屏软件忽略。
更多属性可以参考 Using Aria 中的 States and properties,部分属性可能在小程序设置不生效。
更多 role 可以参考 Using Aria 中的 Widget Roles,部分 role 可能在小程序设置不生效。
因此,无障碍优化便可以借助读屏软件,结合 WAI-ARIA 的特性进行开发。互联网应用引入无障碍特性,使得障碍用户可以清晰准确的获取到页面信息,获得更好的产品体验,方便地实现网上办事、购物等。
京喜小程序首页无障碍优化
背景
此前,京喜小程序未进行无障碍优化,障碍群体在读屏软件的辅助下,基本不能使用。这使得平台失去了障碍群体的市场,同时障碍群体也失去了体验京喜小程序平台服务的机会。因此,希望对平台进行无障碍优化,提升平台的可用性、易用性,让障碍群体享受更好的购物体验。
优化方案
产品提供焦点划分规则、朗读规则、阅读顺序,为京喜小程序首页量身定制无障碍优化方案。内部方案,这里就不透露了。(想了解的话,来投一波简历啊~)
开发实现
目前小程序官方已经支持无障碍访问特性,用户在读屏模式下可以体验无障碍访问。
开发细则
DOM 顺序很重要
读屏软件在读屏时默认按照 DOM 的顺序朗读。
如果 DOM 的顺序与内容的语义顺序不一致,会使得内容难以理解。例如首页中的商品瀑布流,按左右两列布局:
在开发过程中应尽量避免使用会影响到 DOM 视觉顺序的样式,如果无法避免,需要手动设置 tabIndex 属性,告知读屏软件正确的内容顺序。
非文本元素增加描述和角色属性
通过给非文本元素增加描述和角色属性,元素的内容就可以被读屏软件清晰准确地朗读。
- 图像可使用 alt 属性描述图像内容,读屏软件会根据 alt 中的内容朗读出
“描述图像内容 图像”
。 - view 本身是无语义的,可以给元素增加
aria-role
和aria-label
属性。 读屏软件会朗读出“label 描述内容 + role 类型”
。
整块元素读取
一个元素可能由很多子元素组成。在无障碍模式下,读屏软件只能分别聚焦子元素,单独将每个子元素信息读出来。障碍用户在读屏软件的辅助下,获取到的都是元素零零碎碎的信息,这样的体验很不友好。
因此,在无障碍优化过程中,可以将元素当作按钮整块朗读,将子元素的信息整合作为描述,并尽量精简描述内容,缩短朗读文案的时间。
隐藏元素读取
如果不希望部分内容被读出来,可以使用 aria-hidden=\'true\' 来声明,这样读屏时就会忽略这些元素。
<Text aria-hidden=\'true\'>读屏时会忽略这行文本</Text>
在无障碍模式下,这个属性可用来隐藏辅助作用不大或是具有干扰性的内容。
场景实现
非文本元素读取
首页头部中京喜 Logo 和文字是一整张图片。聚焦后,读屏软件默认会读成图像,无法将图片中的文字朗读出来。这样的无障碍体验是非常差的。
在这个场景下,可通过给 Logo 图片增加描述
来进行无障碍优化。
<View className=\'index__main\'>
<View className=\'index__logo\' aria-role=\'text\' aria-label=\'京喜\' />
<View className=\'index__title\'>京东旗下社交电商平台</View>
</View>
类似的还有关闭按钮、返回顶部按钮、菜单栏按钮……
<View
className=\'back-top\'
aria-role=\'button\'
aria-label=\'返回顶部\'
/>
搜索框读取
首页搜索框聚焦后,读屏软件默认会将搜索框中的暗纹读出来。但是障碍用户并不能明显的感知到搜索框元素。
在这个场景下,可以通过给搜索框增加角色属性
来进行无障碍优化。
<View aria-role=\'searchbox\'>
<SearchBar />
</View>
轮播图读取
轮播图由多个子元素组成,但点击为整块点击,且每个子元素都是图片,读屏软件无法让用户清晰感知元素的含义。
在这样的场景下,可以给每一个子元素标签增加描述
,读屏软件就可以识别到子元素了。
<View className=\'banner\'>
<Swiper>
<SwiperItem aria-role=\'text\' aria-label=\'活动推荐1\'>活动1</SwiperItem>
<SwiperItem aria-role=\'text\' aria-label=\'活动推荐2\'>活动2</SwiperItem>
<SwiperItem aria-role=\'text\' aria-label=\'活动推荐3\'>活动3</SwiperItem>
<SwiperItem aria-role=\'text\' aria-label=\'活动推荐4\'>活动4</SwiperItem>
</Swiper>
</View>
但这样的无障碍优化在安卓手机上体验并不友好。
当障碍用户聚焦到轮播图后,读屏软件将子元素的描述朗读读来。轮播图继续轮播,焦点索引却不会随轮播状态自动更新,而是跟随当前子元素滑动消失在屏幕中。若要获取更新后的轮播信息,需要重新聚焦。
在这样的场景下,建议在轮播图的最外层增加描述
,将整块内容当作按钮处理,让障碍用户清楚这是整体点击的按钮。
<View className=\'banner\' aria-role=\'button\' aria-label=\'活动推荐,共4个\'>
<Swiper>
<SwiperItem>活动1</SwiperItem>
<SwiperItem>活动2</SwiperItem>
<SwiperItem>活动3</SwiperItem>
<SwiperItem>活动4</SwiperItem>
</Swiper>
</View>
商品卡片读取
商品卡片由多个子元素组成,读屏软件会将聚焦的子元素(商品图、名字、价格、利益点等)一个个的读出来。
但单独读出每个子元素,不便于障碍用户理解商品卡片的完整含义。
类似这样的场景,可以将商品卡片当作一个按钮整块处理。在商品卡片最外层标签加上 aria-role=\'button\'
,还可以通过 aria-label
标签,将商品信息进行整合,精简描述,缩短商品名字的朗读时间,让障碍用户获得更好的体验。
隐藏元素读取
上文提到商品卡片的无障碍优化可通过 aria-role=\'button\'
和 aria-label
来实现。理想情况下,当障碍用户聚焦到商品卡片,读屏软件将整合的商品信息朗读出来,并提示是按钮类型。
但实际情况并非如此。当障碍用户在安卓手机上聚焦后,读屏软件不仅会将整合的商品信息和 role 朗读出来,还会将商品卡片子元素的文本内容朗读出来。(后文会提到 iOS 的表现)
为了避免商品信息重复朗读,可以在元素文本标签上加上 aria-hidden=\'true\'
,隐藏子元素文本描述,让障碍用户能够获取到清晰简洁的商品信息。
<View aria-role=\'button\' aria-label=\'商品整合信息\'>
<View aria-hidden=\'true\'>
<Image className=\'goods__img\' src=\'https://segmentfault.com/img/bVbPbr5\' lazyLoad />
<View className=\'goods__info\'>商品信息…</View>
</View>
</View>
iOS 和安卓端的差异
滑屏手势差异
安卓:双指滑动,根据手势自适应滑动;
iOS:三指滑动,一屏一屏分页滑动。
轮播图焦点差异
安卓:焦点位置会跟随子元素滑动消失;
iOS:焦点位置固定不变,不会随子元素滑动而消失。
价格读取差异
由于整数部分和小数部分字体大小不同,价格文本是用多个标签实现的。
<View>
¥
<Text>259</Text>
<Text>.2</Text>
</View>
安卓:完整朗读 “259.2元”;
iOS:单独朗读单位、整数、小数,并且会将 “¥” 读作“美元符号”。
aria-role=\'button\' 读取差异
安卓:读作“描述+按钮+子元素文本描述”,需借助 aria-hidden=\'true\'
隐藏子元素文本描述,避免信息重复朗读。
iOS:有两种情况。
- 如果标签同时设置了
aria-label
,则读作“描述 按钮”,不重复朗读子元素文本。 - 如果标签仅设置了
aria-role=\'button\'
,会继续识别子元素文本,读作“描述+按钮+子元素文本描述”。为避免重复朗读,也需要给子元素加上aria-hidden=\'true\'
。
小程序无障碍展望
小程序基础库自 2.7.1 起,支持部分 ARIA 标签,但是仍有部分属性和 role 在小程序中不生效,希望未来可以支持所有的 ARIA 标签,给障碍用户带来更好的体验。
另外,小程序目前还没有相关 API 支持识别用户手机是否开启无障碍(读屏)模式(原生 APP 可以通过相关 API识别)。如果能预知用户手机开启了无障碍模式,就可以通过动态控制前端模块展示,从而更好的隐藏无用信息、排除干扰信息(浮层弹窗、动画等)。在启无障碍模式下,设置数据埋点上报,还可以为障碍用户提供更好的体验。
希望微信小程序能尽快加强对无障碍优化开发的支持力度,让障碍群体能够享受信息化所带来的成果,享受便捷美好的生活。
无障碍体验
手机开启读屏模式,扫码二维码体验:
结语
京喜小程序首页无障碍优化上线后,我们对调研的障碍群体进行了回访,并且得到了不错的体验反馈。
这是我们在小程序无障碍优化上迈出的第一步,要获得更好的小程序无障碍访问体验还有很长一段路要走……
希望此次小程序无障碍优化实践,能让障碍群体享受互联网应用所带来的便利,更好的享受生活。
欢迎关注凹凸实验室博客:aotu.io
或者关注凹凸实验室公众号(AOTULabs),不定时推送文章。
以上是关于为视障者打造无障碍的 WinForms 应用程序的主要内容,如果未能解决你的问题,请参考以下文章