基于HarmonyOS 7.0 跨端开发的成语填字挑战页面实战
基于HarmonyOS 7.0 跨端开发的成语填字挑战页面实战
前言
在国学益智与文字游戏类应用中,成语填字是一个寓教于乐、锻炼成语积累的经典主题功能。成语是汉语的瑰宝,而填字游戏(在四字成语中填出缺失的字)既有挑战性又能学习成语,一个能出题填空、给出提示、检测答案、积累已学成语的应用,让学成语变得有趣。一个优秀的成语填字页面,需要用米字格展示成语、提供填空和提示、检测答案对错、并积累已学成语。这类页面在技术上的亮点是"米字格自绘加填字交互加答案检测"——它需要用 CustomPaint 自绘书法米字格、用 TextField 单字填空、并检测答案。当我们把这样一个文字游戏主题的页面放进 HarmonyOS 7.0 的跨端开发语境时,它就成为检验 Flutter 米字格自绘与填字检测跨端一致性的合适样本。本文将以一个真实的 Flutter 成语填字页面为载体,结合 Flutter 与 HarmonyOS 7.0 的融合架构,深入剖析它的设计思路、核心代码与跨端落地路径。需要在开篇明确:本文涉及的鸿蒙适配全部基于 HarmonyOS 跨平台 SIG 维护的定制版 Flutter SDK,而非 flutter.dev 官方版本,这是所有讨论的前提。
背景
成语填字的玩法是"填空补全"。一个四字成语,隐去其中一两个字让用户填(如"一_惊_“填"鸣”“人"成"一鸣惊人”),配合释义提示,既考验成语积累又能学习。米字格是中文书法的标准练习格(田字格加对角线),用米字格展示成语字符,既美观又有书法的文化感。提示用成语的释义帮助联想。检测则比对用户填入的字和正确答案,给出对错反馈。已学成语则积累玩过的成语及其释义出处,形成学习成果。从技术上看,这个页面的亮点是米字格的 CustomPaint 自绘、单字 TextField 填空、答案检测逻辑。在传统多端开发中,要在 Android、iOS、HarmonyOS 上分别实现米字格自绘和填字检测,意味着重复且易不一致。这种"米字格自绘一致、填字检测准确"的要求,正是 Flutter 自绘引擎跨端价值的体现。我们的目标,是用一份 Dart 代码让手机、平板与鸿蒙设备上呈现一致的成语填字体验。
Flutter × Harmony7.0 跨端开发介绍
成语填字页面要在 HarmonyOS 7.0 上正确运行,需要理解 Flutter 在鸿蒙上的运行架构。Flutter 由 Framework、Engine、Embedder 三层组成。Framework 层用 Dart 编写,负责组件、状态、布局、文本输入等,本页面里的进度条、成语米字格、提示、检测反馈、已学成语都属于这一层。Engine 层是运行时核心,负责 Dart VM、AOT 产物加载、GPU 渲染、文本排版等;Flutter 在鸿蒙上的界面由其自绘引擎绘制,通过接入 HarmonyOS 的 ArkUI RenderingContext 获取 GPU 渲染上下文,再由 ArkTS 容器 FlutterAbility 承载输出。这里的技术核心是 _TianGridPainter——用 CustomPaint 自绘书法米字格(外框加十字加对角线),由 Skia 渲染跨端逐像素一致。填空用单字 TextField(maxLength: 1),中文输入由 Embedder 对接鸿蒙输入法。Embedder 层是 Flutter 与鸿蒙系统的桥梁,由 @ohos/flutter_ohos 提供的 FlutterAbility 实现。在能力接入上,米字格自绘、填字、检测、已学成语都是纯 Framework 与 Dart 能力,可零适配复用;成语题库可用本地数据(纯 Dart)。编译上,Release 模式的 AOT 提前编译保证了自绘和渲染的原生级流畅。

