You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Autocomplete在showGeneralDialog中VoiceOver/Talkback无障碍交互异常

Dialog中Autocomplete组件的无障碍支持修复方案

问题场景

使用Autocomplete组件实现输入补全,功能逻辑正常,但当组件嵌入showGeneralDialog弹出的对话框时,VoiceOver/Talkback无法正常操作下拉菜单:

  • 无法通过屏幕阅读器选中下拉项,双击也触发不了onSelected回调
  • 屏幕阅读器无法朗读下拉项的内容

问题原因

showGeneralDialog默认的无障碍容器配置未正确纳入Autocomplete的下拉菜单,导致下拉项无法被屏幕阅读器识别为可交互元素,焦点管理也出现异常。

修复方案

1. 给Dialog设置无障碍容器属性

用Semantics组件包裹Dialog的根内容,标记为独立的无障碍容器,确保下拉菜单能被识别为容器的子元素:

pageBuilder: (context, animation, secondaryAnimation) {
  return Semantics(
    container: true,
    label: '搜索对话框', // 给对话框设置无障碍标签
    child: Scaffold(
      // ... 原有Dialog内容
    ),
  );
}

2. 自定义下拉选项的无障碍语义

重写Autocomplete的optionsViewBuilder,给每个下拉选项添加Semantics组件,明确设置可点击属性和朗读标签:

optionsViewBuilder: (context, onSelected, options) {
  return Align(
    alignment: Alignment.topLeft,
    child: Material(
      elevation: 4.0,
      child: SizedBox(
        height: 200,
        width: 300,
        child: ListView.builder(
          padding: EdgeInsets.zero,
          itemCount: options.length,
          itemBuilder: (context, index) {
            final option = options.elementAt(index);
            return Semantics(
              label: option, // 指定屏幕阅读器朗读的文本
              button: true, // 标记为可点击按钮
              onTap: () => onSelected(option),
              child: ListTile(
                title: Text(option),
                onTap: () => onSelected(option),
              ),
            );
          },
        ),
      ),
    ),
  );
}

3. 确保焦点正确流转

确保Dialog的barrierDismissible设置合理,同时Autocomplete的fieldViewBuilder中正确传递focusNode,避免焦点被Dialog拦截。

完整修复代码示例

showGeneralDialog(
  context: context,
  pageBuilder: (context, animation, secondaryAnimation) {
    return Semantics(
      container: true,
      label: '搜索对话框',
      child: Scaffold(
        backgroundColor: Colors.white,
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              if (textEditingValue.text.isEmpty) {
                return const Iterable<String>.empty();
              }
              return ['Apple', 'Banana', 'Orange']
                  .where((option) => option.toLowerCase().contains(textEditingValue.text.toLowerCase()));
            },
            displayStringForOption: (option) => option,
            onSelected: (String selection) {
              debugPrint('选中了:$selection');
            },
            fieldViewBuilder: (context, textEditingController, focusNode, onFieldSubmitted) {
              return TextField(
                controller: textEditingController,
                focusNode: focusNode,
                decoration: const InputDecoration(
                  labelText: '搜索',
                  border: OutlineInputBorder(),
                ),
                onSubmitted: onFieldSubmitted,
              );
            },
            optionsViewBuilder: (context, onSelected, options) {
              return Align(
                alignment: Alignment.topLeft,
                child: Material(
                  elevation: 4.0,
                  child: SizedBox(
                    height: 200,
                    width: 300,
                    child: ListView.builder(
                      padding: EdgeInsets.zero,
                      itemCount: options.length,
                      itemBuilder: (context, index) {
                        final option = options.elementAt(index);
                        return Semantics(
                          label: option,
                          button: true,
                          onTap: () => onSelected(option),
                          child: ListTile(
                            title: Text(option),
                            onTap: () => onSelected(option),
                          ),
                        );
                      },
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
  },
);

内容的提问来源于stack exchange,提问作者BLKKKBVSIK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:45:37