构建 OpenHarmony 文本高亮关键词标记器:用纯字符串操作实现智能标注

一、为什么需要"文本高亮标记器"?

在 OpenHarmony 的多设备协同场景中,用户常需快速定位信息:

  • 在长篇会议纪要中查找"决策";
  • 在设备日志中定位"ERROR";
  • 在跨端共享文档中标记重点词汇。

虽然系统级搜索功能存在,但应用内高亮能提供更沉浸、更即时的体验------无需跳转,一眼锁定目标。

然而,许多开发者误以为高亮需依赖富文本库或 HTML 渲染。实际上,仅用 Flutter 内置的 Text.richTextSpan,即可实现高效、安全、可定制的关键词高亮。

本文将构建一个极简页面:「文本高亮关键词标记器」。它只包含:

  • 一个多行文本输入框(用于粘贴原文);
  • 一个单行输入框(用于输入关键词);
  • 一个"高亮"按钮;
  • 一个只读结果显示区(自动高亮匹配词)。

所有逻辑基于字符串分割与重组,无正则、无插件、无性能隐患。


二、完整可运行代码

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '文本高亮器',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed(seedColor: Colors.green)),
      home: const HighlightTextPage(),
    );
  }
}

class HighlightTextPage extends StatefulWidget {
  const HighlightTextPage({super.key});

  @override
  State<HighlightTextPage> createState() => _HighlightTextPageState();
}

class _HighlightTextPageState extends State<HighlightTextPage> {
  final _textController = TextEditingController();
  final _keywordController = TextEditingController();
  List<TextSpan> _highlightedSpans = [const TextSpan(text: '请输入文本和关键词,点击"高亮"')];

