Skip to content

[Accessibility] Android WebView 界面对 TalkBack 视障用户存在严重无障碍问题,文件浏览与操作完全不可达 #2800

Description

@baich110

背景

我是一名视障用户,完全依赖 TalkBack(Android 屏幕阅读器)使用手机。OpenList 作为一款优秀的网盘挂载工具,功能强大且支持多种存储服务,但在 Android 端的无障碍体验存在严重问题,导致视障用户几乎无法正常使用核心功能。

OpenList 的 Android 应用采用 WebView 渲染 Web 界面的方式实现 UI。这种架构在功能上没有问题,但在无障碍方面带来了天然缺陷——Web 界面中的交互元素往往缺少 ARIA 语义标注,TalkBack 无法正确识别和操作这些元素。

源码审查说明

我们对 OpenList 后端(OpenListTeam/OpenList)和前端(OpenListTeam/OpenList-Frontend)进行了逐文件审查。后端为纯 Go API 服务,无障碍问题全部集中在前端 Web 界面。前端基于 SolidJS + Hope UI 构建,以下所有问题均基于源码实际定位。

具体问题

1. 文件列表项完全没有无障碍语义(Blocker/Critical)

源码位置src/pages/home/folder/ListItem.tsxsrc/pages/home/folder/GridItem.tsx

文件列表是 OpenList 的核心交互区域,但 TalkBack 用户几乎无法有效浏览和操作文件。具体表现为:

  • 列表项容器 <HStack> 没有 role="listitem",也没有 aria-label,TalkBack 只能朗读出一堆无意义的文本碎片
  • 文件名使用 <Text title={props.obj.name}> 渲染,但 title 属性 TalkBack 不会自动朗读
  • 文件名、文件大小、修改时间分别是独立的 <Text> 元素,TalkBack 逐个朗读,用户无法快速定位目标文件
  • 点击/双击打开文件夹的逻辑绑定在 on:clickon:dblclick 上,容器没有 role="link"role="button",TalkBack 用户无法得知这是可操作的
  • 网格视图 GridItem.tsx 中缩略图 <ImageWithError> 没有 alt 属性
  • 复选框 <ItemCheckbox>checkedonChange,但没有 aria-label 说明选中的是什么文件

2. 右键菜单 TalkBack 完全不可达(Blocker/Critical)

源码位置src/pages/home/folder/context-menu.tsx

长按文件后弹出的操作菜单(下载、重命名、删除、复制、移动、分享等),对 TalkBack 用户完全不可达:

  • 使用 solid-contextmenu 库,菜单通过 onContextMenu(右键事件)触发,Android TalkBack 没有右键事件
  • 菜单项 <Item> 没有 role="menuitem",没有 aria-label
  • 菜单弹出后没有焦点管理(没有自动 focus 到第一个菜单项)
  • 子菜单 <Submenu> 同样缺少 ARIA 语义

3. 文件列表容器缺少语义结构(Barrier/High)

源码位置src/pages/home/folder/List.tsxsrc/pages/home/folder/Grid.tsx

  • 列表容器 <VStack class="list"> 没有 role="list"
  • 列表标题中的排序按钮(点击列名排序)没有 role="button"aria-label,TalkBack 不知道这是可点击的排序控件
  • 全选复选框没有 aria-label="全选"

4. 页面路标完全缺失(Barrier/High)

源码位置index.htmlsrc/pages/home/Layout.tsxsrc/pages/home/header/Header.tsxsrc/pages/home/Nav.tsx

整个 Web 界面缺少 WAI-ARIA 路标(landmark)标记,TalkBack 用户无法使用路标导航快速定位页面区域:

  • index.html<html lang="en">,中文环境应设为 lang="zh-CN"
  • 没有 <main> 标签,主内容区域没有 role="main"
  • 没有 <nav> 标签,面包屑导航(Nav.tsx 中的 <Breadcrumb>)没有 role="navigation" + aria-label
  • 没有 <header> 标签,顶部栏(Header.tsx)没有 role="banner"
  • 搜索区域没有 role="search"

5. 动态内容更新无播报(Barrier/Medium)

全项目搜索发现零个 aria-live、零个 role="status"、零个 aria-busy

  • 文件上传/下载进度变化 TalkBack 不会播报
  • 操作成功或失败的 Toast 通知 TalkBack 无法感知
  • 加载状态(CenterLoading 组件)没有 aria-busyrole="status" 标注

6. 工具栏按钮缺少标签(Barrier/High)

源码位置src/pages/home/toolbar/Toolbar.tsx 及子组件(Upload.tsxMkdir.tsxDelete.tsxRename.tsxCopyMove.tsxDownload.tsxShare.tsx 等)

  • 工具栏中的上传、新建文件夹、批量重命名、复制、移动、删除等按钮
  • 大量使用 Icon 组件渲染图标按钮,只有视觉图标,没有 aria-label
  • TalkBack 会朗读出"按钮"但无法知道具体功能

7. 文件预览界面部分可操作但不完整(Barrier/High)

源码位置src/pages/home/previews/ 目录下各组件

好的方面:图片预览(image.tsx)有较完善的 aria-label(缩放、旋转、翻页等),分页器(Paginator.tsx)有 aria-label="Previous" / "Next"

