Flutter 跨平台实战:OpenHarmony 健康管理应用 Day4|表单非空校验 + 提交按钮 + 消息提示
·
🎯 Flutter 跨平台实战:OpenHarmony 健康管理应用 Day4|表单非空校验 + 提交按钮 + 消息提示
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
🚀 前言
大家好,本篇是 Flutter + OpenHarmony 健康管理应用 开发系列的第四篇笔记。在 Day3 完成健康录入页面表单布局与多输入框搭建的基础上,今天继续完善交互逻辑,新增提交保存按钮、实现表单全字段非空校验,同时通过 SnackBar 给出友好的消息提示,提升 APP 使用体验。本阶段为后续接入本地数据持久化存储做好前置铺垫,全程基于原生 Flutter 组件开发,无需额外第三方依赖,适配 OpenHarmony 鸿蒙模拟器直接运行,适合课程实训作业提交与自查高分使用。
💥 本文你能学到
- Flutter 按钮组件 ElevatedButton 布局与使用
- 表单多字段非空逻辑校验编写
- SnackBar 底部消息提示弹窗实现
- 输入框内容获取与字符串判空处理
- 鸿蒙端表单交互适配与页面调试方法
- 有状态组件资源规范释放写法
🥝 开发环境
1. 环境信息
- 开发工具:DevEco Studio
- 开发语言:Dart
- 开发框架:Flutter
- 调试设备:OpenHarmony 手机模拟器
- 适配平台:OpenHarmony
2. 依赖配置
Day4 无需新增任何第三方依赖,沿用之前默认配置即可,不需要修改 pubspec.yaml 文件。
dependencies:
flutter:
sdk: flutter
📝 今日核心开发功能
- 在健康录入页面添加全屏宽度提交保存按钮
- 实现姓名、年龄、身高、体重、心率全部字段非空校验
- 未填完整信息时弹出提示,禁止提交
- 信息填写完整后给出提交成功友好提示
- 保留输入框控制器规范释放,防止内存泄漏
- 兼容鸿蒙设备软键盘弹出布局,页面正常滚动不遮挡
✅ 完整可运行核心代码
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(primarySwatch: Colors.blue),
home: const MainPage(),
);
}
}
// 主页面底部导航框架
class MainPage extends StatefulWidget {
const MainPage({super.key});
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
final List<Widget> _pages = const [
HomePage(),
HealthInputPage(),
ProfilePage(),
];
void _onItemTapped(int index) {
setState(() {
_currentIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onItemTapped,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.add_chart), label: "健康录入"),
BottomNavigationBarItem(icon: Icon(Icons.person), label: "个人中心"),
],
),
);
}
}
// 首页页面
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("首页")),
body: const Center(
child: Text("欢迎使用健康管理应用", style: TextStyle(fontSize: 18)),
),
);
}
}
// 健康录入页面 新增校验与提交按钮
class HealthInputPage extends StatefulWidget {
const HealthInputPage({super.key});
@override
State<HealthInputPage> createState() => _HealthInputPageState();
}
class _HealthInputPageState extends State<HealthInputPage> {
final TextEditingController _nameController = TextEditingController();
final TextEditingController _ageController = TextEditingController();
final TextEditingController _heightController = TextEditingController();
final TextEditingController _weightController = TextEditingController();
final TextEditingController _heartRateController = TextEditingController();
// 表单校验与提交逻辑
void _submitForm() {
String name = _nameController.text.trim();
String age = _ageController.text.trim();
String height = _heightController.text.trim();
String weight = _weightController.text.trim();
String heart = _heartRateController.text.trim();
if (name.isEmpty || age.isEmpty || height.isEmpty || weight.isEmpty || heart.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("请填写完整所有健康信息")),
);
return;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("✅ 信息提交成功,待本地存储保存")),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("健康录入")),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("姓名", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 8),
TextField(
controller: _nameController,
decoration: const InputDecoration(border: OutlineInputBorder(), hintText: "请输入您的姓名"),
),
const SizedBox(height: 16),
const Text("年龄", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 8),
TextField(
controller: _ageController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(border: OutlineInputBorder(), hintText: "请输入您的年龄"),
),
const SizedBox(height: 16),
const Text("身高(cm)", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 8),
TextField(
controller: _heightController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(border: OutlineInputBorder(), hintText: "请输入您的身高"),
),
const SizedBox(height: 16),
const Text("体重(kg)", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 8),
TextField(
controller: _weightController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(border: OutlineInputBorder(), hintText: "请输入您的体重"),
),
const SizedBox(height: 16),
const Text("心率(次/分)", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
const SizedBox(height: 8),
TextField(
controller: _heartRateController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(border: OutlineInputBorder(), hintText: "请输入您的心率"),
),
const SizedBox(height: 30),
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: _submitForm,
child: const Text("提交保存", style: TextStyle(fontSize: 18)),
),
),
],
),
),
);
}
@override
void dispose() {
_nameController.dispose();
_ageController.dispose();
_heightController.dispose();
_weightController.dispose();
_heartRateController.dispose();
super.dispose();
}
}
// 个人中心页面
class ProfilePage extends StatelessWidget {
const ProfilePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("个人中心")),
body: const Center(child: Text("个人信息展示区域", style: TextStyle(fontSize: 16))),
);
}
}
📱 调试与运行完整步骤
- 停止上一个项目运行
- 打开项目 lib/main.dart 文件,修改原有代码(上方有完整代码)
- 无需修改配置文件,直接终端执行运行命令
flutter run - 选择已启动的 OpenHarmony 模拟器设备,等待编译完成
- 进入健康录入页面,不填写任何内容直接点击提交,查看非空提示

