基于 Harmony 6.0 应用的读书会社交应用首页实现

前言

读书是一件天然孤独的事,但读完之后人和人最想做的事就是"找人聊聊这本书"。读书会作为一种古老的社交形态在线上重生——线上分享读后感、组织共读小组、邀请作者直播、举办读书马拉松,让"孤独的阅读"变成"陪伴的成长"。这种应用的首页要回答四件事——“今天有什么共读活动 / 我在读什么 / 别人在读什么 / 怎么加入一个小组”。Harmony 6.0 时代,读书会应用迎来了几个独特的能力红利——AudioKit 让线上读书会的语音直播低延迟、分布式数据让共读进度多端同步、HMS Push 让"小组同伴更新了笔记"精准触达、HMS Wallet 让书籍电子凭证电子化。本文用 Flutter 在 Harmony 6.0 上实现一个读书会首页,作为本系列第九组的收官。
在这里插入图片描述

背景

读书会类应用的视觉关键词是"沉静、有书卷气、有社区感"——沉静对应"色彩稳重不刺眼",书卷气对应"米黄背景或暖灰",社区感对应"小组成员头像组必须有"。深棕 #92400E 配米黄 #FEF3C7 是这类应用的典型主色——既有"书卷气"又有"温暖"。本项目首页 5 个模块:渐变 Header(已读 X 本 + 阅读时长)、当前在读书籍卡片(封面 + 进度 + 同伴)、共读小组横滑、热门书评列表、即将开始的读书会预告。从产品角度,读书会的最大复购点是"小组同伴的进度"——用户每次打开应用都期待看到"小组里的某个人读到第几章了"。这种"邻里式的进度对比"让读书不再孤独。

Flutter × Harmony 6.0 跨端开发介绍

Harmony 6.0 在读书会这种"重内容 + 强社区"应用上的能力栈非常合适——AudioKit 提供低延迟语音直播、分布式数据让多端共读进度同步、PushKit 提供高优先级推送、HMS Wallet 让电子书凭证落袋、AI 助手能力提供书评摘要和推荐。Flutter 嵌入 Harmony 6.0 的方案非常合适——主页用 Flutter 自绘提供丰富 UI,音频直播能力通过 ArkTS 端 AudioKit 接入。Skia 引擎对深棕米黄(#92400E / #FEF3C7 / #FBBF24)的混合渲染非常温暖,配合圆角卡片和大留白,整页氛围既沉静又有温度。本项目继续坚持纯 UI、零三方依赖、所有页面 StatelessWidget 的极简哲学。

开发核心代码

代码一:阅读统计 Header

Header 必须把"已读多少本 + 阅读时长"做成视觉中心——这是用户的成就感来源。我用一个深棕渐变 Container,顶部一行"我的书房"+ 设置图标,中部"今年已读 18 本 · 阅读 268 小时"统计数据。

Widget _header() {
  return Container(
    padding: const EdgeInsets.all(20),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [_primary, Color(0xFF78350F)],
        begin: Alignment.topLeft, end: Alignment.bottomRight),
      borderRadius: BorderRadius.circular(22),
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Row(children: [
          Icon(Icons.menu_book, color: Colors.white, size: 22),
          SizedBox(width: 8),
          Text('我的书房',
              style: TextStyle(color: Colors.white,
                  fontSize: 18, fontWeight: FontWeight.w800)),
          Spacer(),
          Icon(Icons.bookmark, color: Colors.white, size: 22),
        ]),
        const SizedBox(height: 16),
        const Row(children: [
          Expanded(child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('今年已读',
                  style: TextStyle(color: Colors.white70,
                      fontSize: 12)),
              SizedBox(height: 4),
              Row(crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                Text('18',
                    style: TextStyle(color: Colors.white,
                        fontSize: 32,
                        fontWeight: FontWeight.w900)),
                SizedBox(width: 4),
                Padding(padding: EdgeInsets.only(bottom: 6),
                  child: Text('本',
                      style: TextStyle(color: Colors.white,
                          fontSize: 14,
                          fontWeight: FontWeight.w700))),
              ]),
            ],
          )),
          Expanded(child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('累计阅读',
                  style: TextStyle(color: Colors.white70,
                      fontSize: 12)),
              SizedBox(height: 4),
              Row(crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                Text('268',
                    style: TextStyle(color: Colors.white,
                        fontSize: 32,
                        fontWeight: FontWeight.w900)),
                SizedBox(width: 4),
                Padding(padding: EdgeInsets.only(bottom: 6),
                  child: Text('小时',
                      style: TextStyle(color: Colors.white,
                          fontSize: 14,
                          fontWeight: FontWeight.w700))),
              ]),
            ],
          )),
        ]),
      ],
    ),
  );
}

