Flutter 框架跨平台鸿蒙开发 - 故事接龙应用
摘要: 开源鸿蒙跨平台社区推出"故事接龙"应用,这是一款创意协作写作工具,用户可与陌生人共同创作故事。应用提供奇幻、科幻等6大主题,采用轮流接龙机制(每人限200字,最多10人参与),包含故事广场、创建、接龙、点赞等核心功能。技术栈基于Flutter框架,采用Material Design 3规范,包含完整的数据模型和交互流程,支持模拟陌生人参与。项目通过限制性规则保证创作多样
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图



1.1 应用简介
故事接龙是一款创意协作写作应用,核心理念是"与陌生人一起编织奇妙故事"。用户可以选择或创建故事主题,每人贡献一段文字,共同完成一部独一无二的作品。这种协作创作模式打破了传统写作的孤独感,让创意在陌生人之间流动,每一次接龙都是一次惊喜的相遇。
应用采用"轮流接龙"机制,每位参与者只能贡献一段文字(最多200字),故事最多由10人共同完成。这种限制既保证了故事的多样性,又避免了单方面主导,让每个声音都能被听见。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 故事广场 | 浏览进行中的故事 | ListView卡片展示 |
| 故事创建 | 选择主题、命名故事 | 底部弹窗表单 |
| 故事接龙 | 撰写下一段内容 | TextField输入 |
| 点赞互动 | 为精彩段落点赞 | 状态切换动画 |
| 陌生人模拟 | 模拟其他用户接龙 | Timer延迟触发 |
| 故事完结 | 达到上限自动完结 | 状态标记 |
1.3 故事主题体系
| 主题 | 图标 | 开篇示例 | 色彩 |
|---|---|---|---|
| 奇幻冒险 | 🐉 | 在遥远的东方,有一座被迷雾笼罩的神秘山峰… | 紫色 |
| 都市言情 | 💕 | 那是一个雨夜,她在咖啡店的角落独自坐着… | 粉色 |
| 科幻未来 | 🚀 | 2157年,人类终于收到了来自半人马座的信息… | 蓝色 |
| 悬疑推理 | 🔍 | 密室里只有一盏摇曳的烛火,桌上放着一封未拆的信… | 灰色 |
| 武侠江湖 | ⚔️ | 剑光一闪,白衣少年立于城门之上… | 棕色 |
| 童话世界 | 🧚 | 在彩虹的尽头,住着一位会唱歌的小精灵… | 绿色 |
1.4 接龙规则
┌─────────────────────────────────────────────────────────┐
│ 故事接龙规则 │
├─────────────────────────────────────────────────────────┤
│ ✓ 每人每次最多写200字 │
│ ✓ 每人只能接龙一次 │
│ ✓ 最多10人参与 │
│ ✓ 保持故事连贯性 │
│ ✓ 达到上限自动完结 │
└─────────────────────────────────────────────────────────┘
1.5 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 动画控制 | AnimationController | - |
| 目标平台 | 鸿蒙OS | API 21+ |
二、项目结构
lib/
├── main_story_relay.dart # 应用主入口(~1100行)
│ ├── StoryRelayApp # 根应用组件
│ ├── StorySegment # 故事段落模型
│ ├── Story # 故事模型
│ ├── StoryTheme # 故事主题
│ ├── MockUser # 模拟用户
│ └── StoryRelayHomePage # 主页面
三、数据模型
3.1 StorySegment 模型
class StorySegment {
final String id; // 段落唯一标识
final String content; // 段落内容
final String authorName; // 作者名称
final String authorAvatar; // 作者头像(emoji)
final DateTime createdAt; // 创建时间
int likes; // 点赞数
bool isLiked; // 当前用户是否已点赞
final int wordCount; // 字数统计
}
3.2 Story 模型
class Story {
final String id; // 故事唯一标识
String title; // 故事标题
String theme; // 故事主题
final List<StorySegment> segments; // 段落列表
final DateTime createdAt; // 创建时间
DateTime updatedAt; // 更新时间
int participantCount; // 参与人数
int maxParticipants; // 最大参与人数(10)
bool isCompleted; // 是否已完结
final String creatorName; // 创建者名称
}
3.3 StoryTheme 模型
class StoryTheme {
final String name; // 主题名称
final String icon; // 主题图标
final String opening; // 开篇示例
final Color color; // 主题色彩
}
3.4 MockUser 模型
class MockUser {
final String name; // 用户名称
final String avatar; // 用户头像
final String style; // 写作风格
}
四、核心功能实现
4.1 故事创建流程
4.2 接龙提交流程
4.3 陌生人模拟机制
void _simulateStrangerJoin(Story story) {
Future.delayed(const Duration(seconds: 5), () {
final random = Random();
final user = _mockUsers[random.nextInt(_mockUsers.length)];
final continuations = [
'然而,事情并没有想象中那么简单...',
'就在这时,一个神秘的身影出现...',
// 更多续写内容...
];
story.segments.add(StorySegment(
content: continuations[random.nextInt(continuations.length)],
authorName: user.name,
authorAvatar: user.avatar,
// ...
));
});
}
4.4 点赞交互
GestureDetector(
onTap: () {
setState(() {
if (segment.isLiked) {
segment.likes--;
} else {
segment.likes++;
}
segment.isLiked = !segment.isLiked;
});
},
child: Row(
children: [
Icon(
segment.isLiked ? Icons.favorite : Icons.favorite_border,
color: segment.isLiked ? Colors.red : Colors.grey,
),
Text('${segment.likes}'),
],
),
)
五、界面设计
5.1 主页面布局
┌─────────────────────────────────────┐
│ 📖 故事接龙 📊 │
│ 与陌生人一起编织奇妙故事 │
├─────────────────────────────────────┤
│ [ 故事广场 ] [ 我的接龙 ] │
├─────────────────────────────────────┤
│ ┌─────────────────────────────┐ │
│ │ 🐉 迷雾中的古堡 │ │
│ │ 奇幻冒险 · 4人参与 │ │
│ │ ──────────────────────── │ │
│ │ 艾伦谢过老者,继续向上攀登 │ │
│ │ 🐱 夜猫 最新接龙 │ │
│ │ [4段] [856字] [55❤] [继续] │ │
│ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────────────┐ │
│ │ ➕ 开启新故事 │ │
│ │ 选择主题,写下开篇 │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
5.2 故事详情页布局
┌─────────────────────────────────────┐
│ ← 迷雾中的古堡 │
│ 4人参与 · 856字 · 奇幻冒险 │
├─────────────────────────────────────┤
│ │
│ 🌟 星辰 │
│ ┌─────────────────────────────┐ │
│ │ 在遥远的东方,有一座被迷雾 │ │
│ │ 笼罩的神秘山峰... │ │
│ │ [156字] ❤ 12 │ │
│ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ │
│ │ 墨客继续向上攀登... │ │
│ │ 📖 墨客 │ │
│ └─────────────────────┘ │
│ │
├─────────────────────────────────────┤
│ ✍️ 我 轮到你了 │
│ ┌─────────────────────────────┐ │
│ │ 写下你的故事片段... │ │
│ └─────────────────────────────┘ │
│ 提示:延续上文情节 [接龙] │
└─────────────────────────────────────┘
5.3 创建故事弹窗
┌─────────────────────────────────────┐
│ ──── │
│ │
│ 创建新故事 │
│ 选择主题,写下开篇,邀请陌生人创作 │
│ │
│ 故事标题 │
│ ┌─────────────────────────────┐ │
│ │ 给你的故事起个名字 │ │
│ └─────────────────────────────┘ │
│ │
│ 选择主题 │
│ ┌──────────┐ ┌──────────┐ │
│ │ 🐉 奇幻 │ │ 💕 言情 │ │
│ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 🚀 科幻 │ │ 🔍 悬疑 │ │
│ └──────────┘ └──────────┘ │
│ │
│ 开篇示例 │
│ ┌─────────────────────────────┐ │
│ │ 在遥远的东方,有一座被迷雾 │ │
│ │ 笼罩的神秘山峰... │ │
│ └─────────────────────────────┘ │
│ │
│ 接龙规则 │
│ ✓ 每人每次最多写200字 │
│ ✓ 每人只能接龙一次 │
│ ✓ 最多10人参与 │
│ │
│ ┌─────────────────────────────┐ │
│ │ 开始创作 │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
六、动画效果
6.1 脉冲动画
_pulseController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500),
)..repeat(reverse: true);
ScaleTransition(
scale: Tween<double>(begin: 1.0, end: 1.1).animate(
CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut),
),
child: const Text('📖', style: TextStyle(fontSize: 28)),
)
6.2 主题选择动画
AnimatedContainer(
duration: const Duration(milliseconds: 200),
decoration: BoxDecoration(
color: isSelected ? theme.color.withValues(alpha: 0.15) : Colors.grey.shade50,
border: Border.all(
color: isSelected ? theme.color : Colors.transparent,
width: 2,
),
),
// ...
)
七、模拟用户系统
7.1 模拟用户列表
| 用户名 | 头像 | 写作风格 |
|---|---|---|
| 星辰 | 🌟 | 浪漫 |
| 墨客 | 📖 | 文艺 |
| 风铃 | 🎐 | 清新 |
| 夜猫 | 🐱 | 神秘 |
| 暖阳 | ☀️ | 温暖 |
| 云朵 | ☁️ | 梦幻 |
| 书虫 | 📚 | 知性 |
| 画笔 | 🎨 | 创意 |
7.2 模拟接龙内容库
final continuations = [
'然而,事情并没有想象中那么简单。一个意想不到的转折即将发生...',
'就在这时,一个神秘的身影出现在远方,带来了未知的命运...',
'时间仿佛静止了,空气中弥漫着一种说不清的紧张感...',
'没有人注意到,角落里有一双眼睛正在默默注视着这一切...',
'命运的齿轮开始转动,一个全新的篇章即将展开...',
];
八、初始化数据
8.1 预置故事
应用启动时初始化3个示例故事:
| 故事 | 主题 | 参与人数 | 状态 |
|---|---|---|---|
| 迷雾中的古堡 | 奇幻冒险 | 4人 | 进行中 |
| 雨夜的邂逅 | 都市言情 | 3人 | 已完结 |
| 星际信号 | 科幻未来 | 2人 | 进行中 |
8.2 故事段落示例
迷雾中的古堡(片段):
🌟 星辰:在遥远的东方,有一座被迷雾笼罩的神秘山峰…
📖 墨客:年轻的冒险家艾伦站在山脚下,望着那若隐若现的城堡轮廓…
🎐 风铃:山路上,艾伦遇到了一位白发苍苍的老者…
🐱 夜猫:艾伦谢过老者,继续向上攀登。当他推开城堡沉重的大门时…
九、运行与调试
9.1 运行命令
# 运行到鸿蒙设备
flutter run -d harmony lib/main_story_relay.dart
# 运行到Windows
flutter run -d windows -t lib/main_story_relay.dart
# 代码分析
flutter analyze lib/main_story_relay.dart
9.2 功能测试清单
| 测试项 | 测试内容 | 预期结果 |
|---|---|---|
| 故事浏览 | 滚动故事列表 | 卡片正常显示 |
| 故事详情 | 点击故事卡片 | 进入详情页 |
| 创建故事 | 填写标题、选择主题 | 成功创建 |
| 接龙提交 | 输入20-200字 | 成功添加段落 |
| 点赞功能 | 点击爱心图标 | 数量变化 |
| 陌生人模拟 | 等待5秒 | 自动添加段落 |
| 故事完结 | 达到10段 | 标记完结 |
十、扩展方向
10.1 后端集成
┌─────────────┐ WebSocket ┌─────────────┐
│ 客户端 │ ←───────────────→ │ 服务器 │
└─────────────┘ └─────────────┘
│ │
│ 实时同步段落 │
│ 用户认证 │
│ 故事匹配 │
│ 数据持久化 │
↓ ↓
┌─────────────┐ ┌─────────────┐
│ 本地缓存 │ │ 云端数据库 │
└─────────────┘ └─────────────┘
10.2 功能扩展计划
| 版本 | 功能 | 描述 |
|---|---|---|
| v1.1 | 真实用户系统 | 注册登录、个人主页 |
| v1.2 | 故事匹配 | 根据偏好匹配故事 |
| v1.3 | 评论功能 | 对段落发表评论 |
| v1.4 | 私信系统 | 创作者之间交流 |
| v1.5 | 故事导出 | 导出PDF/EPUB |
十一、总结
故事接龙应用通过"轮流接龙"机制,实现了陌生人协作创作的核心体验。应用内置6种故事主题,每种主题配有独特的开篇示例和色彩风格,为用户提供丰富的创作选择。
应用采用粉色渐变主题,营造温馨浪漫的创作氛围。故事卡片采用主题色渐变头部设计,清晰展示故事状态和参与信息。段落展示采用左右交错布局,增强阅读趣味性。
接龙规则设计合理:每人最多200字、只能接龙一次、最多10人参与,这些限制既保证了故事的多样性,又避免了单方面主导。陌生人模拟功能让用户在离线状态下也能体验协作创作的乐趣。
应用采用Material Design设计规范,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。后续版本计划集成真实用户系统、WebSocket实时同步、云端存储等功能,为用户提供更完善的协作创作体验。
与陌生人一起,编织奇妙故事!
更多推荐
所有评论(0)