欢迎光临
我们一直在努力

【HarmonyOS 6】“档案“页面的UI布局拆解

上一篇我们拆解了"维系"首页的布局。这篇继续看第二个 Tab——档案。

“维系"页解决的是"我现在该做什么”,“档案"页解决的是"我关心的人是谁”。两个页面的布局思路完全不同:维系页是多种卡片的混合拼图,档案页则是同一种卡片的纵向重复。

布局越单一,反而越考验单张卡片的设计。


一、页面全貌

效果

对应代码骨架:

@Builder
PeopleTab() {
Scroll() {
Column() {
Row() { Text('人物档案') Blank() Text('+ 新增档案') }
Text('为每个人建立可维护的关系画像')
this.PersonDetailCard()
this.PersonDetailCard()
this.PersonDetailCard()
}
.width('100%')
.padding({ left: 24, right: 24, top: 0, bottom: 140 })
}
.scrollBar(BarState.Off)
.height('100%')
.width('100%')
.backgroundColor('#F9F7F2')
}

和"维系"页一样,外层是 Scroll + Column,左右 24vp 内边距,底部 140vp 给导航栏留白。这些不再重复,这篇的重点是 PersonDetailCard 这张卡片。


二、标题行:左标题右操作

Row() {
Text('人物档案')
.fontSize(26)
.fontWeight(FontWeight.Bold)
.fontColor('#2C2723')
Blank()
Text('+ 新增档案')
.fontSize(15)
.fontColor('#8B7355')
}
.width('100%')
.alignItems(VerticalAlign.Center)
.margin({ top: 20, bottom: 6 })
.padding({ left: 2, right: 2 })

和"维系"页的问候区域一样,Row + Blank() 实现左右分布。但这里有一个额外细节:

2.1 alignItems(VerticalAlign.Center)

.alignItems(VerticalAlign.Center)

标题是 26 号字,操作按钮是 15 号字,高度差很大。如果不设居中对齐,按钮会贴着标题底部,视觉上偏下。VerticalAlign.Center 让两者垂直居中,看起来更平衡。

2.2 微调 padding

.padding({ left: 2, right: 2 })

2vp 的左右内边距,让标题行和下方副标题有微小的错位。这种"不完美对齐"反而让页面不那么机械。


三、副标题:一句话说明页面用途

Text('为每个人建立可维护的关系画像')
.fontSize(14)
.fontColor('#A0988C')
.width('100%')
.margin({ bottom: 24 })

14 号字、灰色 #A0988C,视觉上退到最远处。它的作用不是被阅读,而是让用户第一次进入页面时,花 0.5 秒理解"这个页面是干什么的"。


四、PersonDetailCard:整页的核心

从上到下三个区域:头部信息、分隔线、备注与标签。

@Builder
PersonDetailCard(
initial: string,
name: string,
relation: string,
intimacy: number,
note: string,
tags: string[],
lastContactDays: number,
accentColor: string
) {
Column() {
// 头部:头像 + 姓名/关系/亲密度
Row() { }
.width('100%')

// 分隔线
Divider().color('#F0EBE3').margin({ top: 18, bottom: 18 })

// 备注
Text(note)
.fontSize(14)
.lineHeight(22)
.fontColor('#7A7066')
.width('100%')

// 标签
Flex({ wrap: FlexWrap.Wrap }) { }
.width('100%')
}
.alignItems(HorizontalAlign.Start)
.padding(22)
.borderRadius(22)
.backgroundColor('#FFFFFF')
.shadow({ radius: 14, color: '#1A000007', offsetY: 4 })
.margin({ bottom: 16 })
}

接下来逐层拆开。


五、头部:头像 + 右侧信息

头部是一个 Row,左侧头像、右侧文字信息:

Row() {
// 头像
Column() {
Text(initial)
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
}
.width(56)
.height(56)
.borderRadius(28)
.justifyContent(FlexAlign.Center)
.backgroundColor(accentColor)

// 右侧信息
Column() {
Row() { } // 第一行:姓名 + 关系标签
Row() { } // 第二行:亲密度 + 上次沟通
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
.margin({ left: 16 })
}
.width('100%')

5.1 头像:56×56 圆形

.width(56)
.height(56)
.borderRadius(28)

比"维系"页的头像(40×40 和 50×50)都大。因为"档案"页的人物信息更详细,头像作为视觉锚点需要更大更醒目。

borderRadius 设为宽度的一半(28),形成正圆。

5.2 头像背景色由外部传入

.backgroundColor(accentColor)

accentColor 是卡片的参数之一,不同人物用不同颜色:

人物accentColor视觉感受
王奕辰 #8B7355 经典棕
林阿姨 #9B8578 温暖棕
陈若宁 #7A8B7A 沉稳绿

这个颜色不仅用在头像上,还用在关系标签和亲密度星标上,形成一张卡片一个主色调的效果。

5.3 右侧 Column 用 layoutWeight(1)

.layoutWeight(1)
.margin({ left: 16 })

头像固定 56vp,右侧文字用 layoutWeight(1) 填满剩余宽度。margin({ left: 16 }) 控制头像和文字之间的间距,比"维系"页的 12-14vp 稍大,因为这张卡片整体尺寸更大,间距也要相应放大。


六、第一行:姓名 + 关系标签

Row() {
Text(name)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#2C2723')
Text(relation)
.fontSize(12)
.fontColor(accentColor)
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
.borderRadius(8)
.backgroundColor('#FAF6EF')
.margin({ left: 10 })
}

6.1 关系标签的配色

.fontColor(accentColor)
.backgroundColor('#FAF6EF')

文字颜色用 accentColor(和头像同色),背景用 #FAF6EF(极浅的暖色)。这样标签和头像形成色彩呼应,同时浅底保证文字可读性。

6.2 药丸标签的 padding

.padding({ left: 10, right: 10, top: 4, bottom: 4 })
.borderRadius(8)

上下 4、左右 10 的内边距,配合 8vp 圆角,形成一个小药丸形状。字号 12 配合这个尺寸,视觉上紧凑但不拥挤。


七、第二行:亲密度星标 + 上次沟通

Row() {
ForEach([1, 2, 3, 4, 5], (star: number) => {
Text(star <= intimacy ? '★' : '☆')
.fontSize(13)
.fontColor(star <= intimacy ? '#D4B896' : '#E0D8CC')
.margin({ right: 2 })
})
Text(`· 上次沟通 ${lastContactDays} 天前`)
.fontSize(13)
.fontColor('#B5ADA2')
.margin({ left: 8 })
}
.margin({ top: 6 })

★★★★☆ · 上次沟通 12 天前

7.1 用 ForEach 渲染星标

ForEach([1, 2, 3, 4, 5], (star: number) => {
Text(star <= intimacy ? '★' : '☆')
})

5 颗星,intimacy 是几就亮几颗。ForEach 遍历 [1,2,3,4,5],每次判断当前星星是否应该亮起。

7.2 两色区分亮暗星

.fontColor(star <= intimacy ? '#D4B896' : '#E0D8CC')

亮星用金色 #D4B896,暗星用浅灰 #E0D8CC。两种颜色饱和度都不高,不会抢夺姓名的视觉焦点。

7.3 星标和文字之间用 · 分隔

Text(`· 上次沟通 ${lastContactDays} 天前`)
.margin({ left: 8 })

中圆点 · 作为星标和文字的分隔符,比竖线 | 更柔和。margin({ left: 8 }) 让分隔符和星标之间有 8vp 的间距。


八、分隔线

Divider().color('#F0EBE3').margin({ top: 18, bottom: 18 })

头部信息和备注之间用一条浅色分隔线隔开。#F0EBE3 是暖灰色,和页面整体色调一致。

上下各 18vp 的间距,让分隔线两侧都有足够的呼吸空间。


九、备注文字

Text(note)
.fontSize(14)
.lineHeight(22)
.fontColor('#7A7066')
.width('100%')

14 号字、22 行高,行间距约 8vp,阅读舒适。#7A7066 是中灰色,比主文字 #2C2723 浅,比辅助文字 #B5ADA2 深,适合这种"重要但不是最醒目"的信息。


十、标签区:Flex 自动换行

Flex({ wrap: FlexWrap.Wrap }) {
ForEach(tags, (tag: string) => {
Text(tag)
.fontSize(12)
.fontColor('#9A8E82')
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.borderRadius(14)
.backgroundColor('#F7F4EE')
.margin({ top: 14, right: 8 })
})
}
.width('100%')

10.1 为什么用 Flex 而不是 Row

Row 不会自动换行。如果标签太多,会超出屏幕宽度。

Flex({ wrap: FlexWrap.Wrap }) 会在空间不足时自动换行,标签数量从 1 到 N 都能正常展示。

10.2 标签的间距控制

.margin({ top: 14, right: 8 })

只设了 top 和 right,没有设 bottom 和 left。这样:

  • 水平方向:标签之间靠 right: 8 分隔。
  • 垂直方向:换行后靠 top: 14 分隔。
  • 第一行顶部不需要额外间距,因为备注文字已经提供了空间。

10.3 标签样式

.fontSize(12)
.fontColor('#9A8E82')
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.borderRadius(14)
.backgroundColor('#F7F4EE')

和关系标签不同,这里的标签用灰色 #9A8E82 + 浅底 #F7F4EE,视觉上更轻。因为一张卡片只有一个关系标签(重要),但可能有多个特征标签(咖啡爱好者、帮过我大忙…),特征标签不应该太抢眼。

borderRadius(14) 配合 padding 形成圆角药丸,和关系标签风格统一。


十一、卡片外壳

.alignItems(HorizontalAlign.Start)
.padding(22)
.borderRadius(22)
.backgroundColor('#FFFFFF')
.shadow({ radius: 14, color: '#1A000007', offsetY: 4 })
.margin({ bottom: 16 })

11.1 padding 22

比"维系"页的提醒卡片(padding 18)和久未联系卡片(padding 18)都大。因为这张卡片信息量更大,需要更多内边距让内容不显得拥挤。

11.2 borderRadius 22

圆角也更大(提醒卡片 20、久未联系卡片 18)。卡片越大,圆角也应该越大,否则会显得生硬。

11.3 阴影最轻

.shadow({ radius: 14, color: '#1A000007', offsetY: 4 })

#1A000007 的最后两位 07 表示约 3% 不透明度,是整页最轻的阴影。因为档案页只有一种卡片,不需要通过阴影强弱来区分层级——所有卡片地位平等。


十二、和"维系"页的对比

两个页面用了相同的外层结构(Scroll + Column),但卡片设计思路完全不同:

对比项维系页档案页
卡片种类 3 种(提醒、久未联系、统计) 1 种(PersonDetailCard)
卡片方向 提醒横向、久未联系横向 全部纵向
信息密度 提醒卡片高、久未联系低 统一中等密度
头像尺寸 40 / 50 56
卡片圆角 20 / 18 / 24 22
卡片内边距 18 / 18 / 26 22
分隔线 有(头部和备注之间)

核心区别:维系页用不同卡片表达不同优先级,档案页用同一卡片表达平等关系。


十三、总结

这篇我们拆解了"档案"页面的 UI 布局,核心要点:

  • 单一卡片纵向重复:页面结构极简,重点全在卡片设计上。
  • 头像 + layoutWeight:固定头像宽度,右侧信息弹性填充。
  • accentColor 贯穿卡片:头像、关系标签、星标共用一个主色,一张卡片一个色调。
  • ForEach 渲染星标:5 颗星根据亲密度动态亮灭,两色区分。
  • Flex 自动换行标签:标签数量不确定时,Flex({ wrap: FlexWrap.Wrap }) 是最稳妥的方案。
  • 分隔线划分区域:头部信息和备注之间用浅色 Divider 隔开,比留白更有结构感。
  • 尺寸随卡片放大:头像 56、padding 22、borderRadius 22,比小卡片都大一圈。
  • 赞(0)
    未经允许不得转载:171主机测评 » 【HarmonyOS 6】“档案“页面的UI布局拆解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址