  void _highlightText() {
    final text = _textController.text;
    final keyword = _keywordController.text.trim();

    if (keyword.isEmpty) {
      setState(() {
        _highlightedSpans = [TextSpan(text: text.isEmpty ? '请输入文本' : text)];
      });
      return;
    }

    final parts = text.split(keyword);
    final spans = <TextSpan>[];
    for (int i = 0; i < parts.length; i++) {
      spans.add(TextSpan(text: parts[i]));
      if (i < parts.length - 1) {
        spans.add(TextSpan(
          text: keyword,
          style: const TextStyle(backgroundColor: Colors.yellow, fontWeight: FontWeight.bold),
        ));
      }
    }
    setState(() {
      _highlightedSpans = spans;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('文本高亮标记器')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            TextField(controller: _textController, maxLines: 3, decoration: const InputDecoration(labelText: '输入原文')),
            TextField(controller: _keywordController, decoration: const InputDecoration(labelText: '输入关键词')),
            const SizedBox(height: 12),
            ElevatedButton(onPressed: _highlightText, child: const Text('高亮')),
            const SizedBox(height: 16),
            Expanded(
              child: SingleChildScrollView(
                child: RichText(
                  text: TextSpan(style: DefaultTextStyle.of(context).style, children: _highlightedSpans),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

✅ 此代码仅使用 Flutter 内置组件TextField, RichText, TextSpan 等),无需任何权限或外部依赖,在 OpenHarmony DevEco 模拟器中可直接运行。输入文本和关键词,点击"高亮",匹配词将以黄色背景加粗显示。


三、核心思想:用字符串分割实现高亮

高亮的本质是将原文按关键词切分为若干段,然后在每段之间插入"已样式化的关键词"。

例如:

原文:"OpenHarmony 是开源的"

关键词:"开源"

分割结果:["OpenHarmony 是", "的"]

重组后:[普通文本 "OpenHarmony 是"] + [高亮文本 "开源"] + [普通文本 "的"]

这种方法简单、高效、可预测,避免了正则表达式的复杂性和潜在安全风险(如 ReDoS)。


四、高亮逻辑实现:

我们首先看核心高亮算法:

dart 复制代码
void _highlightText() {
  final text = _textController.text;
  final keyword = _keywordController.text.trim();

  if (keyword.isEmpty) {
    setState(() {
      _highlightedSpans = [TextSpan(text: text.isEmpty ? '请输入文本' : text)];
    });
    return;
  }

  final parts = text.split(keyword);
  final spans = <TextSpan>[];
  for (int i = 0; i < parts.length; i++) {
    spans.add(TextSpan(text: parts[i]));
    if (i < parts.length - 1) {
      spans.add(TextSpan(
        text: keyword,
        style: const TextStyle(backgroundColor: Colors.yellow, fontWeight: FontWeight.bold),
      ));
    }
  }
  setState(() {
    _highlightedSpans = spans;
  });
}


这段代码实现了安全、高效的关键词高亮

  • 空值处理:若关键词为空,直接显示原文或提示,避免无效操作;
  • text.split(keyword) :利用 Dart 内置字符串方法,按关键词分割;
    • 若关键词不存在,parts 长度为 1,循环中不会添加高亮项;
    • 若存在 N 次,parts 长度为 N+1,循环中会插入 N 次高亮关键词;
  • TextSpan 构建
    • 普通文本使用默认样式;
    • 关键词使用黄色背景 + 加粗,视觉突出;
  • setState 更新 :触发 RichText 重建,显示新结果。

💡 此方法区分大小写 。若需忽略大小写,可先将 textkeyword 转为小写进行分割,但保留原文大小写用于显示------本文为简洁未实现,但扩展容易。


五、富文本渲染与布局:

再看 UI 渲染部分:

dart 复制代码
Expanded(
  child: SingleChildScrollView(
    child: RichText(
      text: TextSpan(style: DefaultTextStyle.of(context).style, children: _highlightedSpans),
    ),
  ),
)

这里展示了 RichText 的正确使用方式

  • TextSpan 样式继承
    • 外层 TextSpan 设置 style: DefaultTextStyle.of(context).style,确保普通文本继承当前主题字体、颜色;
    • 内层高亮 TextSpan 仅覆盖 backgroundColorfontWeight,其余属性(如字号、颜色)自动继承;
  • 可滚动容器
    • Expanded 占据剩余空间;
    • SingleChildScrollView 允许结果区域垂直滚动,避免内容溢出;
  • 响应式布局
    • 输入框固定高度,结果区自适应,适配不同屏幕尺寸。

📌 值得注意的是,RichText 不支持 SelectableText 的选择功能 。若需可选文本,可用 SelectableText.rich 替代(Flutter 3.0+ 支持),但 OpenHarmony 模拟器兼容性需验证。本文选用 RichText 以确保最大兼容性。


六、为何这个工具具有广泛适用性?

1. 开发者调试

  • 快速验证日志中的关键字段;
  • 模拟搜索结果高亮效果。

2. 终端用户场景

  • 在共享笔记中标记重点;
  • 在设备说明文档中查找参数。

3. 教学价值

  • 演示 TextSpanRichText 的组合使用;
  • 展示字符串操作在 UI 中的直接应用;
  • 体现"状态驱动视图"的 Flutter 核心思想。

更重要的是,它完全运行在应用沙盒内,不读取文件、不访问网络、不申请权限,符合 OpenHarmony 安全规范。


七、工程优化建议

1. 性能考虑

  • 对超长文本(>10KB),splitTextSpan 列表可能影响性能;
  • 可限制输入长度:TextField(maxLength: 1000)

2. 功能扩展(保持简洁)

  • 多关键词高亮 :用 List<String> 存储关键词,嵌套分割;
  • 高亮颜色自定义:增加颜色选择器;
  • 清除高亮 :重置 _highlightedSpans

但本文坚持"单一功能极致简化",未加入额外复杂度。


八、结语:用基础能力,解决真实问题

本文的页面仅 69 行代码,却展示了如何用 Flutter 最基础的字符串和文本组件,实现一个实用、直观、安全的功能。它证明了:伟大的用户体验,往往源于对基础能力的深度掌握,而非对复杂框架的依赖

在 OpenHarmony 的跨端开发中,我们应始终铭记:稳定、兼容、简洁,比炫技更重要

让我们继续用这样的微创新,让技术真正服务于人。

🌐 欢迎加入开源鸿蒙跨平台社区

https://openharmonycrossplatform.csdn.net/

在这里,您将获得:

  • OpenHarmony 富文本最佳实践;
  • Flutter 字符串处理与 UI 映射技巧;
  • 无依赖实用组件模板。

用基础,成就可靠。

相关推荐
b2077212 小时前
Flutter for OpenHarmony 身体健康状况记录App实战 - 体重趋势实现
python·flutter·harmonyos
2501_948120152 小时前
Java实现的SSL/TLS协议通信系统
java·开发语言·ssl
b2077212 小时前
Flutter for OpenHarmony 身体健康状况记录App实战 - 个人中心实现
android·java·python·flutter·harmonyos
你这个代码我看不懂2 小时前
Vue子父组件.sync
javascript·vue.js·ecmascript
灰灰勇闯IT2 小时前
Flutter for OpenHarmony:布局组件实战指南
前端·javascript·flutter
cici158742 小时前
基于MATLAB的TERCOM算法实现与优化
开发语言·matlab
天上飞的粉红小猪2 小时前
c++的IO流
开发语言·c++
学嵌入式的小杨同学2 小时前
【嵌入式 Linux 实战 1】Ubuntu 环境搭建 + 目录结构详解:嵌入式开发入门第一步
linux·c语言·开发语言·数据结构·vscode·vim·unix