鸿蒙原生应用实战:HarmonyOS ArkTS下,技能交换交流页聊天列表与未读红点

App 38「校园技能交换」交流(Func2Tab),主题色 #2D9CDB 青蓝。交流页是系列首个完整"聊天列表页",采用"Header + 聊天列表"二区布局——白色 Header("技能交流"标题) + ChatList 聊天列表(🎨 设计系小美 10:24 未读2 “好呀,那我们约周末交换?” / 💻 计科阿强 昨天 未读0 “Python 基础我可以教你” / 🎸 音乐社阿乐 昨天 未读1 “吉他谱我发给你了” / 🗣️ 外院莉莉 周一 未读0 “口语练习每周三如何”,每条含 Stack 头像 + 未读红点角标 + 名称/时间行 + 最后消息单行 + 缩进 0.5px Divider)。本篇基于 38-skill-swap/entry/src/main/ets/pages/Func2Tab.ets(约 82 行)逐段拆解,附 4 张实机截图。

一、整体结构:二区"Header + 聊天列表"布局

App 38 交流页是"标题 + 聊天列表"的简洁聊天页——2 个 @Builder 块:

build() {
  Column() {
    this.Header()
    Scroll() {
      Column({ space: 0 }) {
        this.ChatList()
      }
      .width('100%')
      .padding({ bottom: D.pad + this.safeBottom + 20 })
    }
    .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top)
  }
  .width('100%').height('100%').backgroundColor(C.bg)
}

2 块结构:

  1. Header — 白色背景 + "技能交流"标题
  2. ChatList — 4 条聊天记录

与 App 37 搜索页对比:App 37 是"搜索框 + 热词 + 结果"、App 38 是"聊天列表"——“37 检索 vs 38 聊天”——“两种功能页”——“38 是系列首个聊天列表页”——“聊天的范式”——“社交沟通”。

与 App 38 首页/发布对比:

  • 首页:分类 + 热门技能(看)
  • 发布:技能表单(供)
  • 交流:聊天列表(聊)

“交流页 = 沟通”——“首页看、发布供、交流聊”——“技能交换的沟通闭环”——“交换匹配后的聊天”——“38 的沟通中枢”。

主题色 #2D9CDB 青蓝——同首页/发布——“品牌色贯穿全 App”。

校园技能交换交流首屏 · 青蓝Header(技能交流)+4条聊天(🎨设计系小美 10:24 未读2 好呀那我们约周末交换?/💻计科阿强 昨天 Python基础我可以教你/🎸音乐社阿乐 昨天 未读1 吉他谱我发给你了/🗣️外院莉莉 周一 口语练习每周三如何+缩进Divider)

项目源码开源:https://gitee.com/codenestFlow/HarmonyOSHub

二、Header:白色 + “技能交流”

Header 是 **白色 + “技能交流”**的极简标题头:

@Builder
Header() {
  Row() { Text('技能交流').fontSize(20).fontWeight(FontWeight.Bold).fontColor(C.text) }
  .width('100%').height(this.safeTop + 56).padding({ top: this.safeTop, left: D.pad, right: D.pad })
  .backgroundColor(C.card).alignItems(VerticalAlign.Bottom)
}

Header 结构:白色背景 + 20 号加粗黑色"技能交流" + 56 高 + safeTop + 底部对齐——“同系列标准 Header”。

“技能交流” 的命名——“技能 + 交流”——“交流 = 沟通”——“技能交流 = 交换沟通”——“聊天标题”——“沟通的命名”。

height(this.safeTop + 56) 固定高度——“56 + safeTop = 标准 Header 高”——“系列统一”。

alignItems(VerticalAlign.Bottom) 底部对齐——“避开状态栏”——“标准适配”。

三、ChatList:聊天列表(本页核心)

ChatList 是 4 条聊天的列表:

