Flutter 框架跨平台鸿蒙开发 - 自定义食材搭配应用技术内容
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
食材搭配是一款专注于食材营养搭配与健康饮食指导的移动应用,为用户提供科学的食材搭配建议。中华饮食文化讲究"药食同源",食材之间的搭配不仅影响口感,更关乎营养吸收与身体健康。本应用帮助用户了解食材搭配的奥秘,让每一餐都吃得健康、吃得科学。
应用支持八大食材分类,涵盖肉类、蔬菜、海鲜、水果、谷物、调味品、乳制品及其他。每种搭配都有详细的说明、推荐菜谱和营养标签,帮助用户做出明智的食材选择。黄金搭配、可以搭配、不宜搭配三种类型,让用户一目了然。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 搭配列表 | 展示所有食材搭配,按类型排序 | ListView + Card |
| 分类筛选 | 八大食材分类快速筛选 | FilterChip |
| 类型筛选 | 黄金搭配/可以搭配/不宜搭配 | PopupMenuButton |
| 搜索功能 | 按食材名称、搭配说明搜索 | TextField过滤 |
| 搭配详情 | 完整展示搭配说明、菜谱、营养 | ModalBottomSheet |
| 统计展示 | 各类型搭配数量统计 | 统计栏 |
| 食材信息 | 食材营养、功效介绍 | 信息卡片 |
1.3 食材搭配记录字段
| 字段 | 类型 | 说明 |
|---|---|---|
| 搭配ID | String | 唯一标识 |
| 食材1 | Ingredient | 第一种食材 |
| 食材2 | Ingredient | 第二种食材 |
| 搭配类型 | PairingType | 黄金/可以/不宜 |
| 搭配说明 | String | 搭配原因说明 |
| 推荐菜谱 | String? | 推荐菜品名称 |
| 标签列表 | List | 分类标签 |
1.4 食材记录字段
| 字段 | 类型 | 说明 |
|---|---|---|
| 食材ID | String | 唯一标识 |
| 食材名称 | String | 食材名称 |
| 食材分类 | IngredientCategory | 八大分类 |
| 食材描述 | String | 简要描述 |
| 营养成分 | List | 主要营养素 |
| 食疗功效 | String | 健康功效 |
| 表情符号 | String | 食材图标 |
1.5 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 目标平台 | 鸿蒙OS | API 21+ |
1.6 项目结构
lib/
└── main_ingredient_pairing.dart
├── IngredientPairingApp # 应用入口
├── IngredientCategory # 食材分类枚举
├── PairingType # 搭配类型枚举
├── Ingredient # 食材数据模型
├── IngredientPairing # 搭配数据模型
└── IngredientPairingPage # 主页面
├── _buildCategoryChips() # 分类筛选条
├── _buildSearchBar() # 搜索栏
├── _buildStatisticsBar() # 统计栏
├── _buildPairingsList() # 搭配列表
├── _buildPairingCard() # 搭配卡片
├── _showPairingDetail() # 详情弹窗
├── _buildIngredientCircle() # 食材圆形展示
└── _buildIngredientInfoCard() # 食材信息卡片
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 数据流程图
2.4 搭配详情展示流程
三、核心模块设计
3.1 数据模型设计
3.1.1 食材分类枚举 (IngredientCategory)
enum IngredientCategory {
meat, // 肉类
vegetable, // 蔬菜
seafood, // 海鲜
fruit, // 水果
grain, // 谷物
spice, // 调味品
dairy, // 乳制品
other, // 其他
}
3.1.2 食材分类属性映射
| 分类类型 | 中文名称 | 主题颜色 |
|---|---|---|
| meat | 肉类 | 红色 |
| vegetable | 蔬菜 | 绿色 |
| seafood | 海鲜 | 蓝色 |
| fruit | 水果 | 橙色 |
| grain | 谷物 | 琥珀色 |
| spice | 调味品 | 紫色 |
| dairy | 乳制品 | 青色 |
| other | 其他 | 灰色 |
3.1.3 搭配类型枚举 (PairingType)
enum PairingType {
good, // 黄金搭配
neutral, // 可以搭配
bad, // 不宜搭配
}
3.1.4 搭配类型属性映射
| 搭配类型 | 中文名称 | 表情符号 | 主题颜色 |
|---|---|---|---|
| good | 黄金搭配 | ✅ | 绿色 |
| neutral | 可以搭配 | ⚠️ | 橙色 |
| bad | 不宜搭配 | ❌ | 红色 |
3.1.5 食材模型 (Ingredient)
class Ingredient {
final String id; // 唯一标识
final String name; // 食材名称
final IngredientCategory category; // 食材分类
final String description; // 食材描述
final List<String> nutrients; // 营养成分
final String benefits; // 食疗功效
final String emoji; // 表情符号
String get categoryName; // 分类中文名
Color get categoryColor; // 分类主题色
}
3.1.6 搭配模型 (IngredientPairing)
class IngredientPairing {
final String id; // 唯一标识
final Ingredient ingredient1; // 食材1
final Ingredient ingredient2; // 食材2
final PairingType type; // 搭配类型
final String reason; // 搭配说明
final String? recipe; // 推荐菜谱
final List<String> tags; // 标签列表
String get typeText; // 类型中文名
Color get typeColor; // 类型主题色
String get typeEmoji; // 类型表情
}
3.2 筛选过滤算法
3.2.1 过滤流程
3.2.2 过滤实现
List<IngredientPairing> get _filteredPairings {
var pairings = _pairings.toList();
// 搭配类型筛选
if (_selectedPairingType != null) {
pairings = pairings.where((p) => p.type == _selectedPairingType).toList();
}
// 食材分类筛选
if (_selectedCategory != null) {
pairings = pairings.where((p) {
return p.ingredient1.category == _selectedCategory ||
p.ingredient2.category == _selectedCategory;
}).toList();
}
// 关键词搜索
if (_searchQuery.isNotEmpty) {
pairings = pairings.where((p) {
return p.ingredient1.name.contains(_searchQuery) ||
p.ingredient2.name.contains(_searchQuery) ||
p.reason.contains(_searchQuery) ||
p.tags.any((tag) => tag.contains(_searchQuery));
}).toList();
}
// 按类型排序:黄金 > 可以 > 不宜
pairings.sort((a, b) {
final order = {PairingType.good: 0, PairingType.neutral: 1, PairingType.bad: 2};
return order[a.type]!.compareTo(order[b.type]!);
});
return pairings;
}
3.3 详情弹窗设计
3.3.1 弹窗结构
3.3.2 弹窗实现
void _showPairingDetail(IngredientPairing pairing) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (context) {
return DraggableScrollableSheet(
initialChildSize: 0.6,
minChildSize: 0.4,
maxChildSize: 0.9,
expand: false,
builder: (context, scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
// 食材展示区
// 搭配说明区
// 推荐菜谱区
// 食材信息区
],
),
);
},
);
},
);
}
3.4 页面结构设计
3.4.1 主页面布局
3.5 状态管理
3.5.1 核心状态变量
class _IngredientPairingPageState extends State<IngredientPairingPage> {
final List<Ingredient> _ingredients = []; // 所有食材
final List<IngredientPairing> _pairings = []; // 所有搭配
String _searchQuery = ''; // 搜索关键词
IngredientCategory? _selectedCategory; // 选中的分类筛选
PairingType? _selectedPairingType; // 选中的类型筛选
}
四、UI设计规范
4.1 配色方案
应用采用绿色主题风格,体现健康饮食的理念:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | Green | AppBar、按钮、强调 |
| 黄金搭配 | Green | 黄金搭配标识 |
| 可以搭配 | Orange | 可以搭配标识 |
| 不宜搭配 | Red | 不宜搭配标识 |
| 肉类 | Red | 肉类食材标识 |
| 蔬菜 | Green | 蔬菜食材标识 |
| 海鲜 | Blue | 海鲜食材标识 |
4.2 搭配类型样式
4.2.1 类型标签
| 类型 | 表情 | 颜色 | 说明 |
|---|---|---|---|
| 黄金搭配 | ✅ | 绿色 | 营养互补,推荐搭配 |
| 可以搭配 | ⚠️ | 橙色 | 可以搭配,注意事项 |
| 不宜搭配 | ❌ | 红色 | 不建议同食,影响健康 |
4.2.2 食材圆形图标
┌─────────────────┐
│ 🥩 │ ← 食材表情
│ │
│ 彩色圆形背景 │ ← 分类对应颜色
│ 彩色圆形边框 │
└─────────────────┘
4.3 组件规范
4.3.1 搭配卡片
┌─────────────────────────────────────────────────────────────┐
│ [🥩猪肉] ✅ 黄金搭配 [🥬白菜] │
│ │
│ 猪肉与白菜搭配,荤素结合,营养均衡。白菜的清香可以... │
│ │
│ [经典搭配] [家常菜] │
└─────────────────────────────────────────────────────────────┘
4.3.2 统计栏
┌─────────────────────────────────────────────────────────────┐
│ ✅ 黄金搭配 ⚠️ 可以搭配 ❌ 不宜搭配 │
│ 8组 1组 3组 │
└─────────────────────────────────────────────────────────────┘
4.3.3 详情弹窗
┌─────────────────────────────────────────────────────────────┐
│ ─────── │
│ │
│ 🥩 ✅ 🥬 │
│ 猪肉 黄金搭配 白菜 │
│ 肉类 蔬菜 │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ℹ️ 搭配说明 │ │
│ │ 猪肉与白菜搭配,荤素结合,营养均衡... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 🍴 推荐菜谱 │ │
│ │ 白菜炖猪肉、猪肉白菜饺子 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ [经典搭配] [家常菜] │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 🥩 猪肉 │ │ 🥬 白菜 │ │
│ │ 常见肉类 │ │ 冬季当家菜 │ │
│ │ [蛋白质][脂肪] │ │ [维生素C][膳食纤维]│ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
4.4 交互设计
4.4.1 操作方式
| 操作 | 手势 | 效果 |
|---|---|---|
| 查看详情 | 点击卡片 | 弹出详情弹窗 |
| 筛选分类 | 点击FilterChip | 按食材分类过滤 |
| 筛选类型 | 点击筛选菜单 | 按搭配类型过滤 |
| 搜索 | 输入关键词 | 实时过滤 |
| 关闭详情 | 下滑/点击外部 | 关闭弹窗 |
五、核心功能实现
5.1 主页面构建
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('食材搭配'),
actions: [
PopupMenuButton<PairingType?>(
icon: const Icon(Icons.filter_list),
onSelected: (value) {
setState(() {
_selectedPairingType = value;
});
},
itemBuilder: (context) => [
const PopupMenuItem(value: null, child: Text('全部类型')),
const PopupMenuItem(value: PairingType.good, child: Text('✅ 黄金搭配')),
const PopupMenuItem(value: PairingType.neutral, child: Text('⚠️ 可以搭配')),
const PopupMenuItem(value: PairingType.bad, child: Text('❌ 不宜搭配')),
],
),
],
),
body: Column(
children: [
_buildCategoryChips(),
_buildSearchBar(),
_buildStatisticsBar(),
Expanded(
child: _filteredPairings.isEmpty
? _buildEmptyState()
: _buildPairingsList(),
),
],
),
);
}
5.2 分类筛选条
Widget _buildCategoryChips() {
return Container(
height: 50,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: ListView(
scrollDirection: Axis.horizontal,
children: [
FilterChip(
label: const Text('全部'),
selected: _selectedCategory == null,
onSelected: (selected) {
setState(() {
_selectedCategory = null;
});
},
),
...IngredientCategory.values.map((category) {
return FilterChip(
label: Text(categoryName),
selected: _selectedCategory == category,
selectedColor: categoryColor.withValues(alpha: 0.2),
onSelected: (selected) {
setState(() {
_selectedCategory = selected ? category : null;
});
},
);
}),
],
),
);
}
5.3 统计栏
Widget _buildStatisticsBar() {
final goodCount = _pairings.where((p) => p.type == PairingType.good).length;
final neutralCount = _pairings.where((p) => p.type == PairingType.neutral).length;
final badCount = _pairings.where((p) => p.type == PairingType.bad).length;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('✅', '黄金搭配', goodCount, Colors.green),
_buildStatItem('⚠️', '可以搭配', neutralCount, Colors.orange),
_buildStatItem('❌', '不宜搭配', badCount, Colors.red),
],
);
}
5.4 详情弹窗
void _showPairingDetail(IngredientPairing pairing) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return DraggableScrollableSheet(
initialChildSize: 0.6,
minChildSize: 0.4,
maxChildSize: 0.9,
expand: false,
builder: (context, scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
// 食材展示区
Row(
children: [
_buildIngredientCircle(pairing.ingredient1),
// 搭配类型标签
_buildIngredientCircle(pairing.ingredient2),
],
),
// 搭配说明区
// 推荐菜谱区
// 食材信息区
],
),
);
},
);
},
);
}
5.5 食材圆形图标
Widget _buildIngredientCircle(Ingredient ingredient) {
return Column(
children: [
Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: ingredient.categoryColor.withValues(alpha: 0.2),
shape: BoxShape.circle,
border: Border.all(
color: ingredient.categoryColor,
width: 2,
),
),
child: Center(
child: Text(ingredient.emoji, style: const TextStyle(fontSize: 36)),
),
),
Text(ingredient.name, style: const TextStyle(fontWeight: FontWeight.bold)),
Text(ingredient.categoryName, style: TextStyle(color: ingredient.categoryColor)),
],
);
}
六、食材搭配知识拓展
6.1 食材搭配原则
6.2 常见食材相克
| 食材组合 | 相克原因 | 建议 |
|---|---|---|
| 菠菜 + 豆腐 | 草酸与钙形成草酸钙 | 菠菜焯水后可同食 |
| 螃蟹 + 柿子 | 形成胃结石 | 间隔2小时以上 |
| 虾 + 维C | 可能产生砷化合物 | 避免大量同食 |
| 牛奶 + 柠檬 | 蛋白质凝固 | 分开食用 |
| 萝卜 + 人参 | 功效相抵 | 避免同食 |
6.3 黄金搭配推荐
| 食材组合 | 搭配优势 | 推荐菜品 |
|---|---|---|
| 猪肉 + 白菜 | 荤素搭配,营养均衡 | 白菜炖猪肉 |
| 西红柿 + 鸡蛋 | 蛋白质与番茄红素互补 | 西红柿炒蛋 |
| 牛肉 + 胡萝卜 | 脂溶性维生素更易吸收 | 胡萝卜炖牛肉 |
| 豆腐 + 鱼 | 动植物蛋白互补 | 鱼头豆腐汤 |
| 螃蟹 + 生姜 | 中和寒性,去腥增香 | 清蒸螃蟹配姜醋 |
6.4 食材分类营养特点
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 数据管理
| 功能 | 说明 |
|---|---|
| SQLite存储 | 本地数据库存储搭配数据 |
| 自定义添加 | 用户自定义食材搭配 |
| 数据同步 | 云端数据备份同步 |
7.2.2 智能功能
| 功能 | 说明 |
|---|---|
| 营养计算 | 计算搭配营养成分 |
| 智能推荐 | 根据食材推荐搭配 |
| 饮食建议 | 个性化饮食建议 |
7.2.3 社交功能
| 功能 | 说明 |
|---|---|
| 搭配分享 | 分享搭配到社交平台 |
| 用户评价 | 用户对搭配评分 |
| 社区讨论 | 食材搭配话题讨论 |
八、注意事项
8.1 开发注意事项
-
颜色处理:使用
withValues(alpha:)替代已废弃的withOpacity() -
弹窗实现:使用
DraggableScrollableSheet实现可拖拽弹窗 -
列表展开语法:
if (condition) ...[widgets]正确使用展开操作符 -
筛选逻辑:分类筛选需检查两个食材是否都属于该分类
8.2 用户体验优化
💡 用户体验建议 💡
- 分类筛选直观便捷
- 搭配类型一目了然
- 详情展示清晰完整
- 弹窗交互流畅自然
8.3 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 弹窗无法拖拽 | DraggableScrollableSheet配置错误 | 检查expand参数 |
| 筛选无结果 | 过滤条件错误 | 检查筛选逻辑 |
| 颜色不显示 | 颜色值错误 | 检查categoryColor getter |
| 列表展开语法错误 | ...[]使用不当 |
检查语法结构 |
九、运行说明
9.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
9.2 运行命令
# 查看可用设备
flutter devices
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_ingredient_pairing.dart
# 运行到Windows
flutter run -d windows -t lib/main_ingredient_pairing.dart
# 代码分析
flutter analyze lib/main_ingredient_pairing.dart
十、总结
食材搭配应用通过完善的功能设计,帮助用户了解食材搭配的科学知识。应用支持八大食材分类,配以专属主题色彩,让食材分类更加直观。黄金搭配、可以搭配、不宜搭配三种类型,让用户快速了解搭配建议。
详情弹窗采用可拖拽设计,展示食材圆形图标、搭配说明、推荐菜谱和食材营养信息,信息展示完整清晰。统计栏实时显示各类型搭配数量,让用户对数据一目了然。搜索和筛选功能让用户快速定位目标搭配。
界面设计采用绿色主题风格,体现健康饮食的理念。食材圆形图标设计美观大方,搭配卡片边框颜色与类型对应,视觉层次分明。应用采用Material Design 3设计规范,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。
科学搭配,健康饮食,营养均衡,美味生活!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)