开发核心代码
成语填字页面的代码可分为三个核心部分。第一部分是米字格的 CustomPaint 自绘。页面以 StatefulWidget 承载,入口类被统一命名为 SearchPage,状态类 _IdiomFillPageState 用 _TianGridPainter 自绘米字格。
class SearchPage extends StatefulWidget {
const SearchPage({super.key});
@override
State<SearchPage> createState() => _IdiomFillPageState();
}
class _TianGridPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..style = PaintingStyle.stroke;
// 外框(紫色)
paint..strokeWidth = 1.5..color = const Color(0xFF6A1B9A).withOpacity(0.3);
canvas.drawRect(Rect.fromLTWH(1, 1, size.width - 2, size.height - 2), paint);
// 米字格内线(浅灰)
paint..strokeWidth = 0.5..color = Colors.grey.withOpacity(0.2);
canvas.drawLine(Offset(size.width / 2, 0), Offset(size.width / 2, size.height), paint); // 竖中线
canvas.drawLine(Offset(0, size.height / 2), Offset(size.width, size.height / 2), paint); // 横中线
canvas.drawLine(Offset(0, 0), Offset(size.width, size.height), paint); // 对角线\
canvas.drawLine(Offset(size.width, 0), Offset(0, size.height), paint); // 对角线/
}
@override
bool shouldRepaint(covariant CustomPainter old) => false;
}
这段代码用 CustomPaint 自绘书法米字格。_TianGridPainter 用 drawRect 画外框、用四条 drawLine 画米字格的内线(竖中线、横中线、两条对角线),构成传统书法练习的米字格。外框用紫色、内线用浅灰,层次分明。米字格是中文书写的文化符号,自绘它让成语展示有了书法的韵味。shouldRepaint 返回 false 因为米字格是静态的。这种自绘由 Skia 渲染,鸿蒙上与手机端逐像素一致。用 CustomPaint 画米字格这种文化元素,体现了 Flutter 自绘对文化符号的还原能力。
第二部分是填字交互,它用单字 TextField 加米字格叠放实现填空。
List.generate(4, (i) {
final isFilled = puzzle['filled'][i] as bool; // 是否已给出
final userChar = _charControllers[i].text.trim();
final isCorrect = userChar == idiom[i];
return SizedBox(
width: 60, height: 72,
child: Stack(children: [
CustomPaint(size: const Size(60, 72), painter: _TianGridPainter()), // 米字格背景
if (isFilled)
Center(child: Text(idiom[i], style: const TextStyle(fontSize: 32, color: Color(0xFF6A1B9A)))) // 已给字
else
TextField( // 填空格
controller: _charControllers[i],
textAlign: TextAlign.center, maxLength: 1, // 限一字
style: TextStyle(fontSize: 32,
color: _showResult ? (isCorrect ? Colors.green : Colors.red) : const Color(0xFF6A1B9A)),
decoration: const InputDecoration(counterText: '', border: InputBorder.none, hintText: '?'),
onChanged: (_) => setState(() {}),
),
]),
);
})
这段代码用 Stack 把米字格背景和字符叠放实现填字。List.generate(4, ...) 生成四个格子(四字成语),每个格子用 Stack 叠放米字格自绘背景和字符层。已给出的字(isFilled)直接显示,需填的字用单字 TextField(maxLength: 1 限一字、counterText: '' 隐藏计数器)。检测后(_showResult)填入的字按对错变色(对绿错红)。这种"米字格背景+TextField填空"的叠放设计,让填字既有书法格的美感又能交互输入。Stack 叠放、maxLength 限字都是 Flutter 标准能力,跨端一致。

