资讯详情

让图表对盲人友好:TEAChart VoiceOver 无障碍访问实现原理深度解析

📅 2026/10/16 16:14:45 | 华诺云谱 👁 阅读
让图表对盲人友好:TEAChart VoiceOver 无障碍访问实现原理深度解析
【免费下载链接】TEAChartSimple and intuitive iOS chart library. Contribution graph, clock chart, and bar chart.项目地址https://gitcode.com/gh_mirrors/te/TEAChart点击查看免费下载TEAChart 是一款简单直观的 iOS 图表库内置贡献图、时钟图与柱状图三种图表并完整支持VoiceOver 无障碍访问。这篇文章面向零基础读者带你拆解一个用 Core Graphics 绘制的自绘图表是如何被翻译成视障用户能逐格听懂的语音播报的——看懂之后你能把这套思路搬到任何自绘图表上。为什么自绘图表对 VoiceOver 是盲区像UILabel、UIButton这类系统控件天生自带无障碍信息手指滑过去 VoiceOver 就能念出来。但图表不一样。TEAChart 的每种图表都是在一个UIView里用CGContext直接画出来的——扇形、色块、柱条。系统只看到一堆被填充的像素和路径它根本不知道第 12 格代表3 次提交也不知道某段红色扇形代表上午 10 点到 11 点。所以默认情况下视障用户的手指划过整张图表VoiceOver什么都不会念——因为整张视图对它而言就是一坨没有文字的空View。想让它开口就必须主动把数据翻译成人话。TEAChart 的做法就是给图表里的每一个图形单元每一格、每一根柱、每一段扇形都配一个独立的、能被朗读的元素。TEAChart 的 VoiceOver 无障碍能力一览 三种图表都遵循同一套机制只是念的话术不同图表类型源码文件VoiceOver 会念出示例贡献图TEAChart/TEAContributionGraph.m2026年10月6日3 次提交 / ……无提交柱状图TEAChart/TEABarChart.mA 25.00 %时钟图TEAChart/TEAClockChart.m上午10:30 到 上午11:30下面我们把这套机制拆成原理 → 关键技巧 → 具体话术三层来看。原理一用 UIAccessibilityElement 给图形单元配音iOS 提供了一个UIAccessibilityElement。它不是视图不参与界面布局本质是一个虚拟的可朗读单元只干一件事在屏幕某块区域上念一句你指定的话。要让它生效需要设三样东西initWithAccessibilityContainer:—— 把它挂在哪张图表视图下accessibilityFrame—— 它对应屏幕上的哪块区域用屏幕坐标accessibilityLabel—— 它要念的那句人话。以贡献图为例每画完一天就顺手造一个这样的元素UIAccessibilityElement *dayBlock [[UIAccessibilityElement alloc] initWithAccessibilityContainer:self]; dayBlock.accessibilityFrame [self convertRect:backgroundRect toView:nil]; if (contributions 0) { dayBlock.accessibilityLabel [NSString stringWithFormat:% : %ld Contributions, date, contributions]; } [self.accessibleElements addObject:dayBlock];这里的self.accessibleElements是一个私有数组专门用来收集本视图所有的可朗读单元。原理二让图表视图实现无障碍容器协议造好了一个个元素还不够还得让 VoiceOver知道这些元素的存在。这就要让图表视图实现无障碍容器协议UIAccessibilityElementContainer它一共就四个方法逻辑非常简单方法作用TEAChart 的返回isAccessibilityElement视图本身是否要自己念返回NO我是容器不念内容accessibilityElementCount我里面有几个可朗读单元等于数据条数accessibilityElementAtIndex:按下标取某一个单元返回对应的UIAccessibilityElementindexOfAccessibilityElement:反过来查某个单元的下标在数组里定位以柱状图为例见 TEABarChart.m- (BOOL)isAccessibilityElement { return NO; } - (NSInteger)accessibilityElementCount { return self.data.count; } - (id)accessibilityElementAtIndex:(NSInteger)index { return self.accessibleElements[index]; } - (NSInteger)indexOfAccessibilityElement:(id)element { return [self.accessibleElements indexOfObject:element]; }isAccessibilityElement返回NO意思是我这块整体不念但我里面有子元素VoiceOver 就会转而按accessibilityElementCount逐个遍历、逐个朗读。关键技巧在 drawRect: 里边绘制、边注册✨TEAChart 有个很关键的设计无障碍元素不在别处创建而是在drawRect:里、和图形画出来的同一时刻一起生成。为什么要这么做因为图表的几何信息每根柱多高、每格在哪、每段扇形多大都是在drawRect:里才真正算出来的。既然坐标是这时才确定的那么无障碍框accessibilityFrame也就在这里取——画到哪儿就把朗读区放到哪儿。这样保证了看到的和听到的位置天然一致不会因为某处改动而错位。还有一个容易被忽略的细节accessibilityFrame需要的是屏幕坐标而drawRect:里拿到的是视图内部坐标所以要用[self convertRect:... toView:nil]转换过去。时钟图里还藏着一个坑。它要用CGContextGetPathBoundingBox取当前路径的包围盒当无障碍框这一步必须在CGContextFillPath真正填充扇形之前完成——因为路径一旦被填充/描边当前路径就被清空了再取包围盒就取不到正确的扇形范围了。这段顺序见 TEAClockChart.m。三种图表分别怎么念贡献图逐格播报提交量对应 GitHub 风格贡献日历。它对每一天的色块都生成一个元素日期交给NSDateFormatterNSDateFormatterFullStyle按本地化格式念出来有提交2026年10月6日3 次提交无提交2026年10月6日无提交关键实现见 TEAContributionGraph.m注意有 / 无提交会走不同的话术。柱状图念出柱名与占比对应每根柱子一个元素若设置了xLabels就用标签名如 A来称呼这根柱没设置则自动生成Bar 3 of 8这样的名字保证每根柱都有身份数值不念原始数而是念成百分比A 25.00 %当最大值很大时百分比比原始值更友好。见 TEABarChart.m。时钟图念出起止时间区间对应 Pomotodo元素注册见 TEAClockChart.m。无障碍标签怎么写才自然好听️代码里最能体现为盲人友好的其实不是技术结构而是那句要被念出来的accessibilityLabel。TEAChart 的做法有三个小窍门量纲要带单位—— 说3 次提交25.00 %而不是干巴巴的 3 或 0.25空值也要开口—— 没数据就明说无提交而不是沉默长格式交给系统本地化—— 日期、时间都用NSDateFormatter输出自动适配用户语言与地区。念出来的应该是人话而不是变量值或十六进制色号。关键源码位置速查文件与行号要点位置无障碍元素数组柱状图TEABarChart.m逐柱注册无障碍元素TEABarChart.m容器协议四方法柱状图TEABarChart.m逐日注册无障碍元素TEAContributionGraph.m容器协议四方法贡献图TEAContributionGraph.m扇形包围盒 → 无障碍框TEAClockChart.m容器协议四方法时钟图TEAClockChart.mDemo 装配三种图表TEAViewController.m完整属性文档TEAContributionGraph.h可落地的 iOS 图表无障碍实践清单 ✅如果要把 TEAChart 的思路用到你自己的自绘图表面照着这几点做即可自绘视图默认对 VoiceOver 不可见必须主动实现无障碍别指望系统自动读懂像素每个图形单元 一个UIAccessibilityElementframelabel让容器视图实现四个方法且accessibilityElementCount必须与真实元素数一致accessibilityFrame用屏幕坐标convertRect:toView:nil标签写成人话带单位、处理空值、用本地化日期几何在drawRect:里算就在drawRect:里同步生成元素保证视听位置一致。总结TEAChart 用虚拟元素 容器协议 drawRect: 同步三板斧把三种原本对 VoiceOver 完全失明的自绘图表变成了视障用户能逐格、逐柱、逐段朗读的内容。这套模式不复杂却非常通用——无论是图表、看板、时间轴还是自定义列表只要坚持给每个图形单元配一句人话就能让你的 App 对更多用户真正友好。赞分享【免费下载链接】TEAChartSimple and intuitive iOS chart library. Contribution graph, clock chart, and bar chart.项目地址https://gitcode.com/gh_mirrors/te/TEAChart点击查看免费下载相关推荐Threebox 入门指南如何 10 分钟给 Mapbox 地图加上可交互的 3D 对象Threebox 入门指南如何 10 分钟给 Mapbox 地图加上可交互的 3D 对象 想在地图上放一个 3D 模型、让它能被点击、被拖动、还能沿着导航路线前端3D渲染图形学GISMetaTube SDK Go核心架构解析深入理解Go语言元数据管理SDK设计MetaTube SDK Go核心架构解析深入理解Go语言元数据管理SDK设计 MetaTube SDK Go是一个功能强大的元数据管理SDK专为Go语言开CANN/PTO-ISAMegaMoE调度融合算子示例PTO MegaMoE Dispatch Combine Fusion Example 中文文档 https://link.gitcode.com/i/ab算子库人工智能CANN创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