Flutter for OpenHarmony:言隅 - 用 Flutter 打造诗意灵感收集器的艺术实践

欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

发布时间:2026年2月9日

技术栈:Flutter 3.22+、Dart 3.4+、ListView、TextField、状态管理、时间格式化
项目类型:创意工具 / 灵感捕捉 / 教育级 CRUD 应用
适用读者:Flutter 开发者、写作者、设计师、对“微创作”有需求的用户


引言:在信息洪流中,为灵光一现留一方净土

我们都有过这样的瞬间:地铁上瞥见一句诗、会议间隙闪过一个金句、深夜突然悟出一段哲思——但转瞬即逝,未及记录。而传统笔记应用太重,社交平台又太喧嚣。

《言隅》(PhraseNook)正是为此而生:一个极简、专注、无干扰的灵感短语收集器。它不分类、不标签、不联网,只提供最纯粹的功能——输入、保存、回看。所有数据仅在当前页面生命周期内存在,刷新即清空,却足以守护那些稍纵即逝的“啊哈时刻”。

本文将深入剖析其五大核心维度:

  1. 可展开文本的智能截断与交互设计
  2. 时间感知的格式化策略:从“刚刚”到“历史”
  3. 搜索驱动的动态过滤机制
  4. 双模操作:点击展开 + 长按删除
  5. 克制式产品哲学:为何不持久化?

并探讨如何在零外部依赖的前提下,打造一个兼具诗意与工程严谨的微型创作空间。
在这里插入图片描述


一、内容呈现:可展开文本的优雅处理

1.1 智能截断逻辑

final displayText = isExpanded
    ? phrase.content
    : phrase.content.length > 80
        ? '${phrase.content.substring(0, 80)}…'
        : phrase.content;
设计考量:
  • 80字符阈值:约等于中文40字,在手机屏幕上显示3–4行,避免卡片过高
  • 省略号暗示:明确告知内容被截断,激发用户点击欲望
  • 无缝切换:展开/收起时文本平滑过渡,无闪烁

1.2 展开指示器

if (phrase.content.length > 80)
  Text(isExpanded ? '▲ 收起' : '▼ 展开', style: TextStyle(color: primary))

在这里插入图片描述

  • 语义化图标:▲/▼ 符合用户心智模型
  • 主色强调:使用主题主色,引导交互
  • 条件渲染:仅当内容超长时显示,避免视觉噪音

✍️ 写作心理学
灵感短语的价值在于“完整阅读”。截断不是限制,而是邀请。


二、时间感知:上下文敏感的时间格式化

2.1 智能时间显示

String _formatTime(DateTime time) {
  final now = DateTime.now();
  if (time.year == now.year && time.month == now.month && time.day == now.day) {
    return '${time.hour}:${time.minute}';
  }
  return '${time.month}/${time.day} ${time.hour}:${time.minute}';
}

在这里插入图片描述

时间语义分层:
场景 显示格式 用户认知
今天创建 14:30 “刚刚写的”
非今天 2/5 14:30 “前几天的灵感”
  • 省去年份:因数据仅会话内存在,年份冗余
  • 无“昨天/前天”:避免复杂逻辑,保持简洁

2.3 时间位置与样式

Text(_formatTime(...), style: TextStyle(color: grey, fontSize: 12))
  • 底部弱化:灰色小字号,不抢夺内容注意力
  • 垂直间距SizedBox(height: 8) 确保与正文分离

时间作为上下文
不是冰冷的时间戳,而是灵感的“温度计”。


三、搜索系统:轻量级动态过滤

3.1 实时搜索实现

TextField(
  controller: _searchController,
  onChanged: (_) => setState(() {}),
)
  • 无防抖:因数据量小(会话内),实时响应更流畅
  • 大小写不敏感toLowerCase() 确保搜索友好

3.2 过滤逻辑

List<Phrase> get _filteredPhrases {
  final query = _searchController.text.toLowerCase().trim();
  if (query.isEmpty) return _allPhrases;
  return _allPhrases.where((p) => p.content.toLowerCase().contains(query)).toList();
}

在这里插入图片描述

  • 计算属性:确保始终返回最新结果
  • 子串匹配:支持关键词任意位置匹配

