Flutter × OpenHarmony 实战:个人理财助手底部模块导航栏的设计与实现
Flutter × OpenHarmony 实战:个人理财助手底部模块导航栏的设计与实现
前言
在个人理财类 App 中,最核心的交互入口通常集中在首页底部,例如:账本、统计、资产、我的等模块。一个设计合理的模块选择器(底部导航栏),不仅决定了用户的第一印象,也直接影响整体产品的易用性。
本文基于 Flutter × OpenHarmony 跨端技术栈,实现一个适用于个人理财助手的 自定义底部模块选择器组件,并从架构设计、UI 组件拆解、状态管理三个层面进行完整解析,帮助你理解如何在真实项目中构建可复用的导航模块。

背景
在实际项目中,我遇到过两个典型问题:
- Flutter 自带的
BottomNavigationBar灵活性有限,样式定制度不高; - 在 OpenHarmony 设备上,需要更轻量、可控的 UI 组件,以适配不同尺寸与系统风格。
因此选择:
- 不使用系统默认导航组件;
- 通过 Row + Expanded + GestureDetector 自行构建一个模块选择器;
- 实现一个“业务驱动型”的导航组件,而非纯 UI 组件。
目标是做到:
一个完全可控、可主题化、可扩展的底部模块选择器。

Flutter × OpenHarmony 跨端开发介绍
为什么选择 Flutter × OpenHarmony?
| 维度 | 优势 |
|---|---|
| Flutter | 高性能 UI 渲染、声明式开发 |
| OpenHarmony | 国产系统生态、原生支持分布式 |
| 组合优势 | 一套代码,多端运行(手机/平板/鸿蒙设备) |
整体架构:
Flutter UI 层
↓
Dart 业务逻辑
↓
OpenHarmony 系统能力
在 OpenHarmony 中,Flutter 主要负责:
- 页面布局
- 状态管理
- 交互逻辑
而系统能力(文件、网络、通知)交给鸿蒙侧插件处理。
开发核心代码(详细解析)

下面是本文核心:模块选择器组件实现代码。
一、完整实现代码
/// 构建模块选择器(底部导航栏样式)
Widget _buildModuleSelector(ThemeData theme) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: theme.colorScheme.surfaceVariant,
),
child: Row(
children: FinanceModule.values.map((module) {
final isSelected = _currentModule == module;
return Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_currentModule = module;
});
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: isSelected
? theme.colorScheme.primary
: Colors.transparent,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
_getModuleIcon(module),
size: 24,
color: isSelected
? theme.colorScheme.onPrimary
: theme.colorScheme.onSurfaceVariant,
),
const SizedBox(height: 4),
Text(
_getModuleName(module),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: isSelected
? theme.colorScheme.onPrimary
: theme.colorScheme.onSurfaceVariant,
),
),
],
),
),
),
);
}).toList(),
),
),
);
}
二、模块枚举设计(业务建模)
首先是模块抽象:
enum FinanceModule {
account, // 账本
stats, // 统计
assets, // 资产
profile, // 我的
}
这是非常关键的一步:
不要直接写死 4 个按钮,而是用 枚举驱动 UI。
好处:
- 新增模块只改 enum
- UI 自动扩展
- 避免重复代码
三、整体布局结构解析
Container
└── Container(背景卡片)
└── Row(横向排列模块)
└── Expanded × N
└── GestureDetector
└── Column(图标 + 文本)
这是一个标准的自适应横向导航结构。
1. 外层 Container
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
)
作用:
- 给整个导航栏留边距
- 防止贴边影响美观
2. 背景卡片层
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: theme.colorScheme.surfaceVariant,
),
这一层实现了:
- 圆角卡片风格
- 自动适配深色/浅色主题
这是 Flutter 中非常推荐的写法:
完全基于 Theme,不写死颜色值。
四、模块循环渲染机制
FinanceModule.values.map((module) {
这行代码是整个组件的灵魂:
FinanceModule.values→ 所有模块- 每个模块生成一个按钮
这就是典型的:
数据驱动 UI(Data Driven UI)
五、等宽布局:Expanded
return Expanded(
child: ...
)
作用:
- 每个模块自动占 1/N 宽度
- 屏幕大小变化时自适应
在鸿蒙设备(平板、折叠屏)上尤其重要。
六、点击交互与状态切换
GestureDetector(
onTap: () {
setState(() {
_currentModule = module;
});
},
)
这里体现的是最基础的 Flutter 状态管理模型:
_currentModule:当前选中模块setState:触发 UI 重建
当点击某个模块时:
用户点击
→ 修改状态
→ 触发 rebuild
→ isSelected 变化
→ UI 高亮切换
七、选中态视觉逻辑
final isSelected = _currentModule == module;
后续所有样式都围绕这个布尔值展开:
背景色
color: isSelected
? theme.colorScheme.primary
: Colors.transparent,
图标颜色
color: isSelected
? theme.colorScheme.onPrimary
: theme.colorScheme.onSurfaceVariant,
文本颜色
color: isSelected
? theme.colorScheme.onPrimary
: theme.colorScheme.onSurfaceVariant,
这是一个非常标准的:
状态 → 样式映射模型(State → Style)
八、图标与文案解耦
Icon(_getModuleIcon(module))
Text(_getModuleName(module))
推荐实现方式:
IconData _getModuleIcon(FinanceModule module) {
switch (module) {
case FinanceModule.account:
return Icons.receipt_long;
case FinanceModule.stats:
return Icons.bar_chart;
case FinanceModule.assets:
return Icons.account_balance_wallet;
case FinanceModule.profile:
return Icons.person;
}
}
这样做的好处:
- UI 与业务语义解耦
- 后期可国际化 / 动态配置
心得
在这个组件的设计过程中,我总结了三点工程经验:
1. 不要迷信系统组件
系统自带组件适合 Demo,不适合真实项目。
真实项目需要:
- 可控样式
- 可扩展结构
- 可主题化设计
2. 一切 UI 都应该“数据驱动”
不要写:
Row(
children: [
Button1(),
Button2(),
Button3(),
]
)
而要写:
modules.map(renderButton)
这是工程级 Flutter 的核心思想。
3. 状态一定要“单一可信源”
_currentModule 是唯一状态源:
- 所有高亮逻辑围绕它
- 不产生多份冗余状态
这在后期接入 Provider / Riverpod / Bloc 时非常关键。
总结
本文基于 Flutter × OpenHarmony 实战场景,完整拆解了一个个人理财助手中 底部模块选择器组件 的设计与实现过程。
从工程角度看,这个组件具备:
- 枚举驱动的业务建模能力
- Theme 驱动的样式系统
- 状态驱动的交互逻辑
- 跨端适配的布局结构
它不仅是一个“导航栏”,本质上是一个:
可复用、可扩展、可维护的业务级 UI 组件模板。
在真实项目中,这种组件化思维,远比写几个页面更重要。
- 点赞
- 收藏
- 关注作者
评论(0)