第三部分是答案检测,它逐字比对填空。
void _checkAnswer() {
final idiom = _puzzles[_currentPuzzle]['idiom'] as String;
bool correct = true;
for (int i = 0; i < 4; i++) {
if (!(puzzle['filled'][i] as bool)) { // 只检测需填的格
if (_charControllers[i].text.trim() != idiom[i]) {
correct = false;
break;
}
}
}
setState(() => _showResult = true);
}
// 结果反馈
if (_showResult)
Container(
decoration: BoxDecoration(color: allCorrect ? Colors.green[50] : Colors.red[50]),
child: Row(children: [
Icon(allCorrect ? Icons.celebration : Icons.try_again),
Text(allCorrect ? '恭喜答对!🎉 $idiom' : '正确答案: $idiom'),
]),
)
这段代码检测填字答案。遍历四个格子,只检测需填的格(!filled),逐字比对用户输入(text.trim())和正确答案(idiom[i],字符串按索引取字),有一个错就 correct = false。检测后显示结果——全对显示祝贺、否则显示正确答案。这种逐字符比对的检测用字符串索引和比较实现,纯 Dart 跨端一致。idiom[i] 按索引取字符是 Dart 字符串的基本操作。这套检测逻辑在鸿蒙上与手机端结果一致。三部分代码合在一起,构成了一个米字格美观、填字流畅、检测清晰的成语填字页面,其米字格自绘、填字交互、答案检测都不依赖任何平台特性可零适配跨端,成语题库用本地数据。
心得
把这个成语填字页面落地到 HarmonyOS 7.0,让我对 Flutter 自绘文化符号和文本填空交互在跨端中的表现有了体会。第一点核心体会是用 CustomPaint 自绘文化符号。米字格是中文书法的文化符号,用 CustomPaint 画外框加十字加对角线就能精确还原,由 Skia 渲染跨端逐像素一致。这让成语展示有了书法的文化韵味。这与前面剪纸、竹编的文化图案自绘一脉相承,再次印证 Flutter 自绘对文化元素的还原能力——米字格、田字格、九宫格这些中文书写格都能用简单的线条自绘精确呈现,且跨端一致。第二点深的体会是 Stack 叠放实现填字。把米字格背景(CustomPaint)和字符层(Text 或 TextField)用 Stack 叠放,让填字格既有背景美感又能输入,这种"自绘背景+交互前景"的叠放是组合自绘和交互的常用手法,跨端一致。第三点体会是单字 TextField 的配置。填字用 maxLength: 1 限一字、counterText: '' 隐藏字数计数器、hintText: '?' 提示,这些 TextField 的细节配置让填字格符合需求。中文单字输入由 Embedder 对接鸿蒙输入法。第四点体会是字符串索引检测。答案检测用 idiom[i] 按索引取字符逐字比对,这是字符串处理的基本操作,纯 Dart 跨端一致。同时 _charControllers 列表需在 dispose 中逐个释放。第五点是工程规律的印证:米字格自绘、填字交互、答案检测零成本跨端,文化符号自绘跨端一致,Stack 叠放组合自绘与交互,多个 TextEditingController 需释放。

总结
通过成语填字挑战页面在 HarmonyOS 7.0 上的实践,我们看到了 Flutter 跨端方案在"文字游戏类应用"上的可靠表现。架构上,Framework、Engine、Embedder 三层在鸿蒙平台协同运转,_TianGridPainter 通过 Skia 自绘书法米字格保证了逐像素一致,纯 Dart 的字符串索引比对保证了答案检测的跨端一致,Stack 叠放组合自绘背景与填字交互,中文输入由 Embedder 对接鸿蒙输入法,AOT 编译保证了渲染的流畅,FlutterAbility 承载了与鸿蒙系统的交互。代码上,页面通过 CustomPaint 自绘的米字格、Stack 叠放的填字格、以及逐字比对的答案检测,把成语填字干净地映射成了美观益智的界面,整份 Dart 代码无需修改即可在鸿蒙运行,充分印证了高复用率优势。
这次实践展现了几个有价值的技巧:用 CustomPaint 自绘米字格等中文书写文化符号(跨端逐像素一致,呼应剪纸竹编的文化图案自绘)、用 Stack 叠放自绘背景与 TextField 交互实现填字格、用字符串索引(idiom[i])逐字比对做答案检测(纯 Dart 跨端一致)。成语填字的米字格、填字、检测零成本跨端,题库用本地数据。这提示我们,文字游戏类应用可放心用自绘还原文化符号、用 Stack 组合自绘与交互。因此,对准备进入鸿蒙生态的 Flutter 团队,对这类应用完全可以放心地用 CustomPaint 自绘文化元素、用 Stack 组合背景与交互、用字符串方法检测,信赖其跨端一致,规范管理 TextEditingController,并始终以 HarmonyOS 跨平台 SIG 维护的定制版 Flutter SDK 作为一切工作的起点。唯有如此,才能既享受一次开发、多端部署的红利,又借助自绘与组合的能力,让成语填字这样益智的文字游戏功能真正美观、有趣地陪伴每一位用户学习成语。
- 点赞
- 收藏
- 关注作者
评论(0)