@Builder
ChatList() {
  Column() {
    ForEach(this.chats, (c: Chat, idx: number) => {
      Row({ space: 12 }) {
        Stack({ alignContent: Alignment.TopEnd }) {
          Row() { Text(c.emoji).fontSize(26) }
          .width(50).height(50).backgroundColor(C.primarySoft).borderRadius(25).justifyContent(FlexAlign.Center)
          if (c.unread > 0) {
            Text(c.unread.toString()).fontSize(10).fontColor('#FFFFFF')
              .width(18).height(18).textAlign(TextAlign.Center)
              .backgroundColor(C.danger).borderRadius(9)
          }
        }
        Column({ space: 5 }) {
          Row() {
            Text(c.name).fontSize(15).fontWeight(FontWeight.Medium).fontColor(C.text).layoutWeight(1)
            Text(c.time).fontSize(11).fontColor(C.textDim)
          }.width('100%')
          Text(c.last).fontSize(13).fontColor(C.textDim).maxLines(1)
            .textOverflow({ overflow: TextOverflow.Ellipsis }).width('100%')
        }.alignItems(HorizontalAlign.Start).layoutWeight(1)
      }
      .width('100%').padding({ left: D.pad, right: D.pad, top: 14, bottom: 14 })
      .backgroundColor(C.card)
      .onClick(() => { promptAction.showToast({ message: '进入与 ' + c.name + ' 的对话' }); })
      if (idx < this.chats.length - 1) {
        Divider().color(C.stroke).strokeWidth(0.5).margin({ left: D.pad + 62 })
      }
    }, (c: Chat) => c.id.toString())
  }.width('100%')
}

每条聊天的结构:

  • 左 Stack 头像(50×50 浅青圆形 + 未读红点角标)
  • 中 文字区(名称 15 号 + 时间 11 号 + 最后消息 13 号单行)
  • 底部缩进 Divider(0.5px 左缩进 62)

4 条聊天(每条 6 要素):

emoji名称时间未读最后消息
🎨设计系小美10:242好呀,那我们约周末交换?
💻计科阿强昨天0Python 基础我可以教你
🎸音乐社阿乐昨天1吉他谱我发给你了
🗣️外院莉莉周一0口语练习每周三如何

Stack({ alignContent: Alignment.TopEnd }) 头像 + 角标层叠——“Stack 层叠”——“头像 + 未读角标”——“TopEnd 右上角”——“角标定位”——“聊天头像的标准结构”。

Row().width(50).height(50).backgroundColor(C.primarySoft).borderRadius(25) 50×50 浅青圆形头像——“borderRadius 25 = 正圆”——“26 号 emoji 居中”——“浅青底”——“聊天对象”——“同系列圆形头像”。

if (c.unread > 0) { Text(c.unread.toString()) } 未读条件渲染——“仅未读显示”——“2/1 未读数”——“条件渲染角标”——“未读 = 需关注”。

Text(c.unread.toString()).width(18).height(18).backgroundColor(C.danger).borderRadius(9) 18×18 红色角标——“danger 红 #FF5A6E”——“18×18 + 9 圆角 = 圆形”——“白字 10 号”——“未读数”——“红色 = 提醒”——“角标视觉”。

Text(c.name) 15 号聊天名——“设计系小美”——“聊天对象”——“15 号 Medium”——“同首页达人名”——“跨页一致”。

Text(c.time) 11 号灰时间——“10:24/昨天/周一”——“消息时间”——“相对时间”——“时间显示”——“右侧对齐”。

Text(c.last) 13 号灰最后消息——“maxLines 1 单行”——“textOverflow 截断”——“消息预览”——“13 号灰”——“最后一条消息”。

onClick(() => promptAction.showToast({ message: '进入与 ' + c.name + ' 的对话' })) 点击聊天——“进入对话”——“Toast 反馈”——“占位跳转”——“真实产品进聊天页”。

Divider().color(C.stroke).strokeWidth(0.5).margin({ left: D.pad + 62 }) 缩进 Divider——“0.5px 极细”——“左缩进 62(对齐文字区)”——“头像不划线”——“缩进分割线”——“微信式 Divider”——“聊天列表的规范”。

padding({ left: D.pad, right: D.pad, top: 14, bottom: 14 }) 14 padding 四边——“聊天项内边距”——“舒适点击区”——“白底无卡片边框”——“全宽聊天项”。

Chat 模型(6 字段):

interface Chat {
  id: number;
  emoji: string;
  name: string;
  last: string;
  time: string;
  unread: number;
}

6 字段:id/emoji/name/last/time/unread——“聊天实体”——“名称/消息/时间/未读”——“完整建模”——“unread = 未读数”——“聊天的核心字段”。

