flutter-improving-accessibility
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseImplementing Flutter Accessibility
实现Flutter无障碍功能
Contents
目录
UI Design and Styling
UI设计与样式
Design layouts to accommodate dynamic scaling and high visibility. Flutter automatically calculates font sizes based on OS-level accessibility settings.
- Font Scaling: Ensure layouts provide sufficient room to render all contents when font sizes are increased to their maximum OS settings. Avoid hardcoding fixed heights on text containers.
- Color Contrast: Maintain a contrast ratio of at least 4.5:1 for small text and 3.0:1 for large text (18pt+ regular or 14pt+ bold) to meet W3C standards.
- Tap Targets: Enforce a minimum tap target size of 48x48 logical pixels to accommodate users with limited dexterity.
设计布局以适应动态缩放和高可见性需求。Flutter会根据系统级无障碍设置自动计算字体大小。
- 字体缩放: 确保当字体大小调整到系统最大设置时,布局仍有足够空间显示所有内容。避免为文本容器硬编码固定高度。
- 颜色对比度: 小文本需保持至少4.5:1的对比度,大文本(18pt及以上常规字体或14pt及以上粗体)需保持至少3.0:1的对比度,以符合W3C标准。
- 点击目标: 强制设置最小点击目标尺寸为48x48逻辑像素,以适配操作不便的用户。
Accessibility Widgets
无障碍组件
Utilize Flutter's catalog of accessibility widgets to manipulate the semantics tree exposed to assistive technologies (like TalkBack or VoiceOver).
- : Use this to annotate the widget tree with a description of the meaning of the widgets. Assign specific roles using the
Semanticsenum (e.g., button, link, heading) when building custom components.SemanticsRole - : Wrap composite widgets to merge the semantics of all descendants into a single selectable node for screen readers.
MergeSemantics - : Use this to drop the semantics of all descendants, hiding redundant or purely decorative sub-widgets from accessibility tools.
ExcludeSemantics
利用Flutter的无障碍组件库来操作暴露给辅助技术(如TalkBack或VoiceOver)的语义树。
- : 使用该组件为组件树添加组件含义的描述。在构建自定义组件时,使用
Semantics枚举指定特定角色(如按钮、链接、标题)。SemanticsRole - : 包裹复合组件,将所有子组件的语义合并为一个可供屏幕阅读器选择的节点。
MergeSemantics - : 使用该组件移除所有子组件的语义,将冗余或纯装饰性子组件对无障碍工具隐藏。
ExcludeSemantics
Web Accessibility
Web无障碍
Flutter web renders UI on a single canvas, requiring a specialized DOM layer to expose structure to browsers.
- Enable Semantics: Web accessibility is disabled by default for performance. Users can enable it via an invisible button ().
aria-label="Enable accessibility" - Programmatic Enablement: If building a web-first application requiring default accessibility, force the semantics tree generation at startup.
- Semantic Roles: Rely on standard widgets (,
TabBar,MenuAnchor) for automatic ARIA role mapping. For custom components, explicitly assignTablevalues to ensure screen readers interpret the elements correctly.SemanticsRole
Flutter Web在单个画布上渲染UI,需要专门的DOM层来向浏览器暴露结构。
- 启用语义: Web无障碍默认处于禁用状态以提升性能。用户可通过一个隐形按钮()启用它。
aria-label="Enable accessibility" - 程序化启用: 如果构建的是默认需要无障碍支持的Web优先应用,可在启动时强制生成语义树。
- 语义角色: 依赖标准组件(、
TabBar、MenuAnchor)来自动映射ARIA角色。对于自定义组件,需显式指定Table值,确保屏幕阅读器能正确解析元素。SemanticsRole
Adaptive and Responsive Design
自适应与响应式设计
Differentiate between adaptive and responsive paradigms to build universal applications.
- Responsive Design: Adjust the placement, sizing, and reflowing of design elements to fit the available screen space.
- Adaptive Design: Select appropriate layouts (e.g., bottom navigation vs. side panel) and input mechanisms (e.g., touch vs. mouse/keyboard) to make the UI usable within the current device context. Design to the strengths of each form factor.
区分自适应与响应式设计范式,以构建通用应用。
- 响应式设计: 根据可用屏幕空间调整设计元素的位置、大小和回流方式。
- 自适应设计: 选择合适的布局(如底部导航 vs 侧边面板)和输入机制(如触摸 vs 鼠标/键盘),使UI在当前设备环境下可用。设计时要兼顾不同设备形态的优势。
Workflows
工作流程
Task Progress: Accessibility Implementation
任务进度:无障碍功能实现
Copy this checklist to track accessibility compliance during UI development:
- Verify all interactive elements have a minimum tap target of 48x48 pixels.
- Test layout with maximum OS font size settings to ensure no text clipping or overflow occurs.
- Validate color contrast ratios (4.5:1 for normal text, 3.0:1 for large text).
- Wrap custom interactive widgets in and assign the appropriate
Semantics.SemanticsRole - Group complex composite widgets using to prevent screen reader fatigue.
MergeSemantics - Hide decorative elements from screen readers using .
ExcludeSemantics - If targeting web, verify ARIA roles are correctly mapped and consider programmatic enablement of the semantics tree.
复制以下检查清单,在UI开发过程中跟踪无障碍合规性:
- 验证所有交互元素的最小点击目标为48x48像素。
- 在系统最大字体大小设置下测试布局,确保无文本被裁剪或溢出。
- 验证颜色对比度(常规文本4.5:1,大文本3.0:1)。
- 为自定义交互组件包裹并分配合适的
Semantics。SemanticsRole - 使用对复杂复合组件进行分组,避免屏幕阅读器用户产生疲劳。
MergeSemantics - 使用将装饰性元素对屏幕阅读器隐藏。
ExcludeSemantics - 如果面向Web平台,验证ARIA角色是否正确映射,并考虑程序化启用语义树。
Feedback Loop: Accessibility Validation
反馈循环:无障碍验证
Run this loop when finalizing a view or component:
- Run validator: Execute accessibility tests or use OS-level screen readers (VoiceOver/TalkBack) to navigate the view.
- Review errors: Identify unannounced interactive elements, trapped focus, or clipped text.
- Fix: Apply , adjust constraints, or modify colors. Repeat until the screen reader provides a clear, logical traversal of the UI.
Semantics
在完成视图或组件开发时执行以下循环:
- 运行验证工具: 执行无障碍测试或使用系统级屏幕阅读器(VoiceOver/TalkBack)导航视图。
- 检查错误: 识别未被播报的交互元素、焦点陷阱或被裁剪的文本。
- 修复: 应用、调整约束或修改颜色。重复操作,直到屏幕阅读器能清晰、逻辑地遍历UI。
Semantics
Examples
示例
Programmatic Web Accessibility Enablement
Web无障碍程序化启用
If targeting web and requiring accessibility by default, initialize the semantics binding before running the app.
dart
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter/foundation.dart';
void main() {
if (kIsWeb) {
SemanticsBinding.instance.ensureSemantics();
}
runApp(const MyApp());
}如果面向Web平台且默认需要无障碍支持,在运行应用前初始化语义绑定。
dart
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter/foundation.dart';
void main() {
if (kIsWeb) {
SemanticsBinding.instance.ensureSemantics();
}
runApp(const MyApp());
}Custom Component Semantics
自定义组件语义
If building a custom widget that acts as a list item, explicitly define its semantic role so assistive technologies and web ARIA mappings interpret it correctly.
dart
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
class CustomListItem extends StatelessWidget {
final String text;
const CustomListItem({super.key, required this.text});
Widget build(BuildContext context) {
return Semantics(
role: SemanticsRole.listItem,
label: text,
child: Padding(
padding: const EdgeInsets.all(12.0), // Ensures > 48px tap target if interactive
child: Text(
text,
style: const TextStyle(fontSize: 16), // Ensure contrast ratio > 4.5:1
),
),
);
}
}如果构建的自定义组件用作列表项,需显式定义其语义角色,确保辅助技术和Web ARIA映射能正确解析它。
dart
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
class CustomListItem extends StatelessWidget {
final String text;
const CustomListItem({super.key, required this.text});
Widget build(BuildContext context) {
return Semantics(
role: SemanticsRole.listItem,
label: text,
child: Padding(
padding: const EdgeInsets.all(12.0), // Ensures > 48px tap target if interactive
child: Text(
text,
style: const TextStyle(fontSize: 16), // Ensure contrast ratio > 4.5:1
),
),
);
}
}