Flutter 框架跨平台鸿蒙开发 - 专注森林
运行效果图专注森林是一款创新的专注力管理应用,灵感来源于经典的Forest应用。应用将专注过程游戏化,用户在专注时种植虚拟树木,如果分心放弃,树木就会枯萎。通过这种正向激励机制,帮助用户培养专注习惯,同时积累属于自己的虚拟森林。应用以绿色为主色调,营造自然清新的视觉体验。涵盖专注计时、森林展示、数据统计、个性设置四大模块,支持8种树木类型和4种专注时长,通过树木成长动画和枯萎机制增强用户的专注动力
专注森林应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
专注森林是一款创新的专注力管理应用,灵感来源于经典的Forest应用。应用将专注过程游戏化,用户在专注时种植虚拟树木,如果分心放弃,树木就会枯萎。通过这种正向激励机制,帮助用户培养专注习惯,同时积累属于自己的虚拟森林。
应用以绿色为主色调,营造自然清新的视觉体验。涵盖专注计时、森林展示、数据统计、个性设置四大模块,支持8种树木类型和4种专注时长,通过树木成长动画和枯萎机制增强用户的专注动力。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 专注计时 | 倒计时专注模式 | Timer定时器 |
| 树木成长 | 实时成长动画 | AnimationController |
| 枯萎机制 | 放弃导致枯萎 | 状态判定逻辑 |
| 森林展示 | 已种树木展示 | GridView网格 |
| 数据统计 | 专注时长统计 | CustomPainter图表 |
| 树种选择 | 多种树木类型 | 枚举配置 |
1.3 树木类型系统
| 序号 | 树种名称 | Emoji | 颜色 | 最短时长 | 最长时长 |
|---|---|---|---|---|---|
| 1 | 橡树 | 🌳 | #4CAF50 | 25分钟 | 60分钟 |
| 2 | 松树 | 🌲 | #2E7D32 | 30分钟 | 90分钟 |
| 3 | 樱花 | 🌸 | #E91E63 | 20分钟 | 45分钟 |
| 4 | 枫树 | 🍁 | #FF5722 | 25分钟 | 75分钟 |
| 5 | 竹子 | 🎋 | #8BC34A | 15分钟 | 30分钟 |
| 6 | 棕榈 | 🌴 | #009688 | 35分钟 | 120分钟 |
| 7 | 圣诞树 | 🎄 | #1B5E20 | 40分钟 | 150分钟 |
| 8 | 盆栽 | 🪴 | #66BB6A | 10分钟 | 20分钟 |
1.4 树木成长阶段
| 序号 | 阶段名称 | Emoji | 进度范围 |
|---|---|---|---|
| 1 | 种子 | 🌱 | 0% - 20% |
| 2 | 幼苗 | 🌿 | 20% - 50% |
| 3 | 成长中 | 🌱 | 50% - 100% |
| 4 | 成熟 | 🌳 | 100% |
| 5 | 枯萎 | 🥀 | 放弃后 |
1.5 专注时长选项
| 序号 | 时长名称 | 分钟数 | 图标 |
|---|---|---|---|
| 1 | 短时专注 | 15分钟 | timer_10 |
| 2 | 中等专注 | 25分钟 | timer |
| 3 | 长时专注 | 45分钟 | timer_3 |
| 4 | 超长专注 | 60分钟 | timer_s |
1.6 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 定时器 | Timer | - |
| 动画控制 | AnimationController | - |
| 目标平台 | 鸆蒙OS / Web | API 21+ |
1.7 项目结构
lib/
└── main_focus_forest.dart
├── FocusForestApp # 应用入口
├── TreeType # 树种类型枚举
├── TreeState # 树木状态枚举
├── FocusDuration # 专注时长枚举
├── Tree # 树木数据模型
├── FocusSession # 专注记录模型
├── FocusForestHomePage # 主页面(底部导航)
├── _buildFocusPage # 专注页面
├── _buildForestPage # 森林页面
├── _buildStatsPage # 统计页面
├── _buildSettingsPage # 设置页面
└── WeeklyFocusPainter # 周图表绘制器
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 专注流程图
2.4 树木成长流程
三、核心模块设计
3.1 数据模型设计
3.1.1 树种类型枚举 (TreeType)
enum TreeType {
oak('橡树', '🌳', Color(0xFF4CAF50), 25, 60),
pine('松树', '🌲', Color(0xFF2E7D32), 30, 90),
cherry('樱花', '🌸', Color(0xFFE91E63), 20, 45),
maple('枫树', '🍁', Color(0xFFFF5722), 25, 75),
bamboo('竹子', '🎋', Color(0xFF8BC34A), 15, 30),
palm('棕榈', '🌴', Color(0xFF009688), 35, 120),
christmas('圣诞树', '🎄', Color(0xFF1B5E20), 40, 150),
bonsai('盆栽', '🪴', Color(0xFF66BB6A), 10, 20);
final String label; // 树种名称
final String emoji; // 代表表情
final Color color; // 主题颜色
final int minMinutes; // 最短专注时长
final int maxMinutes; // 最长专注时长
}
3.1.2 树木状态枚举 (TreeState)
enum TreeState {
seed('种子', '🌱'),
sprout('幼苗', '🌿'),
growing('成长中', '🌱'),
mature('成熟', '🌳'),
dead('枯萎', '🥀');
final String label; // 状态名称
final String emoji; // 代表表情
}
3.1.3 树木模型 (Tree)
class Tree {
final String id; // 唯一标识
final TreeType type; // 树种类型
TreeState state; // 当前状态
final DateTime plantedAt; // 种植时间
final int targetMinutes; // 目标时长
int elapsedSeconds; // 已过秒数
bool isAlive; // 是否存活
double growthProgress; // 成长进度
int get elapsedMinutes; // 已过分钟数
double get progress; // 完成进度
void updateState() {
if (!isAlive) {
state = TreeState.dead;
return;
}
final progress = this.progress;
if (progress < 0.2) state = TreeState.seed;
else if (progress < 0.5) state = TreeState.sprout;
else if (progress < 1.0) state = TreeState.growing;
else state = TreeState.mature;
}
}
3.1.4 专注记录模型 (FocusSession)
class FocusSession {
final String id; // 唯一标识
final DateTime startTime; // 开始时间
final DateTime? endTime; // 结束时间
final int durationMinutes; // 专注时长
final bool completed; // 是否完成
final TreeType treeType; // 树种类型
}
3.1.5 树种时长分布
3.2 页面结构设计
3.2.1 主页面布局
3.2.2 专注页面结构
3.2.3 森林页面结构
3.3 树木成长计算
四、UI设计规范
4.1 配色方案
应用以绿色为主色调,营造自然清新的视觉体验:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #4CAF50 (Green) | 导航、强调元素 |
| 深绿 | #2E7D32 | 渐变过渡 |
| 浅绿 | #81C784 | 背景渐变 |
| 背景白 | #FFFFFF | 卡片背景 |
| 文字灰 | #9E9E9E | 次要文字 |
4.2 树种配色
| 树种 | 色值 | 视觉效果 |
|---|---|---|
| 橡树 | #4CAF50 | 自然绿色 |
| 松树 | #2E7D32 | 深邃绿色 |
| 樱花 | #E91E63 | 浪漫粉色 |
| 枫树 | #FF5722 | 温暖橙色 |
| 竹子 | #8BC34A | 清新浅绿 |
| 棕榈 | #009688 | 热带青色 |
| 圣诞树 | #1B5E20 | 浓郁深绿 |
| 盆栽 | #66BB6A | 柔和绿色 |
4.3 状态配色
| 状态 | 色值 | 视觉效果 |
|---|---|---|
| 成长中 | 树种色 | 生机勃勃 |
| 成熟 | 树种色 | 完成状态 |
| 枯萎 | #9E9E9E | 灰暗无光 |
4.4 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 倒计时 | 56px | Bold | 树种色 |
| 状态标签 | 16px | SemiBold | 树种色 |
| 页面标题 | 20px | Bold | #000000 |
| 树种名称 | 12px | Medium | 树种色 |
| 时长文字 | 14px | Medium | #666666 |
4.5 组件规范
4.5.1 专注界面
┌─────────────────────────────────────┐
│ │
│ ✨ 🌿 ✨ │
│ │
│ 🌳 │
│ │
│ 25:00 │
│ [ 成长中 ] │
│ │
│ ████████████░░░░░░░░░░░░ │
│ │
└─────────────────────────────────────┘
4.5.2 时长选择器
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ ⏱️ │ │ ⏱️ │ │ ⏱️ │ │ ⏱️ │
│ 15分钟 │ │ 25分钟 │ │ 45分钟 │ │ 60分钟 │
│ 短时专注 │ │ 中等专注 │ │ 长时专注 │ │ 超长专注 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
4.5.3 树种选择器
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ 🌳 │ │ 🌲 │ │ 🌸 │ │ 🍁 │
│ 橡树 │ │ 松树 │ │ 樱花 │ │ 枫树 │
└────────┘ └────────┘ └────────┘ └────────┘
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ 🎋 │ │ 🌴 │ │ 🎄 │ │ 🪴 │
│ 竹子 │ │ 棕榈 │ │ 圣诞树 │ │ 盆栽 │
└────────┘ └────────┘ └────────┘ └────────┘
4.5.4 森林卡片
┌─────────────────┐
│ 🌳 │
│ 橡树 │
│ 25分钟 │
└─────────────────┘
4.5.5 完成弹窗
┌─────────────────────────────────────┐
│ 🎉 │
│ 专注完成! │
│ 成功种植了一棵橡树 │
│ │
│ ⏱️ 25分钟 🌳 15棵 │
│ │
│ [ 太棒了! ] │
└─────────────────────────────────────┘
五、核心功能实现
5.1 专注计时器实现
void _startFocus() {
setState(() {
_isFocusing = true;
_currentTree = Tree(
id: 'tree_${DateTime.now().millisecondsSinceEpoch}',
type: _selectedTreeType,
plantedAt: DateTime.now(),
targetMinutes: _selectedDuration,
);
});
_treeAnimationController.forward();
_startFocusTimer();
}
void _startFocusTimer() {
_focusTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_currentTree == null) {
timer.cancel();
return;
}
setState(() {
_currentTree!.elapsedSeconds++;
_currentTree!.growthProgress = _currentTree!.progress;
_currentTree!.updateState();
});
if (_currentTree!.progress >= 1.0) {
_completeFocus();
}
});
}
5.2 完成专注实现
void _completeFocus() {
_focusTimer?.cancel();
setState(() {
if (_currentTree != null) {
_currentTree!.isAlive = true;
_currentTree!.state = TreeState.mature;
_forest.insert(0, _currentTree!);
_sessions.insert(0, FocusSession(
id: 'session_${DateTime.now().millisecondsSinceEpoch}',
startTime: _currentTree!.plantedAt,
endTime: DateTime.now(),
durationMinutes: _currentTree!.targetMinutes,
completed: true,
treeType: _currentTree!.type,
));
_totalFocusMinutes += _currentTree!.targetMinutes;
_totalTrees++;
}
_isFocusing = false;
_currentTree = null;
});
_showCompletionDialog();
}
5.3 枯萎机制实现
void _witherTree() {
_focusTimer?.cancel();
setState(() {
if (_currentTree != null) {
_currentTree!.isAlive = false;
_currentTree!.state = TreeState.dead;
_forest.insert(0, _currentTree!);
_sessions.insert(0, FocusSession(
id: 'session_${DateTime.now().millisecondsSinceEpoch}',
startTime: _currentTree!.plantedAt,
endTime: DateTime.now(),
durationMinutes: _currentTree!.elapsedMinutes,
completed: false,
treeType: _currentTree!.type,
));
_witheredTrees++;
}
_isFocusing = false;
_currentTree = null;
});
}
5.4 树木状态更新
void updateState() {
if (!isAlive) {
state = TreeState.dead;
return;
}
final progress = this.progress;
if (progress < 0.2) {
state = TreeState.seed;
} else if (progress < 0.5) {
state = TreeState.sprout;
} else if (progress < 1.0) {
state = TreeState.growing;
} else {
state = TreeState.mature;
}
}
5.5 时间格式化
String _formatTime(int seconds) {
if (seconds < 0) seconds = 0;
final minutes = seconds ~/ 60;
final secs = seconds % 60;
return '${minutes.toString().padLeft(2, '0')}:${secs.toString().padLeft(2, '0')}';
}
六、树木成长系统
6.1 成长阶段判定
6.2 树种解锁条件
6.3 动画效果
七、交互设计
7.1 开始专注流程
7.2 放弃专注流程
7.3 森林浏览流程
八、扩展功能规划
8.1 后续版本规划
8.2 功能扩展建议
8.2.1 成就系统
成就类型:
- 累计种植树木数量
- 连续专注天数
- 单次专注时长
- 特殊树种收集
8.2.2 白噪音功能
音效类型:
- 雨声
- 森林鸟鸣
- 海浪声
- 咖啡馆环境
8.2.3 社交功能
社交特性:
- 分享森林截图
- 好友排行榜
- 共同专注
- 森林参观
九、注意事项
9.1 开发注意事项
-
定时器管理:Timer需要在dispose时取消
-
动画释放:AnimationController需要在dispose时释放
-
状态更新:专注中禁止切换页面
-
树种限制:根据时长限制可选树种
-
数据持久化:考虑使用本地存储保存数据
9.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 计时器不停止 | Timer未取消 | 在dispose中取消 |
| 树木状态错误 | 进度计算错误 | 检查progress计算 |
| 动画卡顿 | Controller未释放 | 在dispose中释放 |
| 树种选择异常 | 时长限制错误 | 检查minMinutes |
9.3 设计理念
🌲 设计理念 🌲
每一棵树都代表着一段专注时光,
每一次放弃都会让树木枯萎。
通过游戏化的方式,
让专注变得有趣,
让坚持变得有意义。
用心专注,种出一片森林,
收获属于自己的专注时光。
十、运行说明
10.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸆蒙OS | API 21+ |
10.2 运行命令
# 查看可用设备
flutter devices
# 运行到Web服务器
flutter run -d web-server -t lib/main_focus_forest.dart --web-port 8114
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_focus_forest.dart
# 运行到Edge浏览器
flutter run -d edge lib/main_focus_forest.dart
# 代码分析
flutter analyze lib/main_focus_forest.dart
十一、总结
专注森林应用通过专注计时、树木成长、森林展示、数据统计四大模块,为用户提供了一个游戏化的专注力管理平台。应用支持8种树木类型和4种专注时长,通过树木成长动画和枯萎机制增强用户的专注动力。
核心功能涵盖专注计时、树木成长、枯萎机制、森林展示、数据统计五大模块。计时系统通过Timer实现精确的倒计时;成长系统根据进度更新树木状态;枯萎机制在用户放弃时标记树木死亡;森林系统展示所有已种树木;统计系统提供周度图表和树种分布。
应用采用Material Design 3设计规范,以绿色为主色调,营造自然清新的视觉体验。通过本应用,希望能够帮助用户培养专注习惯,在专注中收获属于自己的森林。
专注时种树,分心树就枯萎
更多推荐


所有评论(0)