flutter-improving-accessibility

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Implementing 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).
  • Semantics
    : Use this to annotate the widget tree with a description of the meaning of the widgets. Assign specific roles using the
    SemanticsRole
    enum (e.g., button, link, heading) when building custom components.
  • MergeSemantics
    : Wrap composite widgets to merge the semantics of all descendants into a single selectable node for screen readers.
  • ExcludeSemantics
    : Use this to drop the semantics of all descendants, hiding redundant or purely decorative sub-widgets from accessibility tools.
利用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
    ,
    Table
    ) for automatic ARIA role mapping. For custom components, explicitly assign
    SemanticsRole
    values to ensure screen readers interpret the elements correctly.
Flutter Web在单个画布上渲染UI,需要专门的DOM层来向浏览器暴露结构。
  • 启用语义: Web无障碍默认处于禁用状态以提升性能。用户可通过一个隐形按钮(
    aria-label="Enable accessibility"
    )启用它。
  • 程序化启用: 如果构建的是默认需要无障碍支持的Web优先应用,可在启动时强制生成语义树。
  • 语义角色: 依赖标准组件(
    TabBar
    MenuAnchor
    Table
    )来自动映射ARIA角色。对于自定义组件,需显式指定
    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
    Semantics
    and assign the appropriate
    SemanticsRole
    .
  • Group complex composite widgets using
    MergeSemantics
    to prevent screen reader fatigue.
  • 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:
  1. Run validator: Execute accessibility tests or use OS-level screen readers (VoiceOver/TalkBack) to navigate the view.
  2. Review errors: Identify unannounced interactive elements, trapped focus, or clipped text.
  3. Fix: Apply
    Semantics
    , adjust constraints, or modify colors. Repeat until the screen reader provides a clear, logical traversal of the UI.
在完成视图或组件开发时执行以下循环:
  1. 运行验证工具: 执行无障碍测试或使用系统级屏幕阅读器(VoiceOver/TalkBack)导航视图。
  2. 检查错误: 识别未被播报的交互元素、焦点陷阱或被裁剪的文本。
  3. 修复: 应用
    Semantics
    、调整约束或修改颜色。重复操作,直到屏幕阅读器能清晰、逻辑地遍历UI。

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
        ),
      ),
    );
  }
}