- 完整填写所有字段后再次提交,查看提交成功提示,功能正常即实验完成

🔐 跨平台适配说明
本次 Day4 功能开发完全遵循 Flutter 跨平台适配规范,完美兼容 OpenHarmony 系统:
- 页面采用 SingleChildScrollView 滚动布局,适配鸿蒙软键盘弹出,不会遮挡输入框与按钮
- 消息提示组件原生适配鸿蒙系统底部展示位置,样式显示正常无错位
- 数字输入框键盘类型适配鸿蒙输入法,自动弹出数字键盘
- 整体布局自适应鸿蒙模拟器屏幕尺寸,无需额外适配原生代码
🧩 常见错误排查
| 错误现象 | 解决方法 |
|---|---|
| 点击按钮无任何提示弹窗 | 检查是否使用 ScaffoldMessenger 绑定页面上下文,确认方法无语法错误 |
| 全部填写后仍然提示不能为空 | 检查是否使用 trim () 去除首尾空格,避免空格误判为空 |
| 页面底部按钮被键盘遮挡 | 确认外层已嵌套 SingleChildScrollView,保证页面可整体滚动 |
| 编译报错布局溢出 | 合理设置 SizedBox 间距,按钮固定宽高适配页面 |
🎨 项目后续规划
Day4 已完成表单校验、提交按钮与消息提示功能,后续开发规划如下:
- Day5:引入本地存储依赖 shared_preferences,配置项目依赖环境
- Day6:实现健康信息本地持久化保存,关闭重启数据不丢失
- Day7:首页读取本地存储数据,卡片样式展示个人健康信息
- 后续按规划依次完成 UI 美化、BMI 计算、图表可视化、打包发布等全流程
📌 项目总结
本篇完整记录了 Flutter 鸿蒙健康管理项目 Day4 开发全过程,在原有表单基础上完成了提交按钮布局、多字段非空校验、友好消息提示等核心交互功能。通过本次开发,熟练掌握了 Flutter 按钮使用、表单判空逻辑、消息弹窗调用以及有状态组件生命周期资源释放等知识点,同时进一步适配了 OpenHarmony 鸿蒙端交互体验,为下一日接入本地持久化存储功能打下坚实基础。
✅ 结尾小贴士
- 全文代码可直接复制替换运行,无需改动任何配置
- 全程仅使用 DevEco Studio 即可完成开发与调试
- 无需修改 pubspec.yaml 依赖,直接编译运行
- 点赞收藏不迷路,后续将规划持续更新每一日开发笔记!
更多推荐
所有评论(0)