Flutter for OpenHarmony 实战:搜索关键词高亮:使用 RichText和字符串匹配
在移动开发领域,我们总是面临着选择与适配。今天,你的Flutter应用在Android和iOS上运行良好,明天可能就需要考虑一个新的平台:HarmonyOS(鸿蒙)。这不是一道选答题,而是很多团队正在面对的现实。Flutter的优势显而易见——编写一套代码,就能在两个主要平台上运行,开发体验流畅。而鸿蒙代表的是下一个时代的互联生态,它不仅仅是手机系统,更着眼于未来全场景的体验。
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
前言:跨生态开发的新机遇
在移动开发领域,我们总是面临着选择与适配。今天,你的Flutter应用在Android和iOS上运行良好,明天可能就需要考虑一个新的平台:HarmonyOS(鸿蒙)。这不是一道选答题,而是很多团队正在面对的现实。
Flutter的优势显而易见——编写一套代码,就能在两个主要平台上运行,开发体验流畅。而鸿蒙代表的是下一个时代的互联生态,它不仅仅是手机系统,更着眼于未来全场景的体验。将现有的Flutter应用适配到鸿蒙,听起来像是一个“跨界”任务,但它本质上是一次有价值的技术拓展:让产品触达更多用户,也让技术栈覆盖更广。
不过,这条路走起来并不像听起来那么简单。Flutter和鸿蒙,从底层的架构到上层的工具链,都有着各自的设计逻辑。开发过程中会遇到一些具体的问题:代码如何组织?原有的功能在鸿蒙上如何实现?那些平台特有的能力该怎么调用?更实际的是,从编译打包到上架部署,整个流程都需要重新摸索。
本文旨在将这些我们趟过的路、踩过的坑,清晰地摊开给你看。我们不会只停留在“怎么做”,还会聊到“为什么得这么做”,以及“如果出了问题该往哪想”。这更像是一份实战笔记,源自真实的项目经验,聚焦于那些真正卡住过我们的环节。
无论你是在为一个成熟产品寻找新的落地平台,还是从一开始就希望构建能面向多端的应用,这里的思路和解决方案都能提供直接的参考。理解了两套体系之间的异同,掌握了关键的衔接技术,不仅能完成这次迁移,更能积累起应对未来技术变化的能力。
混合工程结构深度解析
项目目录架构
当Flutter项目集成鸿蒙支持后,典型的项目结构会发生显著变化。以下是经过ohos_flutter插件初始化后的项目结构:
my_flutter_harmony_app/
├── lib/ # Flutter业务代码(基本不变)
│ ├── main.dart # 应用入口
│ ├── home_page.dart # 首页
│ └── utils/
│ └── platform_utils.dart # 平台工具类
├── pubspec.yaml # Flutter依赖配置
├── ohos/ # 鸿蒙原生层(核心适配区)
│ ├── entry/ # 主模块
│ │ └── src/main/
│ │ ├── ets/ # ArkTS代码
│ │ │ ├── MainAbility/
│ │ │ │ ├── MainAbility.ts # 主Ability
│ │ │ │ └── MainAbilityContext.ts
│ │ │ └── pages/
│ │ │ ├── Index.ets # 主页面
│ │ │ └── Splash.ets # 启动页
│ │ ├── resources/ # 鸿蒙资源文件
│ │ │ ├── base/
│ │ │ │ ├── element/ # 字符串等
│ │ │ │ ├── media/ # 图片资源
│ │ │ │ └── profile/ # 配置文件
│ │ │ └── en_US/ # 英文资源
│ │ └── config.json # 应用核心配置
│ ├── ohos_test/ # 测试模块
│ ├── build-profile.json5 # 构建配置
│ └── oh-package.json5 # 鸿蒙依赖管理
└── README.md
目录
展示效果图片
flutter 实时预览 效果展示
运行到鸿蒙虚拟设备中效果展示
功能代码实现
搜索关键词高亮组件
实现细节
搜索关键词高亮组件是一个使用RichText和字符串匹配实现的Flutter组件,用于实时高亮显示文本中的搜索关键词。该组件通过以下技术实现:
- 实时搜索:用户输入关键词时,实时高亮显示匹配的文本
- 大小写不敏感:搜索匹配时忽略大小写,提高用户体验
- 预设关键词:提供常用关键词按钮,方便用户快速搜索
- 美观的UI设计:采用现代化的搜索框设计和高亮效果
核心代码实现
组件结构
import 'package:flutter/material.dart';
class SearchHighlight extends StatefulWidget {
final double width;
final double height;
final Color backgroundColor;
final Color primaryColor;
final Color highlightColor;
const SearchHighlight({
Key? key,
this.width = double.infinity,
this.height = 400,
this.backgroundColor = Colors.white,
this.primaryColor = Colors.blue,
this.highlightColor = Colors.yellow,
}) : super(key: key);
State<SearchHighlight> createState() => _SearchHighlightState();
}
class _SearchHighlightState extends State<SearchHighlight> {
TextEditingController _searchController = TextEditingController();
String _searchText = '';
String _content = 'Flutter是谷歌推出的开源移动应用开发框架,使用Dart语言开发,支持跨平台开发。Flutter的优势在于热重载、丰富的UI组件和高性能。OpenHarmony是华为推出的开源操作系统,支持多种设备类型。Flutter for OpenHarmony允许开发者使用Flutter开发OpenHarmony应用。';
void dispose() {
_searchController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16.0),
color: widget.backgroundColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 标题
Text(
'搜索关键词高亮',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: widget.primaryColor,
),
),
SizedBox(height: 20),
// 搜索输入框
Container(
width: double.infinity,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.grey[200],
),
child: Row(
children: [
SizedBox(width: 16),
Icon(
Icons.search,
color: Colors.grey[600],
),
SizedBox(width: 12),
Expanded(
child: TextField(
controller: _searchController,
onChanged: (value) {
setState(() {
_searchText = value;
});
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: '输入关键词搜索',
hintStyle: TextStyle(
color: Colors.grey[500],
),
),
),
),
SizedBox(width: 16),
],
),
),
SizedBox(height: 20),
// 内容展示区域
Container(
width: double.infinity,
padding: EdgeInsets.all(16.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(
width: 1,
color: Colors.grey[300] ?? Colors.grey,
),
),
child: _buildHighlightedText(),
),
SizedBox(height: 20),
// 预设关键词
Text('预设关键词'),
SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 8,
alignment: WrapAlignment.center,
children: [
'Flutter',
'OpenHarmony',
'Dart',
'跨平台',
'开源',
].map((keyword) {
return GestureDetector(
onTap: () {
setState(() {
_searchText = keyword;
_searchController.text = keyword;
});
},
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: _searchText == keyword
? widget.primaryColor
: Colors.grey[200],
),
child: Text(
keyword,
style: TextStyle(
color: _searchText == keyword
? Colors.white
: Colors.black87,
),
),
),
);
}).toList(),
),
SizedBox(height: 20),
// 操作提示
Text(
'提示:输入关键词或点击预设关键词查看高亮效果',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
),
);
}
Widget _buildHighlightedText() {
if (_searchText.isEmpty) {
return Text(
_content,
style: TextStyle(
fontSize: 16,
color: Colors.black87,
height: 1.5,
),
);
}
List<TextSpan> spans = [];
int start = 0;
int index = _content.toLowerCase().indexOf(_searchText.toLowerCase(), start);
while (index != -1) {
// 添加搜索词之前的文本
spans.add(TextSpan(
text: _content.substring(start, index),
style: TextStyle(
fontSize: 16,
color: Colors.black87,
height: 1.5,
),
));
// 添加高亮的搜索词
spans.add(TextSpan(
text: _content.substring(index, index + _searchText.length),
style: TextStyle(
fontSize: 16,
color: Colors.black87,
backgroundColor: widget.highlightColor,
fontWeight: FontWeight.bold,
height: 1.5,
),
));
// 更新起始位置
start = index + _searchText.length;
index = _content.toLowerCase().indexOf(_searchText.toLowerCase(), start);
}
// 添加剩余的文本
spans.add(TextSpan(
text: _content.substring(start),
style: TextStyle(
fontSize: 16,
color: Colors.black87,
height: 1.5,
),
));
return RichText(
text: TextSpan(children: spans),
);
}
}
使用方法
基本使用
import 'components/search_highlight.dart';
// 在需要的地方使用
SearchHighlight()
自定义配置
// 自定义宽度、高度和颜色
SearchHighlight(
width: 300,
height: 400,
backgroundColor: Colors.grey[100]!,
primaryColor: Colors.green,
highlightColor: Colors.yellowAccent,
)
在主应用中的集成
以下是在主应用中集成搜索关键词高亮组件的代码:
import 'package:flutter/material.dart';
import 'components/search_highlight.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter for openHarmony',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
debugShowCheckedModeBanner: false,
home: const MyHomePage(title: 'Flutter for openHarmony'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
// 搜索关键词高亮
Card(
elevation: 4,
margin: EdgeInsets.only(bottom: 20),
child: SearchHighlight(),
),
],
),
),
);
}
}
开发中需要注意的点
-
字符串匹配大小写处理:在实现搜索功能时,使用
toLowerCase()方法确保大小写不敏感的匹配,提高用户体验。 -
空值处理:在使用
Colors.grey[300]等可能返回null的颜色值时,使用??运算符提供默认值,避免类型错误。 -
状态管理:使用
setState方法更新状态时,确保只更新必要的部分,避免不必要的重建。 -
文本控制器管理:使用
TextEditingController时,记得在dispose方法中调用dispose(),避免内存泄漏。 -
响应式布局:使用
Wrap组件实现预设关键词的自适应布局,确保界面在不同屏幕尺寸上都能正常显示。 -
用户体验:添加适当的间距和动画效果,提升界面美观度和用户体验。
本次开发中容易遇到的问题
-
Flutter SDK权限问题:在运行Flutter命令时可能会遇到权限不足的问题,导致无法正常构建和运行项目。解决方法是确保Flutter SDK目录有正确的读写权限。
-
组件导入路径错误:在导入自定义组件时,可能会因为路径错误导致编译失败。解决方法是使用相对路径或绝对路径正确导入组件。
-
状态管理问题:在使用
setState更新状态时,可能会因为状态更新逻辑不正确导致界面不刷新。解决方法是确保所有需要更新的状态都通过setState方法进行更新。 -
颜色处理问题:在处理颜色时,可能会因为颜色值为null导致运行时错误。解决方法是使用
??运算符为可能为null的颜色值提供默认值。 -
布局适配问题:在不同屏幕尺寸上,组件可能会出现布局错乱的问题。解决方法是使用
Wrap、Flex等自适应布局组件,确保界面在不同屏幕尺寸上都能正常显示。 -
组件不存在错误:在引用不存在的组件时,会导致编译失败。解决方法是确保只引用项目中实际存在的组件,移除对不存在组件的引用。
-
字符串匹配问题:在实现搜索关键词高亮时,可能会因为字符串匹配逻辑不正确导致高亮效果不准确。解决方法是使用
toLowerCase()方法确保大小写不敏感的匹配,并正确处理字符串的索引和截取。
总结本次开发中用到的技术点
-
Flutter组件化开发:将搜索关键词高亮功能封装为独立的
SearchHighlight组件,提高代码复用性和可维护性。 -
状态管理:使用
setState方法管理组件状态,实现实时搜索和高亮效果。 -
交互设计:使用
GestureDetector实现点击交互效果,通过颜色变化反馈用户操作。 -
布局组件:使用
Wrap、SingleChildScrollView、Card等组件实现自适应布局。 -
参数化设计:通过构造函数参数化组件配置,允许用户自定义组件宽度、高度、背景色、主题色和高亮色。
-
响应式设计:使用自适应布局组件,确保界面在不同屏幕尺寸上都能正常显示。
-
图标使用:使用
Icons类提供的图标,丰富界面设计。 -
字符串处理:使用字符串匹配和截取实现关键词高亮功能。
-
主题配置:在主应用中配置主题,确保整个应用的视觉风格一致。
-
错误处理:通过移除对不存在组件的引用,解决编译错误。
-
RichText使用:使用
RichText和TextSpan实现文本的部分高亮效果,这是实现关键词高亮的核心技术。 -
TextField使用:使用
TextField实现用户输入,并通过onChanged回调实时处理输入内容。 -
TextEditingController:使用
TextEditingController控制文本输入框的内容,实现预设关键词的快速填充。 -
空值安全:使用
??运算符处理可能为null的值,确保代码的健壮性。
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)