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

Flutter中实现点击文本特定词汇播放对应音效的方案

解决Flutter故事文本中特定词汇的点击音效问题

你觉得TextSpan手动拆分太繁琐?可以试试自动解析带标记的文本+批量生成可点击TextSpan的方式,不用一个个手动拼接,效率高很多,具体实现步骤如下:

1. 先维护词汇与音效的映射表

把需要触发音效的词汇和对应的音效路径关联起来,方便后续快速匹配:

final Map<String, String> soundMapping = {
  'honking': 'assets/sounds/honking.mp3',
  'rustling': 'assets/sounds/rustling.mp3',
  // 后续新增词汇直接在这里加就行
};

2. 写一个文本解析工具函数

针对你用<strong>标记的特定词汇,用正则自动拆分文本,生成对应的TextSpan列表:

List<TextSpan> parseStoryContent(String rawText) {
  final spans = <TextSpan>[];
  final tagRegex = RegExp(r'<strong>(.*?)<\/strong>');
  int lastPosition = 0;

  // 遍历所有带标记的词汇
  for (final match in tagRegex.allMatches(rawText)) {
    // 添加标记前的普通文本
    if (match.start > lastPosition) {
      spans.add(TextSpan(text: rawText.substring(lastPosition, match.start)));
    }
    // 提取标记里的词汇
    final targetWord = match.group(1)!;
    // 生成带点击事件的TextSpan
    spans.add(TextSpan(
      text: targetWord,
      style: const TextStyle(
        color: Colors.blue,
        decoration: TextDecoration.underline,
        fontSize: 16,
      ),
      recognizer: TapGestureRecognizer()
        ..onTap = () {
          // 这里直接调用你已有的音效播放方法
          playSound(soundMapping[targetWord]!);
        },
    ));
    lastPosition = match.end;
  }

  // 添加最后一段未标记的文本
  if (lastPosition < rawText.length) {
    spans.add(TextSpan(text: rawText.substring(lastPosition)));
  }

  return spans;
}

3. 在UI中使用解析后的结果

用RichText组件渲染解析好的TextSpan列表:

RichText(
  text: TextSpan(
    style: const TextStyle(color: Colors.black, fontSize: 16),
    children: parseStoryContent("Mimi和Sami听到了<strong>honking</strong>声"),
  ),
  padding: const EdgeInsets.all(16),
)

额外优化点

  • 如果后续换了标记(比如不用<strong>改用其他标签),只需要修改正则表达式即可;
  • 可以把解析函数封装成全局工具类,整个项目的故事文本都能复用;
  • 要是需要给可点击词汇加点击反馈(比如变色),可以在点击事件里配合状态管理做样式切换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:05:31