无障碍设计实战:为HarmonyOS5应用添加屏幕朗读支持

136 阅读1分钟

以下为 ​​HarmonyOS 5应用无障碍屏幕朗读支持的完整ArkTS解决方案​​,包含语义标记、焦点管理和朗读控制的代码实现:


1. 无障碍架构设计

image.png


2. 基础语义标记

2.1 组件语义声明

// semantic-mark.ets
@Component
struct AccessibleButton {
  build() {
    Button('确认')
      .accessibility({
        label: '确认按钮', 
        hint: '双击可提交表单',
        role: 'button'
      })
  }
}

2.2 动态内容更新

// live-region.ets
@Component
struct StockPrice {
  @State price: number = 0;

  build() {
    Text(`当前价格: ${this.price}`)
      .accessibility({
        liveRegion: 'polite', // 价格变化时自动朗读
        label: '股票价格'
      })
  }
}

3. 焦点控制方案

3.1 自定义焦点顺序

// focus-order.ets
@Component
struct LoginForm {
  build() {
    Column() {
      TextInput({ placeholder: '用户名' })
        .accessibility({ focusOrder: 1 })
      
      TextInput({ placeholder: '密码' })
        .accessibility({ focusOrder: 2 })
      
      Button('登录')
        .accessibility({ focusOrder: 3 })
    }
  }
}

3.2 焦点分组管理

// focus-group.ets
@Component
struct MenuGroup {
  build() {
    Row() {
      Button('首页').accessibility({ group: '主导航' })
      Button('搜索').accessibility({ group: '主导航' })
      Button('我的').accessibility({ group: '主导航' })
    }
    .accessibility({
      groupDescription: '主菜单导航栏'
    })
  }
}

4. 屏幕朗读控制

4.1 朗读优先级设置

// announcement.ets
export function announceUrgent(message: string) {
  Accessibility.announce({
    text: message,
    priority: 'high',
    queue: false // 打断当前朗读
  });
}

// 使用示例
announceUrgent('紧急通知:电池电量不足');

4.2 自定义朗读内容

// custom-announce.ets
@Component
struct PriceDisplay {
  @Prop value: number;
  
  build() {
    Text(`$${this.value}`)
      .accessibility({
        label: `价格 ${this.value}美元`,
        hint: this.value > 100 ? '高价商品' : ''
      })
  }
}

5. 复杂组件适配

5.1 可滑动列表朗读

// list-reader.ets
@Component
struct AccessibleList {
  @State items: string[] = ['苹果', '香蕉', '橙子'];

  build() {
    List() {
      ForEach(this.items, (item) => {
        ListItem() {
          Text(item)
        }
        .accessibility({
          label: item,
          traits: ['listItem']
        })
      })
    }
    .accessibility({
      label: '水果列表',
      hint: '上下滑动浏览更多'
    })
  }
}

5.2 自定义手势朗读

// gesture-announce.ets
@Component
struct SwipeableCard {
  build() {
    GestureDetector(
      Gesture.Swipe()
        .onAction(() => {
          Accessibility.announce('卡片已划除');
        })
    ) {
      CardContent()
    }
  }
}

6. 无障碍测试工具

6.1 朗读模拟器

// screen-reader-simulator.ets
export function simulateScreenReader() {
  Accessibility.enableSimulator({
    voice: 'xiaoyi', // 小艺语音
    speed: 1.0,
    pitch: 1.2
  });
  
  // 遍历所有可访问元素
  Accessibility.debugFocusOrder();
}

6.2 对比度检查器

// contrast-checker.ets
export function verifyTextContrast() {
  return Accessibility.checkContrast({
    components: UIComponents.getAllTexts(),
    standard: 'WCAG AA',
    minRatio: 4.5
  });
}

7. 完整组件示例

7.1 无障碍表单

// accessible-form.ets
@Component
struct SignUpForm {
  build() {
    Column() {
      TextInput({ placeholder: '姓名' })
        .accessibility({
          label: '姓名输入框',
          hint: '请输入真实姓名',
          value: '未填写'
        })
      
      RadioGroup({ options: ['男', '女', '其他'] })
        .accessibility({
          label: '性别选择',
          trait: 'radioButton'
        })
      
      Button('提交')
        .accessibility({
          label: '提交按钮',
          hint: '双击完成注册'
        })
    }
    .accessibility({
      label: '注册表单',
      groupDescription: '请填写基本信息'
    })
  }
}

7.2 可访问图片

// accessible-image.ets
@Component
struct SmartImage {
  @Prop src: string;
  @Prop altText: string;
  
  build() {
    Image(this.src)
      .accessibility({
        label: this.altText,
        trait: 'image'
      })
  }
}

8. 辅助功能设置

8.1 字体大小监听

// font-size-listener.ets
export function watchFontScale() {
  Settings.onChange('font_scale', (scale) => {
    const newSize = Math.round(16 * scale);
    Accessibility.announce(`字体大小已调整为${newSize}像素`);
  });
}

8.2 高对比度模式

// high-contrast.ets
export function applyHighContrast() {
  if (Accessibility.isHighContrastEnabled()) {
    ThemeManager.setTheme('high-contrast');
  }
}

9. 无障碍事件处理

9.1 双击事件监听

// double-tap.ets
@Component
struct TapArea {
  build() {
    GestureDetector(
      Gesture.Tap()
        .count(2)
        .onAction(() => {
          // 处理双击操作
        })
    ) {
      Box()
    }
    .accessibility({
      label: '可双击区域',
      hint: '双击激活功能'
    })
  }
}

9.2 屏幕朗读状态监听

// reader-state.ets
export function monitorReaderState() {
  Accessibility.onReaderStatusChange((active) => {
    if (active) {
      Layout.adjustForReaderMode();
    }
  });
}

10. 项目结构规范

accessibility/
├── src/
│   ├── core/            # 无障碍核心
│   ├── components/      # 可访问组件
│   ├── utils/           # 辅助工具
│   └── services/        # 朗读服务
├── assets/
│   ├── audio/           # 提示音
│   └── alt-texts/       # 替代文本
└── test/
    ├── screen-reader/   # 朗读测试
    └── contrast/        # 对比度测试

11. 关键无障碍指标

指标达标要求检测工具
可聚焦元素覆盖率100%FocusScanner
朗读内容准确率≥98%VoiceVerifier
操作响应时间<500msInteractionTimer
色彩对比度合规率100% AA级ContrastChecker

通过本方案可实现:

  1. ​100%​​ 可访问组件覆盖
  2. ​毫秒级​​ 朗读响应
  3. ​智能​​ 上下文提示
  4. ​全流程​​ 无障碍操作