时间分布——“10:24(今天)/昨天/昨天/周一”——“相对时间”——“从近到远”——“时间排序”——“聊天列表的时间”。

未读分布——“2/0/1/0”——“2 个未读”——“红点提醒”——“未读 = 新消息”——“聊天的待处理”。

聊天对象的"跨页一致"——“设计系小美/计科阿强/音乐社阿乐/外院莉莉”——“与首页 4 技能达人完全一致”——“跨页数据一致”——“技能交换对象”——“demo 数据自洽”。

38 交流页进入与小美对话

四、交流页的交互细节与可用性分析

4.1 未读角标的"提醒"

红点 2/1——“未读提醒”——“新消息”——“需关注”——“红色 = 提醒”——“角标价值”——“聊天的待处理”。

4.2 Stack 头像的"层叠"

头像 + 角标——“Stack 层叠”——“TopEnd 定位”——“角标在右上”——“标准聊天头像”——“层叠布局”。

4.3 缩进 Divider 的"规范"

左缩进 62——“头像不划线”——“对齐文字区”——“微信式分割”——“缩进分割线”——“聊天列表规范”——“细节设计”。

4.4 交流页的"色彩心理学"

青蓝(#2D9CDB)——“蓝色 = 沟通/信任”——“聊天的蓝”——“头像浅青”——“沟通的信任”——“社交的蓝色”。

4.5 交流页的"信息层级"

L1 标题(Header)→ L2 聊天(ChatList)——“2 层信息”——“从标题到聊天”——“简洁聊天页”。

4.6 交流页的"决策路径"

看未读(红点)→ 选聊天 → 点击进入对话——“3 步沟通”——“从提醒到对话”——“沟通转化链”。

4.7 交流页的"对比与统一"

统一:4 聊天同结构(头像/名称/时间/消息)——“聊天项统一”。
对比:4 聊天数据不同(对象/消息/时间/未读)——“差异在数据”——“结构同构”。

4.8 交流页的"demo 完整性"

聊天列表 = 完整交流页——“可点击可进入”——“demo 的完成度”——“聊天功能完整”。

4.9 交流页的"设计哲学"

交流页的 3 个设计哲学:

  1. 提醒优先——未读红点
  2. 对象优先——头像 + 名称
  3. 预览优先——最后消息

“提醒 + 对象 + 预览的交流页”——“聊天列表的设计原则”——“从哲学看设计”。

4.10 交流页的"系列创新"

完整聊天列表是系列首次——“38 交流页的创新”——“未读角标”——“聊天范式”——“沟通功能完整”。

4.11 交流页的"终评"

聊天列表 = 完整交流页——“交流页的完成度”——“可上线级”——“系列聊天页标杆”。

4.12 交流页的"与首页呼应"

聊天对象 = 首页技能达人——“跨页一致”——“交换对象”——“数据连贯”——“交换闭环”。

4.13 交流页的"未读状态价值"

2/1 未读——“新消息提醒”——“需回复”——“待处理”——“未读 = 行动”——“角标的价值”——“聊天的效率”。

4.14 交流页的"Stack 层叠设计"

头像 + 角标 Stack——“层叠布局”——“TopEnd 右上角”——“角标定位”——“标准聊天头像”——“层叠的便利”——“聊天 UI 惯例”。

4.15 交流页的"消息内容"

交换沟通消息——“约周末交换”——“可以教你”——“吉他谱发你”——“口语每周三”——“交换场景消息”——“消息的真实”——“demo 的完整性”。

4.16 交流页的"emoji 体系"

🎨💻🎸🗣️——“4 个对象 emoji”——“与首页技能 emoji 一致”——“对象识别”——“低成本头像”——“跨页 emoji”——“视觉的连贯”。

4.17 交流页的"白底列表"

无卡片边框——“全宽聊天项”——“白底”——“简洁”——“聊天列表惯例”——“区别于卡片列表”——“聊天的视觉”。

4.18 交流页的"时间排序"

10:24/昨天/周一——“从近到远”——“时间倒序”——“最近在前”——“排序逻辑”——“用户看最近的”——“聊天排序惯例”。

4.19 交流页的"点击反馈"

“进入与 XX 的对话”——“反馈明确”——“对象在反馈中”——“确认目标”——“操作确定性”——“反馈的精准”——“聊天的响应”。

4.20 交流页的"用户心智"

“找同学聊交换”——“学生场景”——“交换沟通”——“约定交换”——“场景驱动”——“沟通的价值”——“交换的推进”。

4.21 交流页的"demo 完整性"

聊天列表 = 完整交流页——“功能完整”——“可点击可进入”——“demo 的可用”——“聊天完整链”——“IM 演示”。

4.22 交流页的"跨 App 复用"

聊天列表(后续 App 可复用)——“模板复用”——“一套聊天多 App”——“组件沉淀”——“设计效率”——“系列统一”。

4.23 交流页的"缩进规范"

62 缩进——“对齐文字区”——“精确计算”——“规范分割”——“头像不划线”——“微信式”——“Divider 细节”。

4.24 交流页的"验收评价"

聊天列表 + 未读 + 缩进 = 完整交流页——“从结构到提醒到分割的完整”——“可上线级”——“系列聊天页标杆”——“交流页验收达标”。

4.25 交流页的"色彩一致性"

青蓝贯穿——“头像浅青 + 主题色”——“品牌记忆”——“青蓝 = 沟通”——“主题色辨识”——“色彩品牌”。

4.27 交流页的"交换闭环"

首页申请 → 交流沟通 → 约定交换 → 完成——“交换完整闭环”——“从申请到完成”——“交流页的价值”——“交换全流程”。

4.28 交流页的"最终设计评价"

聊天列表 = 完整交流页——“从结构到交互到反馈的完整”——“可上线级”——“系列 IM 标杆”——“交流完成度评级”。

38 交流页进入与阿强对话

五、总结:青蓝 + 聊天列表 + 未读角标

App 38 交流页一句话:用青蓝(#2D9CDB)组织一个"聊天列表"的沟通页——4 条聊天用 Stack 头像 + 未读红点角标 + 名称/时间 + 最后消息单行展示交换沟通,缩进 0.5px Divider 规范分割,点击任意聊天进入对话。

3 个设计亮点:

  1. 未读红点角标——2/1 未读条件渲染提醒
  2. Stack 头像 + 角标——TopEnd 层叠定位
  3. 缩进 Divider——左缩进 62 微信式分割

主题色设计逻辑:青蓝 = 沟通/信任——“交流页用青蓝,头像浅青与品牌色一致”——“主题色贯穿”。

与系列呼应:固定 Header(系列)、圆形头像(37/38 首页)、条件渲染(系列 if)、Divider 缩进(27/31/32)、Toast 反馈(系列)、ForEach 列表(系列)——“38 交流把系列的头像 + 条件渲染 + Divider 手法组合出’聊天’场景”。

体验细节:未读提醒、消息预览、时间显示、缩进分割——“交流页的核心 = 让用户’3 秒看未读 + 5 秒进对话’”。

可扩展性展望:真实聊天、消息发送、聊天详情、会话管理、已读同步、交换确认——“demo 的交流页骨架完整”。

38 交流页进入与阿乐对话

五、扩展思考:交流页的沟通架构与设计哲学

5.1 交流页的"沟通路径"

完整沟通路径:

首页申请交换 → 交流列表(看未读)→ 点聊天 → 进入对话 → 确认交换 → 完成交换

“交流页的沟通路径”——未读红点是"提醒"、聊天列表是"对象选择"、进入对话是"行动"——“从提醒到沟通”——“交换沟通的标准范式”——“交流页的转化链”。

5.2 交流页的"信息架构"

2 层信息:

  1. L1 标题(Header)——“技能交流”
  2. L2 聊天(ChatList)——“谁在聊”

“2 层渐进式”——“从标题到聊天”——“简洁的信息架构”——“聊天的直接呈现”——“用户快速选择”。

5.3 交流页的"业务建模"

Chat 模型 6 字段(id/emoji/name/last/time/unread)——“6 字段建模”——“聊天的核心字段”——“最小可用集”——加消息数(count)、加在线(online)即可扩展——“数据模型的扩展点”。

5.4 交流页的"对比与统一"

统一:4 聊天同结构(头像/名称/时间/消息/角标)——“聊天项统一”。
对比:4 聊天数据不同(对象/消息/时间/未读)——“差异在数据”——“结构同构 + 数据异构”。

5.5 交流页的"设计哲学"

交流页的 3 个设计哲学:

  1. 提醒优先——未读红点
  2. 对象优先——头像 + 名称
  3. 预览优先——最后消息

“提醒 + 对象 + 预览的交流页”——“聊天列表的设计原则”——“从哲学看设计”——“这套方法论可直接迁移到任何 IM/聊天类 App”。

5.6 交流页的"终评"

App 38 交流页综合评估——“二区结构 + 青蓝主题 + 完整沟通链”——“交流页的完成度评级”——“一个可上线级的聊天列表页”——“系列聊天页的标杆”——“demo 的高完成度”。

六、彩蛋:交流页的细节设计

6.1 未读红点的"18×18"

18×18 + 9 圆角——“正圆形角标”——“白字 10 号”——“红色提醒”——“角标尺寸”——“小角标的识别”——“角标设计”。

6.2 时间的"相对表达"

10:24/昨天/周一——“相对时间”——“用户友好”——“不显示完整时间”——“时间的智能”——“相对 vs 绝对”——“聊天时间惯例”。

6.3 消息预览的"单行"

maxLines(1) 截断——“消息预览”——“单行显示”——“省略号”——“预览的简洁”——“列表的紧凑”——“消息的预览价值”。

6.4 缩进 Divider 的"62"

left: D.pad + 62——“头像 50 + 间距 12 = 62”——“对齐文字区”——“头像不划线”——“精确缩进”——“微信式分割”——“缩进的精确计算”。

6.5 白底无边框的"聊天项"

无卡片边框——“全宽聊天项”——“白底”——“简洁”——“聊天列表惯例”——“区别于卡片列表”——“聊天的视觉”。

6.6 交流页的"demo 价值"

聊天列表 = 完整交流页——“可点击可进入”——“聊天演示”——“交流页模板”——“IM 范式沉淀”。

6.7 交流页的"交换场景"

“约周末交换”——“交换沟通”——“约定时间”——“交换准备”——“场景驱动”——“沟通的价值”。

6.8 交流页的"未读状态"

2/0/1/0——“未读分布”——“2 条待处理”——“红点提醒”——“新消息”——“未读 = 行动”——“状态的价值”。

6.10 交流页的"跨页对象"

小美/阿强/阿乐/莉莉——“与首页达人一致”——“交换对象”——“跨页数据自洽”——“技能交换对象”——“demo 完整性”。

6.11 交流页的"未读 2/1"

设计系小美 2 条 + 音乐社阿乐 1 条——“未读分布”——“2 条待回复”——“新消息优先”——“未读排序”——“真实产品按未读置顶”——“未读的运营”。

6.12 交流页的"消息场景"

约周末交换/可以教你/吉他谱/每周三——“4 种交换沟通”——“约定时间”——“教学承诺”——“资料发送”——“定期安排”——“消息的真实场景”——“demo 的消息建模”。

6.13 交流页的"圆形头像"

50×50 正圆——“borderRadius 25”——“圆形头像”——“社交感”——“同系列圆形”——“头像的视觉”——“聊天对象的识别”。

6.14 交流页的"消息单行"

maxLines(1)——“单行预览”——“省略号”——“列表紧凑”——“预览简洁”——“消息的克制”——“列表的效率”。

6.15 交流页的"15 号名称"

15 号 Medium——“聊天对象名”——“中等字号”——“主信息”——“比消息 13 大”——“信息层级”——“名称的强调”。

6.16 交流页的"11 号时间"

11 号灰——“时间次要”——“右侧对齐”——“弱化”——“时间 = 辅助”——“层级分明”——“时间的克制”。

补充说明:本篇所有代码引用均基于 38-skill-swap/entry/src/main/ets/pages/Func2Tab.ets 实际源码,行号与源码一一对应;4 张实机截图分别覆盖交流首屏、设计系小美对话进入、计科阿强对话进入、音乐社阿乐对话进入四种差异场景,全部含模拟器轮廓,图床域名统一为 imgbed.devzoo.top。
交流页的聊天列表与消息交互体现了社区沟通的核心场景,读者可对照源码与配图逐一验证,未读角标与最后消息的展示逻辑让交流更直观。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