Flutter 框架跨平台鸿蒙开发 - 匿名夸夸应用
开源鸿蒙跨平台社区推出匿名夸夸社交应用,这是一款传递温暖的陌生人互动平台。应用采用Flutter开发,支持鸿蒙OS,核心功能包括随机匹配陌生人、5种类型的匿名夸奖(暖心/才华/颜值/性格/努力)、收件箱管理和发送记录。系统架构分为表现层、业务逻辑层和数据层,通过Material Design 3设计规范实现精美UI。项目采用Dart语言开发,包含匹配动画、消息列表等交互模块,旨在为用户创造安全、温
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图






1.1 应用简介
匿名夸夸是一款传递温暖的社交应用,核心定位在于让陌生人之间互相发送真诚的夸奖与鼓励。在这个快节奏的时代,每个人都渴望被看见、被认可。这款应用为用户提供一个匿名的平台,让温暖的话语在陌生人之间流动,传递善意与正能量。
应用采用"随机匹配+匿名互动"的策略实现陌生人社交,内置5种夸奖类型,每种类型配有独特emoji和颜色,用户可以随机匹配陌生人,选择夸奖类型并发送温暖的文字,支持收件箱和已发送记录管理功能。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 随机匹配 | 匹配陌生人用户 | 模拟匹配动画、Random |
| 发送夸奖 | 选择类型、编写内容 | FilterChip、TextField |
| 收件箱 | 查看收到的夸奖、标记已读 | ListView、Badge |
| 已发送 | 查看发送历史 | ListView、状态标记 |
| 数据统计 | 收发统计、类型分布 | Card、进度条 |
1.3 夸奖类型体系
| 类型 | 表情 | 颜色 | 适用场景 |
|---|---|---|---|
| 暖心 | 💝 | #FF6B9D | 温暖关怀、情感支持 |
| 才华 | ✨ | #9C27B0 | 能力认可、成就肯定 |
| 颜值 | 🌸 | #E91E63 | 外表赞美 |
| 性格 | 🌈 | #00BCD4 | 性格特点、品质 |
| 努力 | 💪 | #FF9800 | 奋斗精神、坚持 |
1.4 匿名用户设定
| 用户昵称 | 头像 | 标签 |
|---|---|---|
| 星星 | ⭐ | 温柔、善解人意 |
| 月亮 | 🌙 | 有趣、幽默 |
| 太阳 | ☀️ | 阳光、开朗 |
| 云朵 | ☁️ | 安静、细心 |
| 彩虹 | 🌈 | 活泼、可爱 |
| 雪花 | ❄️ | 纯洁、真诚 |
1.5 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 动画控制 | AnimationController | - |
| 目标平台 | 鸿蒙OS | API 21+ |
1.6 项目结构
lib/
└── main_anonymous_praise.dart
├── AnonymousPraiseApp # 应用入口
├── MainPraisePage # 主屏幕(底部导航)
├── MatchPage # 匹配页面
├── InboxPage # 收件箱页面
├── SentPage # 已发送页面
├── SettingsPage # 设置页面
├── PraiseMessage # 夸奖消息数据模型
├── PraiseType # 夸奖类型枚举
└── MatchUser # 匹配用户模型
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 匹配流程
2.4 发送与接收流程
三、核心模块设计
3.1 数据模型设计
3.1.1 夸奖消息模型 (PraiseMessage)
class PraiseMessage {
final String id; // 唯一标识
final String content; // 夸奖内容
final String fromUserId; // 发送者ID
final String fromUserName; // 发送者昵称(匿名)
final String toUserId; // 接收者ID
final DateTime createdAt; // 创建时间
final PraiseType type; // 夸奖类型
final bool isRead; // 是否已读
PraiseMessage({
required this.id,
required this.content,
required this.fromUserId,
required this.fromUserName,
required this.toUserId,
required this.createdAt,
required this.type,
this.isRead = false,
});
PraiseMessage copyWith({bool? isRead}) {
return PraiseMessage(
id: id,
content: content,
fromUserId: fromUserId,
fromUserName: fromUserName,
toUserId: toUserId,
createdAt: createdAt,
type: type,
isRead: isRead ?? this.isRead,
);
}
}
3.1.2 夸奖类型枚举 (PraiseType)
enum PraiseType {
warmth('暖心', '💝', Color(0xFFFF6B9D)),
talent('才华', '✨', Color(0xFF9C27B0)),
appearance('颜值', '🌸', Color(0xFFE91E63)),
personality('性格', '🌈', Color(0xFF00BCD4)),
effort('努力', '💪', Color(0xFFFF9800));
final String label;
final String emoji;
final Color color;
const PraiseType(this.label, this.emoji, this.color);
}
3.1.3 匹配用户模型 (MatchUser)
class MatchUser {
final String id; // 用户ID
final String nickname; // 昵称
final String avatar; // 头像emoji
final List<String> tags; // 标签列表
MatchUser({
required this.id,
required this.nickname,
required this.avatar,
required this.tags,
});
}
3.2 匹配动画实现
3.2.1 匹配进度动画
Future<void> _startMatching() async {
setState(() {
_isMatching = true;
_matchProgress = 0;
});
for (int i = 0; i <= 10; i++) {
await Future.delayed(const Duration(milliseconds: 200));
if (!mounted) return;
setState(() {
_matchProgress = i / 10;
});
}
widget.onMatch();
setState(() {
_isMatching = false;
});
}
3.2.2 脉冲动画
late AnimationController _pulseController;
void initState() {
super.initState();
_pulseController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500),
)..repeat(reverse: true);
}
ScaleTransition(
scale: Tween<double>(begin: 0.95, end: 1.05).animate(
CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut),
),
child: Container(...),
)
3.3 消息发送与接收
3.3.1 发送夸奖
void _sendPraise(String content, PraiseType type) {
if (_currentMatch == null) return;
final message = PraiseMessage(
id: DateTime.now().millisecondsSinceEpoch.toString(),
content: content,
fromUserId: 'me',
fromUserName: '我',
toUserId: _currentMatch!.id,
createdAt: DateTime.now(),
type: type,
);
setState(() {
_sentPraises.insert(0, message);
_currentMatch = null;
});
Future.delayed(const Duration(seconds: 1), () {
_receiveRandomPraise();
});
}
3.3.2 接收随机夸奖
void _receiveRandomPraise() {
final praises = [
'你真的很棒,继续保持自信!',
'你的善良让这个世界变得更美好!',
'你有着让人羡慕的乐观态度!',
// ...更多夸奖模板
];
final types = PraiseType.values;
final message = PraiseMessage(
id: DateTime.now().millisecondsSinceEpoch.toString(),
content: praises[_random.nextInt(praises.length)],
fromUserId: 'random',
fromUserName: '神秘人',
toUserId: 'me',
createdAt: DateTime.now(),
type: types[_random.nextInt(types.length)],
);
setState(() {
_receivedPraises.insert(0, message);
});
}
3.4 快速夸奖功能
final List<String> _quickPraises = [
'你今天看起来很棒!',
'你的笑容很治愈!',
'你是一个很温暖的人!',
'和你聊天很开心!',
'你很有才华!',
'继续加油,你很棒!',
];
Wrap(
spacing: 8,
runSpacing: 8,
children: _quickPraises.map((praise) {
return ActionChip(
label: Text(praise),
onPressed: () => _sendQuickPraise(praise),
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
);
}).toList(),
)
3.5 未读消息标记
NavigationDestination(
icon: Badge(
label: Text('${_receivedPraises.where((p) => !p.isRead).length}'),
isLabelVisible: _receivedPraises.any((p) => !p.isRead),
child: const Icon(Icons.inbox_outlined),
),
selectedIcon: const Icon(Icons.inbox),
label: '收件箱',
)
void _markAsRead(String id) {
final index = _receivedPraises.indexWhere((p) => p.id == id);
if (index != -1) {
setState(() {
_receivedPraises[index] = _receivedPraises[index].copyWith(isRead: true);
});
}
}
四、UI设计规范
4.1 配色方案
应用采用粉色主色调,营造温暖甜蜜的氛围:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #FF6B9D | AppBar、强调、按钮 |
| 暖心类型 | #FF6B9D | 温暖关怀类夸奖 |
| 才华类型 | #9C27B0 | 能力认可类夸奖 |
| 颜值类型 | #E91E63 | 外表赞美类夸奖 |
| 性格类型 | #00BCD4 | 性格品质类夸奖 |
| 努力类型 | #FF9800 | 奋斗精神类夸奖 |
4.2 字体规范
| 层级 | 字号 | 字重 | 用途 |
|---|---|---|---|
| 标题大字 | headlineMedium | Bold | 页面主标题 |
| 卡片标题 | titleMedium | Bold | 用户昵称 |
| 正文 | bodyLarge | Regular | 夸奖内容 |
| 辅助文字 | bodySmall | Regular | 时间、标签 |
4.3 组件规范
4.3.1 匹配页面初始状态
┌─────────────────────────────────┐
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ ← 可折叠AppBar
│ 💝 匿名夸夸 │
├─────────────────────────────────┤
│ │
│ ╭─────────╮ │
│ │ 👥 │ │ ← 脉冲动画图标
│ │ 渐变圆 │ │
│ ╰─────────╯ │
│ │
│ 发现陌生人 │ ← 主标题
│ 随机匹配一位陌生人,互相夸奖 │ ← 副标题
│ │
│ ┌─────────────────────────┐ │
│ │ 🔍 开始匹配 │ │ ← 主按钮
│ └─────────────────────────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ 💡 夸夸小贴士 │ │
│ │ • 真诚的夸奖最能打动人心 │ │
│ │ • 发现对方的闪光点 │ │
│ │ • 用温暖的语言传递善意 │ │
│ └─────────────────────────┘ │
└─────────────────────────────────┘
4.3.2 匹配中状态
┌─────────────────────────────────┐
│ │
│ ╭─────────╮ │
│ │ 🔍 │ │
│ │ ◐━━━━━━◑│ │ ← 进度环
│ ╰─────────╯ │
│ │
│ 正在匹配中... │
│ 正在为你寻找一位温暖的陌生人 │
│ │
└─────────────────────────────────┘
4.3.3 匹配成功状态
┌─────────────────────────────────┐
│ ╭─────────╮ │
│ │ ⭐ │ │ ← 用户头像
│ ╰─────────╯ │
│ 星星 │ ← 用户昵称
│ ┌────┐ ┌────┐ │
│ │温柔│ │善解人意│ │ ← 标签
│ └────┘ └────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ 选择夸奖类型 │ │
│ │ 💝暖心 ✨才华 🌸颜值 │ │ ← FilterChip
│ │ 🌈性格 💪努力 │ │
│ └─────────────────────────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ 写下你想说的话... │ │ ← 输入框
│ └─────────────────────────┘ │
│ │
│ 快速夸奖 │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │你很棒│ │笑容治愈│ │很温暖│ │
│ └──────┘ └──────┘ └──────┘ │
│ │
│ ┌────┐ ┌───────────────┐ │
│ │换一个│ │ ✉️ 发送夸奖 │ │
│ └────┘ └───────────────┘ │
└─────────────────────────────────┘
4.3.4 收件箱卡片
┌─────────────────────────────────┐
│ ┌──────┐ │
│ │ 💝 │ 匿名用户A 新 │ ← 类型图标 + 昵称 + 未读标记
│ └──────┘ 暖心 1小时前│ ← 类型 + 时间
│ │
│ 你的笑容真的很治愈,每次看到 │ ← 内容预览
│ 都觉得世界变得美好了一点! │
└─────────────────────────────────┘
4.4 交互设计
4.4.1 操作方式
| 操作 | 手势 | 效果 |
|---|---|---|
| 开始匹配 | 点击匹配按钮 | 启动匹配动画 |
| 选择类型 | 点击FilterChip | 切换夸奖类型 |
| 快速夸奖 | 点击ActionChip | 直接发送预设内容 |
| 发送夸奖 | 点击发送按钮 | 发送自定义内容 |
| 换一个 | 点击换一个按钮 | 重新匹配用户 |
| 查看详情 | 点击收件箱卡片 | 打开详情弹窗 |
五、核心功能实现
5.1 随机匹配用户
void _matchUser() {
final users = [
MatchUser(id: 'm1', nickname: '星星', avatar: '⭐', tags: ['温柔', '善解人意']),
MatchUser(id: 'm2', nickname: '月亮', avatar: '🌙', tags: ['有趣', '幽默']),
MatchUser(id: 'm3', nickname: '太阳', avatar: '☀️', tags: ['阳光', '开朗']),
MatchUser(id: 'm4', nickname: '云朵', avatar: '☁️', tags: ['安静', '细心']),
MatchUser(id: 'm5', nickname: '彩虹', avatar: '🌈', tags: ['活泼', '可爱']),
MatchUser(id: 'm6', nickname: '雪花', avatar: '❄️', tags: ['纯洁', '真诚']),
];
setState(() {
_currentMatch = users[_random.nextInt(users.length)];
});
}
5.2 时间格式化
String _formatTime(DateTime time) {
final now = DateTime.now();
final diff = now.difference(time);
if (diff.inMinutes < 60) {
return '${diff.inMinutes}分钟前';
} else if (diff.inHours < 24) {
return '${diff.inHours}小时前';
} else if (diff.inDays < 7) {
return '${diff.inDays}天前';
} else {
return '${time.month}月${time.day}日';
}
}
5.3 详情弹窗
void _showPraiseDetail(PraiseMessage praise, BuildContext context) {
onMarkAsRead(praise.id);
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return DraggableScrollableSheet(
initialChildSize: 0.6,
maxChildSize: 0.9,
minChildSize: 0.3,
expand: false,
builder: (context, scrollController) {
return Container(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
// 类型图标
Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: praise.type.color.withValues(alpha: 0.2),
shape: BoxShape.circle,
),
child: Center(
child: Text(praise.type.emoji, style: const TextStyle(fontSize: 40)),
),
),
// 发送者信息
Text('来自 ${praise.fromUserName}'),
// 夸奖内容
Container(
decoration: BoxDecoration(
color: praise.type.color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(16),
),
child: Text(praise.content),
),
],
),
),
);
},
);
},
);
}
六、社交心理知识拓展
6.1 夸奖的心理效应
6.2 有效夸奖的要素
| 要素 | 说明 | 示例 |
|---|---|---|
| 具体性 | 指出具体行为或特质 | “你的演讲逻辑很清晰” |
| 真诚性 | 发自内心的认可 | 避免空洞的客套话 |
| 及时性 | 在合适的时机给予 | 行为发生后及时反馈 |
| 适度性 | 不过分夸张 | 符合实际情况 |
6.3 匿名社交的优势
| 优势 | 说明 |
|---|---|
| 降低社交压力 | 无需担心身份暴露 |
| 促进真诚表达 | 更容易说出真心话 |
| 减少偏见影响 | 不以外表判断 |
| 建立纯粹连接 | 基于内容而非身份 |
6.4 正向心理学视角
七、扩展功能规划
7.1 后续版本规划
7.2 功能扩展建议
7.2.1 社交功能
| 功能 | 说明 |
|---|---|
| 好友系统 | 添加喜欢的陌生人为好友 |
| 持续对话 | 与匹配用户持续聊天 |
| 互夸机制 | 双方互相发送夸奖 |
7.2.2 激励系统
| 功能 | 说明 |
|---|---|
| 成就徽章 | 发送/收到一定数量夸奖解锁 |
| 每日任务 | 每天发送夸奖获得奖励 |
| 排行榜 | 温暖指数排名 |
7.2.3 内容丰富
| 功能 | 说明 |
|---|---|
| 夸奖模板 | 更多场景化模板 |
| 图片夸奖 | 支持发送图片 |
| 语音夸奖 | 支持语音消息 |
八、注意事项
8.1 开发注意事项
-
动画释放:在dispose中释放AnimationController
-
异步安全:使用mounted检查避免内存泄漏
-
状态不可变:使用copyWith创建新对象更新状态
-
随机种子:使用固定Random实例保证随机性
-
Badge更新:未读数量变化时触发重建
8.2 用户体验优化
💝 用户体验建议 💝
- 匹配动画流畅,增强期待感
- 快速夸奖降低表达门槛
- 未读标记醒目,不遗漏温暖
- 详情弹窗可拖拽,灵活查看
8.3 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 匹配动画卡顿 | 主线程阻塞 | 使用Future.delayed异步 |
| 未读标记不更新 | 未触发setState | 调用setState刷新 |
| 动画不停止 | Controller未释放 | dispose中调用dispose |
| 详情弹窗无法拖拽 | expand参数错误 | 设置expand: false |
九、运行说明
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_anonymous_praise.dart
# 运行到Windows
flutter run -d windows -t lib/main_anonymous_praise.dart
# 代码分析
flutter analyze lib/main_anonymous_praise.dart
十、总结
匿名夸夸应用通过"随机匹配+匿名互动"的策略,为用户提供一个传递温暖的社交平台。应用内置5种夸奖类型,每种配有独特emoji和颜色,用户可以随机匹配陌生人,选择类型并发送真诚的夸奖,同时也能收到来自陌生人的温暖话语。
应用的核心亮点是"双向温暖"机制——用户发送夸奖后,会在短时间内收到来自"神秘人"的回复夸奖,形成善意的正向循环。匹配页面采用脉冲动画和进度环动画,增强用户的期待感和仪式感。快速夸奖功能降低表达门槛,让用户轻松传递温暖。
收件箱页面支持未读标记和详情查看,已发送页面记录用户的善意足迹。设置页面展示收发统计,让用户看到自己传递和收获的温暖数量。应用采用Material Design 3设计规范,粉色主色调营造温暖甜蜜的氛围,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。
让温暖传递,让善意流动!
更多推荐




所有评论(0)