flutter 高亮字符,富文本

高亮【keywords】关键字

javascript 复制代码
import 'package:flutter/material.dart';

/// 富文本,高亮字符
class HighlightedText extends StatelessWidget {
  final String text;
  final List<String> keywords;  //关键字
  final Color highlightColor;    //高亮颜色
  final TextStyle normalStyle;   //正常字体样式
  final TextStyle highlightStyle;  //高亮字体样式
  final int? maxLines;
  final TextOverflow overflow;
  final TextAlign textAlign;

  const HighlightedText({
    super.key,
    required this.text,
    required this.keywords,
    this.highlightColor = Colors.red,
    this.normalStyle = const TextStyle(),
    this.highlightStyle = const TextStyle(),
    this.textAlign = TextAlign.start,
    this.maxLines,
    this.overflow = TextOverflow.ellipsis,
  });

  @override
  Widget build(BuildContext context) {
    /// 如果没有关键词,直接返回普通文本
    if (keywords.isEmpty || text.isEmpty) {
      return Text(text, style: normalStyle);
    }

    /// 过滤掉空关键词
    final validKeywords = keywords.where((keyword) => keyword.isNotEmpty).toList();
    if (validKeywords.isEmpty) {
      return Text(text, style: normalStyle);
    }

    /// 创建正则表达式来匹配所有关键词(按长度降序排列,避免短关键词优先匹配)
    validKeywords.sort((a, b) => b.length.compareTo(a.length));

    final pattern = RegExp(
      validKeywords.map((keyword) => RegExp.escape(keyword)).join('|'),
      caseSensitive: false,
    );

    final matches = pattern.allMatches(text);
    final spans = <TextSpan>[];
    int lastEnd = 0;

    /// 遍历所有匹配项
    for (final match in matches) {
      /// 添加匹配前的普通文本
      if (match.start > lastEnd) {
        spans.add(TextSpan(
          text: text.substring(lastEnd, match.start),
          style: normalStyle,
        ));
      }

      /// 获取匹配的文本
      final matchedText = text.substring(match.start, match.end);

      /// 添加高亮的关键词 - 修复样式合并问题
      spans.add(TextSpan(
        text: matchedText,
        style: highlightStyle.merge(TextStyle(
          color: highlightColor,
          fontWeight: FontWeight.bold,
        )),
      ));

      lastEnd = match.end;
    }

    /// 添加剩余的普通文本
    if (lastEnd < text.length) {
      spans.add(TextSpan(
        text: text.substring(lastEnd),
        style: normalStyle,
      ));
    }

    /// 如果没有匹配到任何关键词,返回普通文本
    if (spans.isEmpty) {
      return Text(text, style: normalStyle);
    }

    return RichText(
      maxLines: maxLines,
      overflow: overflow,
      textAlign: textAlign,
      text: TextSpan(children: spans),
    );
  }
}
相关推荐
「、皓子~3 小时前
海狸IM 2.1 正式发布
flutter·微服务·golang·electron·开源软件·im·海狸im
里欧跑得慢4 小时前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
恋猫de小郭4 小时前
AI 时代,一个优化 Flutter 的重复代码工具 Deslop
android·前端·flutter
ljt27249606611 天前
Flutter笔记--envied
前端·笔记·flutter
加农炮手Jinx2 天前
Flutter for OpenHarmony 实战:flutter_animate 声明式动画让 UI 灵动如原生
flutter·ui·华为·harmonyos·鸿蒙
里欧跑得慢2 天前
Flutter 像素级还原:设计稿到代码的视觉无损转换技巧
前端·css·flutter·web
里欧跑得慢2 天前
Flutter 三方库 function_tree — 鸿蒙应用开发中的动态数学公式解析与计算神器,实现鸿蒙深度适配下的复杂函数逻辑运行时求值实战(适配鸿蒙 HarmonyOS Next ohos)
android·前端·安全·flutter·华为·harmonyos
吃西瓜的年年2 天前
vue3原理思维导图
vue.js·笔记·flutter
GitLqr3 天前
从代码复用走向生态:Flutter Dart Package 实战全指南
flutter·全栈·dart