DiaryCard 组件设计:情绪色条、置顶标识与多态内容
前言
卡片组件是内容型应用中最常见的 UI 模式。“海风日记“的DiaryCard组件承载了日记的摘要展示功能,包含情绪色条、置顶标识、时间戳、正文摘要、图片占位、标签和情绪 emoji 等丰富元素。
本文将从DiaryCard.ets源码出发,深入讲解卡片组件的设计思路、多态内容展示以及情绪色条映射机制。
一、组件属性设计
1.1 属性定义
@Component export struct DiaryCard { moodColor: MoodColor = 'default' // 情绪色类型 timeStr: string = '' // 时间字符串 content: string = '' // 正文摘要 tags: string[] = [] // 标签数组 isPinned: boolean = false // 是否置顶 hasImage: boolean = false // 是否有图片 moodEmoji: string = '' // 情绪 emoji onTap: () => void = () => {} // 点击回调 }1.2 属性分类
| 分类 | 属性 | 类型 | 展示效果 |
|---|---|---|---|
| 视觉 | moodColor | 颜色 | 左侧情绪色条 |
| 时间 | timeStr | 字符串 | 时间戳 |
| 内容 | content | 字符串 | 正文摘要 |
| 元数据 | tags,isPinned,hasImage | 布尔/数组 | 标签、置顶、图片标识 |
| 交互 | moodEmoji,onTap | 字符串/函数 | 表情图标、点击响应 |
二、情绪色条
2.1 颜色映射
function getMoodStripColor(mood: MoodColor): string { switch (mood) { case 'sunny': return COLOR_MOOD_SUNNY // 橙色 #F5A623 case 'calm': return COLOR_MOOD_CALM // 薄荷绿 #7ECAAE case 'ponder': return COLOR_MOOD_PONDER // 紫色 #A67EC0 case 'low': return COLOR_MOOD_SAD // 蓝色 #8BAFD6 default: return '#E8D5B0' // 默认米色 } }2.2 色条实现
Rect() .width(3.5) // 3.5vp 宽 .height('100%') // 与卡片等高 .fill(getMoodStripColor(this.moodColor)) .borderRadius({ topLeft: CARD_RADIUS, bottomLeft: CARD_RADIUS })2.3 情绪色与心情的对应
| 心情 | MoodColor | 色值 | 色条颜色 |
|---|---|---|---|
| 开心/晴天 | sunny | #F5A623 | 橙色 |
| 平静 | calm | #7ECAAE | 薄荷绿 |
| 感慨 | ponder | #A67EC0 | 紫色 |
| 低落 | low | #8BAFD6 | 蓝色 |
| 难过 | sad | #B0A8C8 | 淡紫 |
三、置顶标识
3.1 置顶条
if (this.isPinned) { Row({ space: 4 }) { SymbolGlyph($r('sys.symbol.pin')) .fontSize(10).fontColor([COLOR_PRIMARY_DEEP]) Text('置顶').fontSize(10).fontColor(COLOR_PRIMARY_DEEP) .fontWeight(FontWeight.Bold) } .width('100%') .padding({ left: 18, top: 4, bottom: 4 }) .backgroundColor('rgba(245,166,35,0.06)') }3.2 置顶标识的视觉设计
- 图标:
sys.symbol.pin图钉图标 - 文字:“置顶“标签
- 颜色:
COLOR_PRIMARY_DEEP(深橙色) - 背景:极淡橙色背景
rgba(245,166,35,0.06)
四、内容展示
4.1 正文摘要
Text(this.content) .fontSize(14.5).fontColor(COLOR_TEXT_MAIN) .lineHeight(25.4) .maxLines(5) // 最多显示 5 行 .textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出省略4.2 图片占位
if (this.hasImage) { Row() { SymbolGlyph($r('sys.symbol.camera')) .fontSize(20).fontColor(['#C8C0B0']) } .width('100%').height(86) .backgroundColor('#EDE0CC').borderRadius(9) .justifyContent(FlexAlign.Center) .margin({ bottom: 10 }) }4.3 标签和情绪
Row() { if (this.tags.length > 0) { Text(`#${this.tags[0]}`) // 只显示第一个标签 .fontSize(11).fontColor(COLOR_AMBER) .backgroundColor('rgba(245,166,35,0.08)') .padding({ left: 8, right: 8, top: 2, bottom: 2 }) .borderRadius(8) } Blank() if (this.moodEmoji.length > 0) { Text(this.moodEmoji).fontSize(14) } }五、卡片布局
5.1 完整布局
Row() { // 左侧情绪色条 Rect() .width(3.5).height('100%') .fill(getMoodStripColor(this.moodColor)) // 卡片内容 Column() { // 置顶标识(可选) if (this.isPinned) { ... } // 内容区 Column({ space: 6 }) { Text(this.timeStr) // 时间戳 Text(this.content) // 正文摘要 if (this.hasImage) { ... } // 图片占位 // 标签 + 情绪 Row() { ... } } } .layoutWeight(1) }5.2 卡片样式
.width('100%') .backgroundColor(COLOR_CARD_BG) .borderRadius(CARD_RADIUS) .shadow({ radius: 12, color: 'rgba(160,120,60,0.10)', offsetY: 2 }) .clip(true)六、组件的多态展示
6.1 不同状态下的卡片
| 状态 | 置顶 | 图片 | 标签 | 情绪 |
|---|---|---|---|---|
| 普通 | 无 | 无 | 有 | 有 |
| 置顶 | 有 | 无 | 有 | 有 |
| 图文 | 无 | 有 | 有 | 有 |
| 完整 | 有 | 有 | 有 | 有 |
七、常见问题与排查
7.1 卡片内容溢出
问题:正文内容超出卡片区域。
解决方案:使用maxLines和textOverflow控制文本溢出。
7.2 情绪色条不显示
问题:左侧情绪色条没有显示。
原因:Rect 的height('100%')需要父容器有明确高度。
解决方案:确保 Row 有明确的高度约束。
总结
本文通过“海风日记“的 DiaryCard 组件,深入讲解了卡片组件的设计:
- 属性设计:情绪色、时间、内容、标签、交互
- 情绪色条:颜色映射和实现
- 置顶标识:图标 + 文字 + 背景色
- 内容展示:正文摘要、图片占位、标签
- 多态展示:不同状态下的卡片样式
下一篇文章将深入讲解SymbolGlyph 与 FontColor 数组语法,敬请期待。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- Text 组件文档
- Rect 组件文档
- SymbolGlyph 文档
- 海风日记项目源码
- [HarmonyOS 开发者官网](https://atomgit.com/openharmony/docs
- 开源鸿蒙跨平台社区