Flutter 框架跨平台鸿蒙开发 - 成就系统
运行效果图成就系统是一款独特的人生里程碑记录应用,将生活中的"第一次"游戏化,让用户能够记录、回顾并珍藏那些值得铭记的时刻。第一次熬夜、第一次告白、第一次独自旅行……这些看似平凡的瞬间,恰恰是生命中最珍贵的里程碑。应用以金色为主色调,象征成就与荣耀。界面设计借鉴了游戏成就系统的视觉风格,采用徽章墙的形式展示所有成就。通过不同的稀有度区分成就的重要程度,从普通的灰色到传奇的金色,让用户能够直观地感受
成就系统应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
成就系统是一款独特的人生里程碑记录应用,将生活中的"第一次"游戏化,让用户能够记录、回顾并珍藏那些值得铭记的时刻。第一次熬夜、第一次告白、第一次独自旅行……这些看似平凡的瞬间,恰恰是生命中最珍贵的里程碑。
应用以金色为主色调,象征成就与荣耀。界面设计借鉴了游戏成就系统的视觉风格,采用徽章墙的形式展示所有成就。通过不同的稀有度区分成就的重要程度,从普通的灰色到传奇的金色,让用户能够直观地感受到每个成就的独特价值。用户可以通过点击未解锁的成就来解锁它,并为已解锁的成就添加专属回忆。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 成就墙 | 展示所有成就徽章 | GridView网格 |
| 分类浏览 | 六大成就分类 | 分类筛选 |
| 稀有度系统 | 四级稀有度区分 | 颜色编码 |
| 时间线 | 成就解锁历程 | 列表视图 |
| 统计分析 | 成就数据分析 | 图表展示 |
| 回忆记录 | 添加成就回忆 | 对话框表单 |
1.3 成就分类体系
应用将人生成就划分为六大类别:
| 分类 | 图标 | 颜色 | 典型成就 |
|---|---|---|---|
| 成长 | trending_up | #4CAF50 | 第一次熬夜、第一次说"不" |
| 情感 | favorite | #E91E63 | 第一次告白、第一次恋爱 |
| 冒险 | explore | #FF9800 | 第一次蹦极、第一次潜水 |
| 技能 | psychology | #2196F3 | 第一次骑车、第一次游泳 |
| 社交 | groups | #9C27B0 | 第一次演讲、第一次面试 |
| 生活 | home | #00BCD4 | 第一次做饭、第一次养宠物 |
1.4 稀有度等级
| 稀有度 | 颜色 | 点数倍率 | 典型成就 |
|---|---|---|---|
| 普通 | #9E9E9E | 1.0x | 第一次熬夜 |
| 稀有 | #2196F3 | 1.5x | 第一次独自旅行 |
| 史诗 | #9C27B0 | 2.0x | 第一次告白 |
| 传奇 | #FFD700 | 3.0x | 第一次蹦极 |
1.5 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 动画系统 | AnimationController | - |
| 目标平台 | 鸿蒙OS / Web | API 21+ |
1.6 项目结构
lib/
└── main_achievement_system.dart
├── AchievementSystemApp # 应用入口
├── AchievementCategory # 成就分类枚举
├── AchievementRarity # 稀有度枚举
├── Achievement # 成就模型
├── AchievementSystemHomePage # 主页面(底部导航)
├── _buildAchievementWall # 成就墙页面
├── _buildTimeline # 时间线页面
└── _buildStatistics # 统计页面
二、设计理念
2.1 成就系统可视化
2.2 成就稀有度模型
2.3 色彩体系
应用采用金色为主色调:
| 颜色类型 | 色值 | RGB | 用途 |
|---|---|---|---|
| 主色 | #FFD700 | 255,215,0 | 导航、按钮、强调 |
| 辅助色 | #FFA500 | 255,165,0 | 渐变、次要元素 |
| 成长色 | #4CAF50 | 76,175,80 | 成长类成就 |
| 情感色 | #E91E63 | 233,30,99 | 情感类成就 |
| 冒险色 | #FF9800 | 255,152,0 | 冒险类成就 |
| 技能色 | #2196F3 | 33,150,243 | 技能类成就 |
| 社交色 | #9C27B0 | 156,39,176 | 社交类成就 |
| 生活色 | #00BCD4 | 0,188,212 | 生活类成就 |
2.4 成就解锁流程
三、系统架构
3.1 整体架构图
3.2 类图设计
3.3 成就解锁流程
四、核心功能实现
4.1 成就分类枚举
定义六大成就分类:
enum AchievementCategory {
growth('成长', Icons.trending_up, Color(0xFF4CAF50)),
emotion('情感', Icons.favorite, Color(0xFFE91E63)),
adventure('冒险', Icons.explore, Color(0xFFFF9800)),
skill('技能', Icons.psychology, Color(0xFF2196F3)),
social('社交', Icons.groups, Color(0xFF9C27B0)),
life('生活', Icons.home, Color(0xFF00BCD4));
final String label;
final IconData icon;
final Color color;
const AchievementCategory(this.label, this.icon, this.color);
}
4.2 稀有度枚举
定义四级稀有度:
enum AchievementRarity {
common('普通', Color(0xFF9E9E9E), 1.0),
rare('稀有', Color(0xFF2196F3), 1.5),
epic('史诗', Color(0xFF9C27B0), 2.0),
legendary('传奇', Color(0xFFFFD700), 3.0);
final String label;
final Color color;
final double multiplier;
const AchievementRarity(this.label, this.color, this.multiplier);
}
4.3 成就模型
成就数据模型定义:
class Achievement {
final String id;
final String name;
final String description;
final AchievementCategory category;
final AchievementRarity rarity;
final IconData icon;
final bool isUnlocked;
final DateTime? unlockedAt;
final String? memory;
final int pointValue;
const Achievement({
required this.id,
required this.name,
required this.description,
required this.category,
required this.rarity,
required this.icon,
this.isUnlocked = false,
this.unlockedAt,
this.memory,
required this.pointValue,
});
Achievement copyWith({
bool? isUnlocked,
DateTime? unlockedAt,
String? memory,
}) {
return Achievement(
id: id,
name: name,
description: description,
category: category,
rarity: rarity,
icon: icon,
isUnlocked: isUnlocked ?? this.isUnlocked,
unlockedAt: unlockedAt ?? this.unlockedAt,
memory: memory ?? this.memory,
pointValue: pointValue,
);
}
}
4.4 成就徽章渲染
徽章组件的核心渲染逻辑:
Widget _buildAchievementBadge(Achievement achievement) {
final isUnlocked = achievement.isUnlocked;
return GestureDetector(
onTap: () {
if (isUnlocked) {
_showAddMemoryDialog(achievement);
} else {
_unlockAchievement(achievement.copyWith(
isUnlocked: true,
unlockedAt: DateTime.now(),
));
}
},
child: AnimatedBuilder(
animation: _shineAnimationController,
builder: (context, child) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
gradient: isUnlocked
? SweepGradient(
center: Alignment.center,
startAngle: _shineAnimationController.value * 2 * pi,
endAngle: (_shineAnimationController.value * 2 * pi) + pi / 2,
colors: [
achievement.rarity.color.withOpacity(0.1),
achievement.rarity.color.withOpacity(0.3),
achievement.rarity.color.withOpacity(0.1),
],
)
: null,
color: isUnlocked ? null : Colors.grey[200],
border: Border.all(
color: isUnlocked
? achievement.rarity.color.withOpacity(0.5)
: Colors.grey[300]!,
width: isUnlocked ? 2 : 1,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: isUnlocked
? RadialGradient(
colors: [
achievement.rarity.color,
achievement.rarity.color.withOpacity(0.6),
],
)
: null,
color: isUnlocked ? null : Colors.grey[400],
),
child: Icon(
isUnlocked ? achievement.icon : Icons.lock,
color: Colors.white,
size: 24,
),
),
Text(
isUnlocked ? achievement.name : '???',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: isUnlocked ? null : Colors.grey[500],
),
),
],
),
);
},
),
);
}
4.5 解锁动画
解锁时的弹性缩放动画:
ScaleTransition(
scale: Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _badgeAnimationController,
curve: Curves.elasticOut,
),
),
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
achievement.rarity.color,
achievement.rarity.color.withOpacity(0.5),
],
),
boxShadow: [
BoxShadow(
color: achievement.rarity.color.withOpacity(0.5),
blurRadius: 20,
spreadRadius: 5,
),
],
),
child: Icon(
achievement.icon,
size: 40,
color: Colors.white,
),
),
)
4.6 点数计算
成就点数的计算逻辑:
int get _totalPoints {
return _achievements
.where((a) => a.isUnlocked)
.fold(0, (sum, a) => sum + a.pointValue);
}
int get _unlockedCount {
return _achievements.where((a) => a.isUnlocked).length;
}
五、UI设计规范
5.1 配色方案
应用采用金色为主色调:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #FFD700 | 导航、按钮、强调 |
| 辅助色 | #FFA500 | 渐变、次要元素 |
| 成长色 | #4CAF50 | 成长类成就 |
| 情感色 | #E91E63 | 情感类成就 |
| 冒险色 | #FF9800 | 冒险类成就 |
| 技能色 | #2196F3 | 技能类成就 |
| 社交色 | #9C27B0 | 社交类成就 |
| 生活色 | #00BCD4 | 生活类成就 |
5.2 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 页面标题 | 28px | Bold | #FFFFFF |
| 分类标题 | 18px | Bold | 分类颜色 |
| 成就名称 | 11px | Bold | #000000 |
| 成就描述 | 14px | Regular | #666666 |
| 点数标签 | 10px | Bold | 稀有度颜色 |
5.3 组件规范
5.3.1 成就徽章
┌─────────────────┐
│ │
│ ┌─────┐ │
│ │ 🌙 │ │
│ └─────┘ │
│ 夜猫子初体验 │
│ +10 │
│ │
└─────────────────┘
5.3.2 时间线卡片
┌─────────────────────────────────────────┐
│ ●── 💗 勇敢的心 │
│ │ [情感] [史诗] │
│ │ 第一次向喜欢的人告白 │
│ │ "那是一个阳光明媚的下午..." │
│ │ 14:30 +50 │
└─────────────────────────────────────────┘
5.3.3 统计卡片
┌─────────────────────────────────────────┐
│ 总览 │
│ │
│ 🏆 520 🔓 12 🔒 12 │
│ 总成就点 已解锁 待解锁 │
│ │
│ ████████████░░░░░░ 50% │
└─────────────────────────────────────────┘
六、交互设计
6.1 成就墙交互
6.2 成就解锁流程
6.3 页面切换状态
七、数据分析
7.1 统计指标
| 统计项 | 计算方式 | 说明 |
|---|---|---|
| 总成就点 | 已解锁成就点数之和 | 总体成就值 |
| 已解锁数 | isUnlocked为true的数量 | 解锁进度 |
| 待解锁数 | isUnlocked为false的数量 | 剩余成就 |
| 完成度 | 已解锁数/总成就数 | 百分比进度 |
7.2 分类统计
Map<AchievementCategory, int> _calculateCategoryProgress() {
final progress = <AchievementCategory, int>{};
for (var category in AchievementCategory.values) {
final categoryAchievements = _achievements.where((a) => a.category == category);
final unlocked = categoryAchievements.where((a) => a.isUnlocked).length;
progress[category] = unlocked;
}
return progress;
}
7.3 稀有度分布
Map<AchievementRarity, int> _calculateRarityDistribution() {
final distribution = <AchievementRarity, int>{};
for (var rarity in AchievementRarity.values) {
distribution[rarity] = _achievements
.where((a) => a.rarity == rarity && a.isUnlocked)
.length;
}
return distribution;
}
7.4 时间分布分析
| 时间段 | 分析维度 | 应用价值 |
|---|---|---|
| 按周 | 周解锁数量 | 了解每周成就获取频率 |
| 按月 | 月解锁分布 | 了解月度成就模式 |
| 按季度 | 季度解锁趋势 | 了解长期成就趋势 |
| 按年 | 年度成就总结 | 了解年度成就概况 |
八、扩展功能规划
8.1 后续版本规划
8.2 功能扩展建议
8.2.1 自定义成就
支持用户创建自定义成就:
- 自定义成就名称和描述
- 选择分类和稀有度
- 设置解锁条件
- 自定义图标
8.2.2 成就分享
成就分享系统:
- 生成成就分享图片
- 分享到社交平台
- 成就卡片模板
- 分享统计报告
8.2.3 成就提醒
成就纪念日提醒:
- 解锁周年提醒
- 成就推荐提醒
- 未解锁成就提示
- 里程碑通知
九、注意事项
9.1 开发注意事项
-
动画控制:AnimationController需要在dispose时释放
-
状态管理:使用setState管理本地状态,注意刷新时机
-
性能优化:大量成就时注意列表性能,使用SliverList
-
用户体验:解锁动画要流畅,避免卡顿
9.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 徽章不显示 | 数据为空 | 检查_achievements |
| 颜色不正确 | 稀有度映射错误 | 检查AchievementRarity |
| 动画不播放 | 控制器未启动 | 检查forward调用 |
| 点数不更新 | 状态未刷新 | 检查setState |
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_achievement_system.dart --web-port 8129
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_achievement_system.dart
# 运行到Windows
flutter run -d windows -t lib/main_achievement_system.dart
# 代码分析
flutter analyze lib/main_achievement_system.dart
十一、总结
成就系统是一款独特的人生里程碑记录应用,将生活中的"第一次"游戏化,让用户能够记录、回顾并珍藏那些值得铭记的时刻。应用借鉴了游戏成就系统的视觉风格,采用徽章墙的形式展示所有成就,通过不同的稀有度区分成就的重要程度。
从技术实现来看,应用使用GridView构建徽章网格,通过AnimationController实现解锁动画和闪光效果,使用枚举类型定义分类和稀有度,实现了完整的成就记录和管理系统。六大分类和四级稀有度让成就系统更加丰富和有趣。
从用户体验来看,应用提供直观的徽章墙展示,让用户能够快速了解成就分布。通过点击徽章解锁成就,添加专属回忆,操作简单直观。时间线功能让用户能够回顾成就解锁历程,统计功能让用户了解整体成就进度。
应用不仅是一个成就记录工具,更是一个人生里程碑记录平台。它提醒我们:每一个"第一次"都值得被铭记;点击未解锁的徽章来解锁成就;为已解锁的成就添加专属回忆;稀有度越高,成就点数越多。在快节奏的现代生活中,成就系统为我们提供了一种记录和回顾人生重要时刻的方式。
记录人生中的每一个"第一次"
更多推荐

所有评论(0)