阅读时长在生产业务里通过 ArkTS 端记录用户每天的阅读会话时长,再通过分布式数据对象同步到云端。这种长期统计数据非常适合做成桌面服务卡片,让用户每周打开手机就能看到"本周已读 X 小时"。

从「阅读统计 Header」的数据驱动与成就感设计角度再补一段。读书类应用的 Header 必须传递「我已经读了这么多」的成就感。这段 Header 用深绿到墨绿的渐变背景,配合「本月已读 X 小时 / X 本」的双数据 + 阅读进度条 + 「继续阅读」按钮的多段式排版,让用户在打开应用的第一秒就看到自己的阅读积累。深绿色传递「书卷气、宁静、专注」的氛围,是读书类应用的最优主色。「本周阅读 5 天」的连续打卡数据会强化用户「不能断的」的心理压力,是阅读类应用的经典留存触发器。如果未来要扩展支持「阅读目标设定」(用户自己设定每月读完几本),可以在 Header 加一个圆形进度环显示当前完成度,骨架不变。
在这里插入图片描述

代码二:当前在读书籍

当前在读卡片是首页的视觉中心——必须把"封面 + 书名 + 作者 + 进度 + 同伴"全部塞进。我用一个 Row 布局,左侧 100x140 的渐变封面占位,右侧书名 + 作者 + 进度条 + “X 位同伴在读”。

Widget _currentBook() {
  return Container(
    padding: const EdgeInsets.all(14),
    decoration: BoxDecoration(color: _card,
        borderRadius: BorderRadius.circular(16)),
    child: Row(children: [
      Container(width: 100, height: 140,
        decoration: BoxDecoration(
          gradient: LinearGradient(colors: [
            _primary.withValues(alpha: 0.8),
            _amber.withValues(alpha: 0.8),
          ], begin: Alignment.topLeft, end: Alignment.bottomRight),
          borderRadius: BorderRadius.circular(8),
          boxShadow: [BoxShadow(
              color: Colors.black.withValues(alpha: 0.16),
              blurRadius: 10, offset: const Offset(2, 4))]),
        child: const Center(child: Icon(Icons.menu_book,
            color: Colors.white, size: 40)),
      ),
      const SizedBox(width: 14),
      Expanded(child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text('百年孤独',
              style: TextStyle(color: _ink,
                  fontSize: 16, fontWeight: FontWeight.w800)),
          const SizedBox(height: 4),
          const Text('加西亚·马尔克斯',
              style: TextStyle(color: _sub, fontSize: 12)),
          const SizedBox(height: 14),
          ClipRRect(borderRadius: BorderRadius.circular(3),
            child: const LinearProgressIndicator(
              value: 0.42, minHeight: 6,
              backgroundColor: Color(0xFFFEF3C7),
              valueColor: AlwaysStoppedAnimation(_primary),
            ),
          ),
          const SizedBox(height: 6),
          const Text('已读 42% · 第 6 章',
              style: TextStyle(color: _primary, fontSize: 12,
                  fontWeight: FontWeight.w700)),
          const Spacer(),
          Row(children: [
            ...List.generate(3, (i) {
              return Padding(padding: EdgeInsets.only(
                  left: i == 0 ? 0 : -6),
                child: CircleAvatar(radius: 10,
                  backgroundColor: _amber.withValues(
                      alpha: 0.4 + i * 0.15)),
              );
            }),
            const SizedBox(width: 8),
            const Text('+ 12 位同伴在读',
                style: TextStyle(color: _sub, fontSize: 11)),
          ]),
        ],
      )),
    ]),
  );
}

"X 位同伴在读"通过分布式数据查询"我加入的所有读书小组中正在读这本书的人数"得到。这种"群体陪伴感"是读书类应用区别于普通电子书 App 的关键差异。