问题:

  • 视频播放器(video.tsxvideo_box.tsx)的播放/暂停/进度条等控件缺少无障碍标注
  • 文档预览(doc.tsxpdf.tsx)的 iframe 缺少 title 属性
  • iframe.tsx 虽然有 aria-label="Open in new tab",但 iframe 本身缺少 title

8. 表单元素标签不完整(Barrier/Medium)

源码位置src/pages/manage/storages/AddOrEdit.tsxsrc/components/ModalInput.tsx

  • 部分输入框通过 Modal 的 title 属性间接标注,但没有 aria-label 直接关联
  • 存储配置页面的表单非常复杂,大量下拉框和输入框缺少无障碍标签

已有的无障碍实现(正面发现)

全项目约 25 处 aria-label,集中在:

  • ✅ 图片预览控件(缩放、旋转、翻页等)——较完善
  • ✅ 分页器(上一页/下一页)——有基本标注
  • ✅ 搜索框——有 aria-label="search"
  • ✅ 布局切换——有 aria-label="switch layout"
  • ✅ 文件夹树选择器——确认/取消按钮有标注

这说明开发团队有无障碍意识,但目前覆盖范围远远不够,核心交互区域(文件列表、右键菜单、工具栏)是空白。

技术分析与修复建议

具体修复建议

问题 源码文件 修复方案 优先级
文件列表项不可读 ListItem.tsxGridItem.tsx 为容器添加 role="listitem" + aria-label="文件名,文件大小,修改时间",使用 aria-label 将多项信息合并为一个可朗读的整体 Critical
右键菜单不可达 context-menu.tsx 菜单容器添加 role="menu",菜单项添加 role="menuitem" + aria-label,弹出时自动 focus 到第一个菜单项;考虑增加长按触发的备选交互方式 Critical
列表容器缺语义 List.tsxGrid.tsx 容器添加 role="list",排序按钮添加 role="button" + aria-label,全选复选框添加 aria-label High
页面路标缺失 index.htmlLayout.tsx 添加 <main>/<nav>/<header> 语义标签或对应 role,修正 lang 属性 High
工具栏按钮无标签 toolbar/*.tsx 所有图标按钮添加 aria-label High
动态内容无播报 全局通知组件 操作提示用 role="status"aria-live="polite",错误提示用 aria-live="assertive" Medium
表单元素无标签 manage/storages/AddOrEdit.tsx 所有输入框添加 aria-label,下拉框添加 aria-labelaria-activedescendant Medium
文件预览不完整 previews/video.tsx 视频控件添加 role="slider" + aria-label,iframe 添加 title High

参考资料

1. W3C WCAG 2.1 快速指南

W3C 官方的 Web 内容无障碍指南,是所有 Web 应用的无障碍标准基础。OpenList 作为 Web 界面应用,应参照 WCAG 2.1 AA 级别进行适配。

2. WAI-ARIA 最佳实践

W3C 的 ARIA 规范,为动态 Web 应用提供语义标注标准。OpenList 的文件列表、操作菜单、表单等动态交互场景都可以直接参考。

3. 国内 AI 助手无障碍横评

我们对国内主流 AI 助手的视障用户无障碍体验进行了调研:

产品 视障用户可用性
豆包(字节跳动) ✅ 实用性强,标签全覆盖
Kimi(月之暗面) ❌ 标签缺失,无法使用
通义千问(阿里) ❌ 支持弱
文心一言(百度) ❌ 支持弱
DeepSeek(深度求索) ⚠️ 大量未加标签控件

关键发现:豆包是唯一让盲人「真正用起来」的国内 AI 助手,核心原因是按钮标签全覆盖、读屏适配完善。这说明无障碍适配并不需要推翻重构,关键是为每个交互元素添加正确的语义标注

4. GitHub 官方开源无障碍最佳实践

GitHub 官方开源指南建议每个开源项目:

  • 创建 ACCESSIBILITY.md 文件,声明无障碍承诺
  • 创建无障碍 Issue 模板
  • 在 PR 检查清单中加入无障碍检查项
  • 优先处理阻塞性问题(Critical 级别)

来源:https://opensource.guide/accessibility-best-practices-for-your-project/

社区协作

关于我们

我们来自中国视障社区,社区中视障开发者已超 20000 人,视障用户群体已超 20 万人,覆盖国内主流读屏软件用户群体(天坦读屏、TalkBack 等)。

测试协作

如果开发组愿意推进无障碍优化,我们可以在第一版修复发布后,组织社区视障用户进行系统化测试,覆盖多设备、多读屏软件的真实使用场景,提供结构化反馈报告。

推广意愿

OpenList 作为功能最全面的开源网盘挂载工具,如果在无障碍方面率先做好,将在视障用户群体中获得显著的社区口碑与用户增长。我们愿意在视障社区内推广 OpenList 的知名度。

环境信息

  • 设备:Redmi K80 Ultra (dali)
  • Android 版本:16 (API 36)
  • 读屏软件:天坦读屏(Tantan Screen Reader),基于 Android AccessibilityService 框架
  • OpenList 部署方式:Android App

希望开发组能够重视无障碍体验,让视障用户也能顺畅使用 OpenList。感谢!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions