Flutter+OpenHarmony实战:Calculator 计算器项目
前言calculator是一个基于 Flutter 的轻量级Calculator 计算器项目源码集中在lib/main.dart同时保留了ohos平台工程目录。效果图如下本文重点回答三个问题calculator的计算流程是怎样组织的。Flutter 页面状态如何驱动计算器 UI 刷新。这个项目迁移或适配 OpenHarmony 时应重点检查哪些位置。一、项目背景与功能定位1.1 项目功能概览calculator的功能边界很清晰用户点击数字按钮输入数值点击、-、×、÷保存运算符再点击得到结果。项目还提供了C清空按钮、小数点输入按钮以及除法时对num2 0的错误保护。它没有引入复杂第三方依赖因此特别适合讲解 Flutter 小工具从页面到逻辑的一体化实现。1.2 技术关键词本项目可以提炼出以下技术关键词Flutter MaterialApp负责应用级配置、主题色和首页挂载。StatefulWidget承载需要变化的计算器状态。setState在按钮点击后触发 UI 重建。Expanded Row Column构建计算器常见的网格按钮布局。OpenHarmony ohos 工程承载平台侧配置和入口能力。1.3 适合读者本文适合以下读者阅读刚开始学习 Flutter 页面状态管理的开发者。希望把 Flutter 小应用整理成 OpenHarmony 适配文章的作者。需要一篇 CSDN 高分结构模板并希望内容贴合真实项目的技术写作者。提示计算器项目虽然功能简单但它包含输入、状态、分支、错误处理和布局复用特别适合作为 Flutter 入门到平台适配之间的桥梁案例。二、项目目录结构分析2.1 根目录文件当前项目根目录包含 Flutter 标准工程文件也包含 OpenHarmony 平台目录。文件/目录当前项目中的作用文章讲解重点lib/main.dart计算器入口、状态和 UI 全部集中在这里重点拆解计算逻辑和按钮布局pubspec.yaml定义 Flutter SDK、版本和依赖说明依赖简单、适合跨平台适配analysis_options.yamlDart 静态分析配置保持代码风格一致test/Flutter 测试目录可扩展计算逻辑单元测试ohos/OpenHarmony 平台工程适配、签名、入口和资源配置2.2 OpenHarmony 目录ohos目录下可以看到AppScope、entry、EntryAbility.ets、Index.ets、GeneratedPluginRegistrant.ets等文件。这说明项目不仅是普通 Flutter Demo也已经具备 OpenHarmony 工程外壳。OpenHarmony 文件作用检查建议AppScope/app.json5应用级元信息检查应用名、图标和包信息entry/src/main/module.json5模块配置检查入口、权限和设备类型EntryAbility.etsAbility 生命周期入口检查启动流程是否正常Index.ets页面承载入口检查 Flutter 页面嵌入表现GeneratedPluginRegistrant.ets插件注册当前依赖简单重点确认无多余插件异常2.3 代码集中度这个项目的主要业务代码都在一个main.dart文件里。这种组织方式对小 Demo 很友好读者打开一个文件就能看到完整链路。如果项目后续变复杂可以再拆分为calculator_state.dart保存计算状态。calculator_keyboard.dart封装按钮网格。calculator_display.dart封装结果显示区。calculator_logic.dart抽离四则运算逻辑。三、环境准备与依赖配置3.1 pubspec 基础配置项目的pubspec.yaml中名称为calculator版本为1.0.01Dart SDK 约束为^3.9.2。name:calculatordescription:A new Flutter project.publish_to:noneversion:1.0.01environment:sdk:^3.9.2这段配置说明项目是一个私有示例应用不会误发布到pub.dev。3.2 Flutter 依赖项目只依赖 Flutter SDK 和cupertino_icons。dependencies:flutter:sdk:fluttercupertino_icons:^1.0.8dev_dependencies:flutter_test:sdk:flutterflutter_lints:^5.0.0依赖越简单OpenHarmony 适配时排查成本越低。3.3 推荐工具链工具作用推荐理由Flutter SDK编译运行 Flutter 页面项目核心运行环境Dart SDK语言分析、格式化、测试随 Flutter 自带DevEco Studio查看 OpenHarmony 工程检查ohos平台配置CSDN Markdown 编辑器发布文章校验代码块、表格和图片展示四、应用入口源码解读4.1 main 函数lib/main.dart的入口非常短直接启动CalculatorApp。importpackage:flutter/material.dart;voidmain(){runApp(constCalculatorApp());}这段代码体现了 Flutter 应用的标准启动方式。runApp会把CalculatorApp挂载到渲染树根部后续所有页面和状态都从这个入口向下展开。4.2 CalculatorApp 结构CalculatorApp是一个StatelessWidget因为它本身不直接保存计算状态。classCalculatorAppextendsStatelessWidget{constCalculatorApp({super.key});overrideWidgetbuild(BuildContextcontext){returnMaterialApp(title:Calculator,theme:ThemeData(colorScheme:ColorScheme.fromSeed(seedColor:Colors.blue),useMaterial3:true,),home:constCalculatorHomePage(title:Calculator),);}}这里有三个值得写进文章的点title: Calculator说明应用主题明确。ColorScheme.fromSeed(seedColor: Colors.blue)让主题色统一。home: CalculatorHomePage把计算器首页挂载为默认页面。4.3 Material 3 配置项目启用了useMaterial3: true。这意味着按钮、AppBar、默认主题会遵循 Material 3 风格。对于 OpenHarmony 适配文章而言这一点可以用来说明 Flutter 自身 UI 体系如何在不同平台保持一致。五、页面类与状态字段设计5.1 StatefulWidget 分工计算器页面由CalculatorHomePage和_CalculatorHomePageState共同完成。classCalculatorHomePageextendsStatefulWidget{constCalculatorHomePage({super.key,requiredthis.title});finalStringtitle;overrideStateCalculatorHomePagecreateState()_CalculatorHomePageState();}CalculatorHomePage只保存不可变的标题真正变化的数据放到 State 类里。5.2 状态字段项目中定义了五个核心状态字段。class_CalculatorHomePageStateextendsStateCalculatorHomePage{Stringoutput0;double num10;double num20;Stringoperand;bool shouldResetScreenfalse;}字段含义如下字段类型真实作用outputString当前屏幕显示内容默认是0num1double点击运算符前保存的第一个数字num2double点击等号后解析出的第二个数字operandString保存、-、×、÷shouldResetScreenbool控制输入第二个数字时是否清空屏幕5.3 状态设计优点这个状态模型很适合入门案例。它没有额外类也没有复杂状态管理框架却能表达一个计算器的完整生命周期。核心流程可以概括为初始时output 0。用户输入数字后更新output。用户点击运算符后保存num1和operand。用户输入第二个数字。点击后计算结果并写回output。注意shouldResetScreen是这个项目里非常关键的状态。如果没有它点击运算符后继续输入数字时第二个数字会错误地拼接到第一个数字后面。六、核心计算逻辑拆解6.1 buttonPressed 方法入口所有按钮最终都会调用buttonPressed。voidbuttonPressed(StringbuttonText){setState((){if(buttonTextC){output0;num10;num20;operand;shouldResetScreenfalse;}});}真实源码中这个方法包含多个分支文章可以按按钮类型分段讲解。6.2 清空逻辑当按钮文本是C时项目会重置所有状态。if(buttonTextC){output0;num10;num20;operand;shouldResetScreenfalse;}这个分支非常直观适合解释“状态归零”的意义。6.3 运算符逻辑点击、-、×、÷时项目会保存当前屏幕值。}elseif(buttonText||buttonText-||buttonText×||buttonText÷){num1double.parse(output);operandbuttonText;shouldResetScreentrue;}这里的关键是shouldResetScreen true。下一次点击数字时页面不会继续拼接旧值而是开启第二个操作数输入。6.4 等号计算逻辑点击后源码会根据operand执行对应运算。}elseif(buttonText){num2double.parse(output);double result0;if(operand){resultnum1num2;}elseif(operand-){resultnum1-num2;}elseif(operand×){resultnum1*num2;}elseif(operand÷){if(num2!0){resultnum1/num2;}else{outputError;return;}}}这段代码已经覆盖四则运算还对除零做了保护。6.5 结果格式化项目没有直接展示double.toString()而是做了结果格式化。outputresult.toString().endsWith(.0)?result.toInt().toString():result.toStringAsFixed(8).replaceAll(RegExp(r0$),).replaceAll(RegExp(r\.$),);这个细节值得单独写因为它提升了用户体验。例如1 1会显示2而不是2.0。6.6 数字与小数点输入数字输入和小数点输入分支如下。}elseif(buttonText.){if(!output.contains(.)){outputoutputbuttonText;}}else{if(output0||shouldResetScreen){outputbuttonText;shouldResetScreenfalse;}else{outputoutputbuttonText;}}这里有两个实用点小数点只能输入一次。运算符之后第一次输入数字会重置屏幕。七、按钮组件封装7.1 buildButton 方法项目通过buildButton复用按钮样式。WidgetbuildButton(StringbuttonText,Colorcolor,{int flex1}){returnExpanded(flex:flex,child:Padding(padding:constEdgeInsets.all(4.0),child:ElevatedButton(onPressed:()buttonPressed(buttonText),style:ElevatedButton.styleFrom(backgroundColor:color,padding:constEdgeInsets.all(24),shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(12),),),child:Text(buttonText,style:constTextStyle(fontSize:28,fontWeight:FontWeight.bold,color:Colors.white),),),),);}这是整篇文章里最能体现组件复用的一段代码。7.2 参数设计buildButton有三个参数。参数类型用途buttonTextString显示按钮文本并传给buttonPressedcolorColor控制按钮背景色flexint控制按钮宽度比例默认是 17.3 样式选择按钮使用ElevatedButton并设置了backgroundColor区分数字、运算符、清空和等号。padding: EdgeInsets.all(24)保证点击区域足够大。BorderRadius.circular(12)让按钮有圆角。TextStyle(fontSize: 28, fontWeight: FontWeight.bold)增强可读性。八、页面布局实现8.1 Scaffold 与 AppBar页面根结构使用Scaffold。returnScaffold(appBar:AppBar(title:Text(widget.title),backgroundColor:Theme.of(context).colorScheme.inversePrimary,),body:Column(children:[// display area// keyboard area],),);AppBar 的标题来自widget.title也就是CalculatorHomePage(title: Calculator)传入的值。8.2 显示区域计算器顶部显示当前结果。Expanded(child:Container(alignment:Alignment.centerRight,padding:constEdgeInsets.all(24),child:Text(output,style:constTextStyle(fontSize:64,fontWeight:FontWeight.bold),),),)这个区域把文字右对齐符合计算器常见交互习惯。8.3 按钮区域按钮区使用Expanded(flex: 3)占据更大空间。Expanded(flex:3,child:Column(children:[Row(children:[buildButton(C,Colors.red),buildButton(÷,Colors.orange),buildButton(×,Colors.orange),buildButton(⌫,Colors.grey),]),],),)按钮行按照计算器键盘布局组织清空、运算符和数字区域区分明显。8.4 当前源码中的可改进点项目中展示了⌫退格按钮但buttonPressed目前没有处理⌫分支。这是一处很适合在文章中指出的真实优化点。可以补充如下逻辑}elseif(buttonText⌫){if(output.length1output!Error){outputoutput.substring(0,output.length-1);}else{output0;}}这个优化来自当前项目真实 UI不是凭空添加功能。九、OpenHarmony 适配说明9.1 为什么这个项目适合适配calculator不依赖平台传感器、相机、网络或数据库因此 OpenHarmony 适配重点主要集中在工程配置和 UI 运行效果。这类项目可以作为 Flutter/OpenHarmony 环境是否打通的基础验证项目。9.2 ohos 工程检查点适配时建议重点检查以下内容ohos/AppScope/app.json5中应用信息是否正确。ohos/entry/src/main/module.json5中入口模块是否正常。EntryAbility.ets是否能够启动页面。资源目录中的图标和字符串是否能正确加载。运行时按钮点击、字体大小和布局比例是否正常。9.3 构建命令可以先从 Flutter 标准命令开始检查。flutter pub get flutter analyze fluttertestflutter run如果本地已经配置 OpenHarmony Flutter 工具链再补充对应的 OpenHarmony 构建命令。flutter clean flutter pub get flutter run-dopenharmony-device-id9.4 平台验证表验证项Flutter 侧表现OpenHarmony 侧检查应用启动CalculatorApp正常挂载Ability 能启动页面结果显示output正常刷新字体大小不溢出按钮点击buttonPressed被触发点击区域响应正常除零保护显示Error错误状态不闪退主题色蓝色 Material 主题AppBar 和按钮颜色一致十、测试策略与质量保障10.1 当前测试方向项目已有test目录后续可以把计算逻辑抽成纯函数后测试。例如可以定义一个calculate方法。doublecalculate(double left,double right,Stringop){switch(op){case:returnleftright;case-:returnleft-right;case×:returnleft*right;case÷:if(right0){throwArgumentError(Cannot divide by zero);}returnleft/right;default:throwArgumentError(Unknown operator);}}然后编写单元测试。importpackage:flutter_test/flutter_test.dart;voidmain(){test(calculator addition should work,(){expect(12,3);});test(calculator division by zero should be guarded,(){expect(()1~/0,throwsA(isAIntegerDivisionByZeroException()));});}10.2 手工测试清单发布前建议手工验证以下场景连续输入多个数字例如123。输入小数例如1.25。执行、-、×、÷四种运算。执行1 ÷ 0确认显示Error。点击C后所有状态恢复初始值。点击 UI 中的⌫确认是否按预期处理。10.3 静态分析Flutter 项目建议始终运行静态分析。flutter analyze dartformatlibtestfluttertest如果⌫按钮没有对应逻辑不一定会导致静态分析失败但会影响真实功能完整性。十二、常见问题与优化建议12.1 除零错误如何处理当前项目已经处理除零问题。if(num2!0){resultnum1/num2;}else{outputError;return;}这个处理可以避免直接显示无意义结果。12.2 退格按钮如何补齐UI 中有⌫按钮但当前逻辑没有对应分支。这是本文最重要的源码级优化建议。建议在C分支之后增加退格处理让 UI 和逻辑保持一致。12.3 连续运算如何增强当前项目更接近“两个数字一次运算”的模式。如果要支持1 2 3 6这种连续运算可以在点击第二个运算符时立即计算上一次结果。12.4 输入错误如何增强当前double.parse(output)假设output一定可解析。如果output Error后继续点击运算符建议先重置或忽略。12.5 UI 响应式如何增强按钮使用较大的padding和字体。在小屏设备上可能需要通过LayoutBuilder或动态字号优化。如果这篇文章对你有帮助欢迎点赞、收藏、关注你的支持是我持续创作的动力相关资源Flutter 官方文档Dart 官方文档Dart API 文档开源鸿蒙跨平台社区

相关新闻

MFC框架下中国象棋游戏开发:从数据模型到GDI绘制的完整实现

MFC框架下中国象棋游戏开发:从数据模型到GDI绘制的完整实现

1. 项目概述:一个MFC中国象棋项目的深度拆解最近在整理旧项目时,翻出了一个用MFC和Visual C写的中国象棋游戏。这个项目虽然年头不短,但麻雀虽小五脏俱全,从棋盘绘制、棋子移动、规则判定到胜负判断,完整地走了一遍Win…

2026/7/14 6:59:15阅读更多 →
C++ LoopRepair:迭代式修复 40 个真实 C/C++ 漏洞

C++ LoopRepair:迭代式修复 40 个真实 C/C++ 漏洞

LoopRepair 是一种面向 C/C 循环结构缺陷的迭代式程序修复方法。本文以 40 个真实漏洞为测试基准,详细拆解 LoopRepair 的修复流程、关键技术,并与现有自动修复工具进行对比,展示其在循环相关漏洞上的高修复率和高质量补丁。一、循环漏洞为什…

2026/7/14 6:59:15阅读更多 →
C++ 写代码条件判断边界缺失的隐蔽逻辑漏洞

C++ 写代码条件判断边界缺失的隐蔽逻辑漏洞

一、一个看似正确的函数先看一段简单的 C 代码&#xff1a;#include <iostream> #include <vector>int findIndex(const std::vector<int>& arr, int target) {for (int i 0; i < arr.size(); i) { // 条件写成了 <if (i arr.size()) return -1…

2026/7/14 6:59:15阅读更多 →
Windows内核资源仲裁与转换机制解析

Windows内核资源仲裁与转换机制解析

1. IopSetupArbiterAndTranslators函数概述 在Windows内核中&#xff0c;IopSetupArbiterAndTranslators函数扮演着资源仲裁与转换的关键角色。这个函数主要负责处理设备资源分配过程中的复杂场景&#xff0c;特别是当不同设备对相同资源有冲突需求时。它的核心功能可以概括为&…

2026/7/14 8:44:24阅读更多 →
TDA7468与PIC18F87J11构建高性能音频处理系统

TDA7468与PIC18F87J11构建高性能音频处理系统

1. 音频处理系统的核心组件解析 在构建高性能音频处理系统时&#xff0c;TDA7468和PIC18F87J11的组合堪称黄金搭档。TDA7468是STMicroelectronics推出的一款数字控制音频处理器&#xff0c;具有四通道输入选择、双波段均衡和音量控制功能。这款芯片广泛应用于家用Hi-Fi系统和专…

2026/7/14 8:44:24阅读更多 →
从国赛二等奖到项目落地:生物医学工程竞赛中的深度学习皮肤癌辅助诊断系统全流程复盘

从国赛二等奖到项目落地:生物医学工程竞赛中的深度学习皮肤癌辅助诊断系统全流程复盘

1. 从竞赛到落地&#xff1a;皮肤癌辅助诊断系统的诞生之路 第一次接触皮肤癌辅助诊断这个选题&#xff0c;是在大三那年实验室组会上。导师分享了一组触目惊心的数据&#xff1a;全球每年新增皮肤癌病例超过300万例&#xff0c;而早期诊断的准确率还不到70%。当时我们团队三个…

2026/7/14 8:44:24阅读更多 →
ALCameraViewController错误处理与调试:常见问题解决方案终极指南

ALCameraViewController错误处理与调试:常见问题解决方案终极指南

ALCameraViewController错误处理与调试&#xff1a;常见问题解决方案终极指南 【免费下载链接】ALCameraViewController A camera view controller with custom image picker and image cropping. 项目地址: https://gitcode.com/gh_mirrors/al/ALCameraViewController …

2026/7/14 8:44:24阅读更多 →
APAddressBook Swift版教程:iOS通讯录访问的简洁实现方式

APAddressBook Swift版教程:iOS通讯录访问的简洁实现方式

APAddressBook Swift版教程&#xff1a;iOS通讯录访问的简洁实现方式 【免费下载链接】APAddressBook Easy access to iOS address book 项目地址: https://gitcode.com/gh_mirrors/ap/APAddressBook 想要在iOS应用中优雅地访问用户通讯录吗&#xff1f;APAddressBook提…

2026/7/14 8:44:24阅读更多 →
Go语言REST API开发实战:从环境搭建到生产部署完整指南

Go语言REST API开发实战:从环境搭建到生产部署完整指南

在 Web 开发领域&#xff0c;REST API 作为前后端分离架构中的核心通信桥梁&#xff0c;其设计质量直接影响着整个系统的可维护性和扩展性。Go 语言凭借其简洁的语法、出色的并发性能和高效的编译速度&#xff0c;已成为构建高性能后端服务的首选语言之一。对于从 Java、Python…

2026/7/14 8:39:23阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比&#xff1a;全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时&#xff0c;第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/14 4:56:14阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件&#xff1a;5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件&#xff0c;自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/14 2:55:05阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL&#xff1a;跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/14 6:17:41阅读更多 →
【Cursor数据库安全红线】:自动执行SQL前必须校验的6项权限策略,金融级项目已强制落地

【Cursor数据库安全红线】:自动执行SQL前必须校验的6项权限策略,金融级项目已强制落地

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Cursor数据库安全红线概览 Cursor 作为一款基于 AI 的智能编程助手&#xff0c;其本地数据库&#xff08;SQLite 存储&#xff09;承载着用户代码片段、会话历史、自定义规则及敏感上下文信息。理解其安…

2026/7/14 0:03:18阅读更多 →
【Notion AI写作避坑白皮书】:基于127份真实用户失败案例,总结6大致命误用陷阱

【Notion AI写作避坑白皮书】:基于127份真实用户失败案例,总结6大致命误用陷阱

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;Notion AI写作辅助的底层能力边界认知 Notion AI 并非通用大语言模型的直接封装&#xff0c;而是基于 Llama 系列与自研微调模型构建的轻量化推理服务&#xff0c;其输入上下文窗口严格限制在 8192 token&…

2026/7/14 0:03:18阅读更多 →
AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;AI Agent数据越界行为的合规性挑战与溯源必要性 AI Agent在自主执行任务过程中&#xff0c;可能因提示注入、上下文污染或权限配置缺陷&#xff0c;无意或有意访问、缓存、传输受保护数据&#xff08;如PII、G…

2026/7/14 0:03:18阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/13 4:21:17阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/14 4:45:36阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/14 2:42:17阅读更多 →