🔍 搜索即过滤
在微型应用中,搜索与筛选无需区分。


四、交互设计:双模操作,直觉优先

4.1 点击 → 展开/收起

onTap: () => _toggleExpand(phrase.id)
  • 主交互路径:点击是最高频操作,用于查看完整内容
  • 状态记忆_expandedIds Set 记录每个短语的展开状态

4.2 长按 → 删除

onLongPress: () => _showDeleteDialog(phrase)
  • 危险操作防护:AlertDialog 二次确认
  • 内容预览:删除对话框中显示短语片段,避免误删
  • 视觉警示:红色“删除”按钮强化操作后果

手势语义映射
轻触探索,长按清理——符合物理世界直觉。


五、工程亮点与最佳实践

5.1 轻量级状态管理

  • 三个核心状态
    • _allPhrases:所有短语
    • _expandedIds:展开状态集合
    • _searchController:搜索文本
  • 局部更新setState 仅重建必要部分
  • 无外部依赖:纯 Flutter 实现,教学友好

5.2 最新优先排序

_allPhrases.insert(0, newPhrase); // 最新在最前
  • 符合创作流:用户最关心刚写下的内容
  • 无需排序字段:插入位置即隐含时间序

5.3 空状态引导

Icon(Icons.edit_note_outlined, size: 64, color: Colors.grey),
Text('暂无短语'),
Text('点击“+”添加你的第一句灵感', style: TextStyle(fontSize: 12)),
  • 符号联想:编辑笔记图标建立功能认知
  • 行动号召:明确下一步操作
  • 情感化文案:“灵感”比“内容”更具吸引力

六、克制式设计:为何不持久化?

6.1 产品定位清晰

  • 临时性容器:捕捉“此刻”的灵感,而非永久归档
  • 降低心理负担:用户无需思考“要不要删旧内容”
  • 隐私友好:敏感文字(如日记片段)不应留存设备

6.2 技术权衡

  • Web 平台限制:localStorage 有大小限制且需用户授权
  • MVP 原则:先验证核心价值(快速记录/回看),再考虑增强
  • 教学纯净性:避免引入 shared_preferences 等复杂概念

🧘 禅意设计
有些东西,本就不该被保存。它的价值在于被写下那一刻。


七、进阶演进方向

7.1 功能增强

  1. 导出分享
    • 添加“分享全部”按钮,生成文本或图片
  2. 随机展示
    • “抽一句”功能,随机显示一条短语,用于每日灵感
  3. 字数统计
    • 在输入框下方显示字数,辅助创作

7.2 技术升级

  1. 本地持久化(可选):
    // 使用 hive 或 shared_preferences
    box.put('phrases', _allPhrases.map((p) => jsonEncode(p)).toList());
    
  2. 动画过渡
    • 添加 AnimatedSize 实现展开/收起动画
  3. PWA 支持(Web):
    • 支持安装到桌面,提升使用频率

7.3 设计深化

  1. 字体选择
    • 允许用户切换衬线/无衬线字体,适配阅读偏好
  2. 背景纹理
    • 添加纸张、黑板等背景,增强创作氛围
  3. 语音输入
    • 集成语音识别,支持口述灵感(需权限)

结语:在数字时代,守护文字的纯粹

《言隅》是一次对“效率至上”设计的温柔反抗。它不追求功能全面,而是专注于一个微小却深刻的场景:让灵光一现的文字,有处安放。

在信息过载的时代,《言隅》证明了:最好的工具,往往看起来“什么都没做”。它没有云同步,没有历史版本,甚至没有保存按钮——但它精准地服务于创作者最原始的需求:写下,然后看见

对于开发者而言,这不仅是一个短语收集器,更是一面镜子——照见我们是否真正理解用户,是否敢于对“加功能”的惯性说不。

“Writing is an act of faith, not a trick of grammar.”
—— E.B. White

愿你的下一个应用,也能在喧嚣世界中,为文字留一片宁静的角落。


GitHub Gist 链接phrase_nook_app.dart
适用场景:灵感捕捉、Flutter ListView 教学、可展开文本实践、双模交互范例

📝 Happy Coding!
让每一行代码,都成为文字的守护者。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