从「当前在读书籍」的卡片信息层级与阅读进度可视化角度再补一段。当前在读书籍是阅读类 App 的核心信息位——用户每次打开 App 都希望「立刻能继续上次的进度」。这段大卡片用「书籍封面占位 + 书名 + 作者 + 阅读进度条 + 「X 位同伴在读」chip + 继续阅读按钮」六段信息塞在一张大卡片里。封面用色块 + 书本图标占位(生产业务里替换为真实封面)。进度条用 LinearProgressIndicator 显示已读百分比,配合「已读 35%」文字明确进度。如果未来要支持「多本书并行阅读」,可以把当前在读改成横滑列表展示,骨架不变。鸿蒙 6.0 的 Skia 对进度条这种纯几何图形渲染开销几乎为零。
在这里插入图片描述

代码三:共读小组横滑

每个共读小组卡片需要包含:小组名、当前书籍封面 emoji、成员数、活跃度。我做成 140 高度的横滑列表,每张卡片宽 160。

SizedBox(height: 140,
  child: ListView.separated(
    scrollDirection: Axis.horizontal,
    itemCount: groups.length,
    separatorBuilder: (_, __) => const SizedBox(width: 10),
    itemBuilder: (_, i) {
      final g = groups[i];
      return Container(width: 160,
        padding: const EdgeInsets.all(12),
        decoration: BoxDecoration(color: _card,
            borderRadius: BorderRadius.circular(14)),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(g['emoji'] as String,
                style: const TextStyle(fontSize: 32)),
            const SizedBox(height: 8),
            Text(g['name'] as String,
                style: const TextStyle(color: _ink,
                    fontSize: 13, fontWeight: FontWeight.w700)),
            const SizedBox(height: 4),
            Text(g['book'] as String,
                style: const TextStyle(color: _sub, fontSize: 11),
                maxLines: 1, overflow: TextOverflow.ellipsis),
            const Spacer(),
            Row(children: [
              const Icon(Icons.people_outline,
                  color: _sub, size: 12),
              const SizedBox(width: 4),
              Text('${g['members']} 人',
                  style: const TextStyle(color: _sub,
                      fontSize: 11)),
              const Spacer(),
              Container(width: 6, height: 6,
                decoration: const BoxDecoration(color: _green,
                    shape: BoxShape.circle)),
            ]),
          ],
        ),
      );
    },
  ),
)

绿色小圆点表示"这个小组现在有人在线讨论"——通过分布式数据订阅小组在线状态实现。

从「共读小组横滑」的社群陪伴感与多人协作设计角度再补一段。读书类应用的「共读小组」是连接孤独阅读者的核心功能。这段横滑卡片用「小组封面 + 小组名 + 在读书名 + 成员头像组 + 在线状态 + 加入按钮」六段信息塞在每张卡片里,让用户的视觉动线从「主题(认知)→ 当前在读(共鸣)→ 成员(社交证明)→ 加入(行动)」一气呵成。绿色小圆点表示「现在有人在线讨论」,是激励用户立即加入的关键视觉触发器。如果未来要扩展支持「小组直播讨论」(小组主理人定期开麦讨论),可以在卡片上叠加一个 LIVE 红点 chip,鸿蒙 6.0 的 AudioKit 完全支持这种小组语音场景。

心得

读书会类 App 的视觉灵魂是"沉静 + 陪伴"——深棕米黄给沉静,同伴头像组给陪伴。开发时最容易犯的错是把书籍封面做得过于绚丽,反而稀释了"读书"的氛围。我的策略是用渐变色块作为封面占位,让色彩克制有书卷感。从能力扩展角度,读书会最值得在鸿蒙端打造的是"AudioKit 直播 + 分布式共读进度 + AI 摘要"三件套——AudioKit 让线上读书会语音直播低延迟、分布式数据让共读进度多端同步、AI 助手能力让长书评自动生成摘要。把这些能力组合起来,App 就从一个"电子书阅读器"升级成"陪伴成长的读书伙伴"。

总结

本篇实现了 Harmony 6.0 端的读书会首页,5 个模块、纯 UI、零依赖、约 360 行代码。第九组的"语音日记 / 家庭相册 / 读书会"三个迥异的内容沉淀场景共用同一份骨架,再次验证"骨架不变、页面替换"的方法论可行性。从扩展角度建议生产业务里:把语音直播接入 AudioKit 低延迟通道;把共读进度接入分布式数据对象;把电子书凭证接入 WalletKit;把书评摘要接入 AI 助手能力;把"今日已读时长"做成 FormExtensionAbility 桌面卡片。这些扩展都可以在不动当前 UI 骨架的前提下完成。下一篇进入第十组,把"AR 实景社交 / 运动轨迹 / 卡路里计算"三类首页继续讲透。

在这里插入图片描述

Logo

一站式 AI 云服务平台

更多推荐