news 2026/9/9 13:04:57

鸿蒙原生应用 ArkUI 声明式:实验室首页的 2 列 Grid 与三状态色

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙原生应用 ArkUI 声明式:实验室首页的 2 列 Grid 与三状态色

鸿蒙原生应用 ArkUI 声明式:实验室首页的 2 列 Grid 与三状态色

App 23「实验室设备预约」首页(HomeTab),主题色#0F766E深青色(teal),4 个 Tab 分别为首页(🔬)、设备(🧪)、预约(📅)、我的(👤)。首页采用紧凑布局——Header(实验室设备)+ 5 分类 Chip(全部/光学/电子/机械/化学)+ SectionTitle(设备列表)+2 列 Grid 6 台设备卡(60×100% emoji 图标块 + 名称 + 型号规格 + 3 状态色:空闲绿/使用中橙/维护中红)。本篇基于23-lab-booking/entry/src/main/ets/pages/HomeTab.ets(约 121 行)逐段拆解,附 4 张实机截图。

一、整体结构:3 块紧凑内容

App 23 首页是系列最紧凑的"设备列表"首页——3 个 @Builder 块:

build() { Column() { this.Header() Scroll() { Column({ space: 14 }) { this.ChipRow() this.SectionTitle('设备列表') this.DeviceGrid() } .width('100%') .padding({ left: D.pad, right: D.pad, top: 14, bottom: D.pad + this.safeBottom + 20 }) } .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top) } .width('100%').height('100%').backgroundColor(C.bg) }

3 块结构

  1. Header— "实验室设备"标题
  2. ChipRow— 5 分类胶囊(全部/光学/电子/机械/化学)
  3. SectionTitle('设备列表') + DeviceGrid— 2 列 Grid 6 台设备

与 App 21 问卷首页同构(3 块紧凑结构)——"设备列表 = 任务型列表"(用户来"找设备→预约"),不需要复杂首页。

主题色#0F766E深青色——实验室/科研/专业的调性(深青色接近"实验服蓝绿"、显微镜/试剂瓶的视觉联想)——与 App 19 青绿 #0D9488 同系但更深——**"深青 = 科研严肃、浅青 = 摄影清新"**同系不同调。

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

二、Header + ChipRow

Header 是"实验室设备"单行标题(无 Slogan——"工具型首页不配 Slogan")。

ChipRow 是 5 个分类(全部/光学/电子/机械/化学)的横滑胶囊:

@Builder ChipRow() { Scroll() { Row({ space: 10 }) { ForEach(this.cats, (cat: string, idx: number) => { Text(cat) .fontSize(13) .fontColor(this.activeCat === idx ? '#FFFFFF' : C.textSub) .padding({ left: 14, right: 14, top: 7, bottom: 7 }) .backgroundColor(this.activeCat === idx ? C.primary : C.card) .borderRadius(16) .onClick(() => { this.activeCat = idx; }) }, (cat: string) => cat) } } .scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off).width('100%') }

5 个分类['全部', '光学', '电子', '机械', '化学']——实验室设备的 4 大分类(光学/电子/机械/化学是高校实验室的标准分类)。

@State activeCat: number = 0默认选中"全部"——onClick切选中态(activeCat === idx ? 深青底白字 : 白底灰字)。"假筛选"(同系列其他 Chip)——demo 未联动过滤,真实项目应加filteredDevices()

borderRadius(16)胶囊形——系列标准 Chip。

三、SectionTitle + DeviceGrid:2 列 Grid(本页核心)

SectionTitle 是"设备列表"标题(无右侧链接——简化版)。DeviceGrid 是 2 列 Grid 6 台设备

@Builder DeviceGrid() { Grid() { ForEach(this.devices, (d: Device) => { GridItem() { Column({ space: 8 }) { Row() { Text(d.emoji).fontSize(30) } .width('100%').height(60) .backgroundColor(C.cardSoft).borderRadius(D.rSm) .justifyContent(FlexAlign.Center) Text(d.name).fontSize(13).fontColor(C.text).maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }).width('100%') Text(d.spec).fontSize(11).fontColor(C.textDim).width('100%') Row() { Blank() Text(d.status).fontSize(11).fontColor(d.statusColor).fontWeight(FontWeight.Medium) } .width('100%') } .width('100%') .padding(10) .backgroundColor(C.card).borderRadius(D.rMd) .border({ width: 1, color: C.stroke }) .onClick(() => { promptAction.showToast({ message: d.name }); }) } }, (d: Device) => d.id.toString()) } .columnsTemplate('1fr 1fr') .columnsGap(12) .rowsGap(12) .width('100%') }

3.1 6 台设备的数据

private devices: Device[] = [ { id: 1, emoji: '🔬', name: '高倍显微镜', spec: '1000x · 偏光', status: '空闲', statusColor: C.ok }, { id: 2, emoji: '⚡', name: '示波器', spec: '200MHz · 4通道', status: '使用中', statusColor: C.warn }, { id: 3, emoji: '🧪', name: '高效液相色谱仪', spec: 'UV检测器', status: '空闲', statusColor: C.ok }, { id: 4, emoji: '🔩', name: '万能试验机', spec: '100kN', status: '维护中', statusColor: C.danger }, { id: 5, emoji: '🔭', name: '光谱分析仪', spec: '200-800nm', status: '空闲', statusColor: C.ok }, { id: 6, emoji: '📡', name: '网络分析仪', spec: '9kHz-6GHz', status: '使用中', statusColor: C.warn } ];

6 台设备覆盖 4 大分类

设备分类型号规格状态
🔬 高倍显微镜光学1000x · 偏光空闲(绿)
⚡ 示波器电子200MHz · 4通道使用中(橙)
🧪 高效液相色谱仪化学UV检测器空闲(绿)
🔩 万能试验机机械100kN维护中(红)
🔭 光谱分析仪光学200-800nm空闲(绿)
📡 网络分析仪电子9kHz-6GHz使用中(橙)

6 台设备的"真实实验室设备":显微镜/示波器/色谱仪/试验机/光谱仪/网络分析仪——都是真实的科研仪器(高校实验室常见设备)——"设备列表 = 真实科研环境"

3 状态分布:空闲 3 台(绿)/使用中 2 台(橙)/维护中 1 台(红)——"多空闲、少维护"是实验室常态

3.2 3 状态色映射

  • 空闲C.ok绿(可预约)
  • 使用中C.warn橙(被占用)
  • 维护中C.danger红(不可用)

3 状态 3 色——**"空闲绿/使用橙/维护红"**是设备管理/会议室预约的标准色映射——与 App 14 场地(空闲/已约满)、App 22 投票(进行中/已结束)同款"状态色编码"。

3.3 设备卡的 4 层结构

每张设备卡 4 行(从上到下):

  1. 60 高 emoji 图标块C.cardSoft浅灰底 + 🔬/⚡ 等)
  2. 设备名称(13sp 深色 +maxLines(1)截断)
  3. 型号规格(11sp 灰)——"1000x · 偏光"等
  4. 状态(11sp 状态色 + 加粗 + 右对齐Blank()

Blank()把状态推到右下角——"名称左上、状态右下"的视觉节奏

maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })设备名截断——"高效液相色谱仪" 7 个字在 1 列内放不下——Ellipsis省略(实际显示"高效液相色…")——"Grid 卡片文字必须截断"(列宽有限)。

3.4 2 列 Grid 布局

columnsTemplate('1fr 1fr')+columnsGap(12)+rowsGap(12)——2 列等宽 + 12vp 间隙——6 台设备排成 3 行 2 列。

"2 列 Grid vs 1 列列表"

  • 2 列(本页)——信息密度高(一屏看 4 台)、紧凑
  • 1 列(App 21/22)——信息完整(每行有按钮)、宽松

"设备列表用 2 列 Grid"是合理选择——设备卡信息少(名称+规格+状态),2 列紧凑展示——"信息少的列表用 Grid、信息多的列表用 List"

四、@State 与"紧凑首页"设计

HomeTab 只有1 个 @StateactiveCat(分类 0-4)。其余数据private不可变。

App 23 首页是系列最紧凑的设备列表(3 块)——**"设备预约 = 找设备 → 看详情 → 预约"**的任务流——首页只负责"找设备"(列表展示)。

对比 App 14 运动场地预约首页(5 块:Hero/入口/周图/场地/排行)——App 14 首页"丰富"因为"运动"是内容型(场地推荐需要营销)——App 23 首页"紧凑"因为"实验室设备"是任务型(用户知道要什么设备)——**"业务类型决定首页复杂度"**再次验证。

五、设备状态与"预约意愿"的联动

App 23 首页的 3 状态直接决定"用户要不要点进详情预约":

状态 → 用户行为

  • 空闲(绿)→ "可以预约" → 点进详情 → 选时段 → 预约
  • 使用中(橙)→ "被占用了" → 可能等/换设备
  • 维护中(红)→ "坏了" → 换设备/联系管理员

"状态 = 预约意愿的引导"——用户扫一眼 Grid 就知道"哪台能约"——"状态色可视化 = 高效筛选"

真实项目的状态扩展

  • 已锁定(被特定用户预约,但还没用)
  • 预约中(未来时段已被预约)
  • 待维护(快需要维护)

"状态机"从 3 态扩展为 6 态——UI 只需改"状态名 + 状态色"(数据结构不变)——"状态可扩展性"是设备管理的基础

六、"设备状态色"与系列状态色的统一体系

App 23 首页的 3 状态色(空闲绿/使用中橙/维护中红)与系列其他 App 的状态色形成统一体系:

状态语义颜色出现位置
空闲/可用/进行中绿C.okApp 23 设备、App 14 场地、App 22 投票
使用中/待处理/即将结束C.warnApp 23 设备、App 22 投票、App 15 环保
维护/已满/已结束C.dangerApp 23 设备、App 14 场地、App 16 商城

"绿=可用、橙=警示、红=不可用"是系列统一的状态色语义——读者在多个 App 间切换不会混淆(同一颜色永远代表同一类语义)——"跨 App 状态色一致性"是设计系统的一致性原则

"状态色映射"的工程实现(App 23 设备卡):

// 数据携带颜色(当前实现) { status: '空闲', statusColor: C.ok } { status: '使用中', statusColor: C.warn } { status: '维护中', statusColor: C.danger }

真实项目应抽成"状态 → 颜色"映射表

const STATUS_COLOR = { '空闲': C.ok, '使用中': C.warn, '维护中': C.danger, '已锁定': C.textDim, '待维护': C.warn }; // 数据只存 status 字符串,颜色查表

"映射表代替数据携带颜色"——新增状态只改映射表一处,数据与视觉解耦。

七、"2 列 Grid" vs "1 列 List" 的选择标准

App 23 设备卡用 2 列 Grid(信息紧凑),对比系列其他列表:

App主列表布局卡片信息量
21 问卷问卷卡1 列 List中(emoji+标题+状态)
22 投票投票卡1 列 List中(emoji+标题+状态+剩余)
23 实验室设备卡2 列 Grid低(emoji+名称+规格+状态)
13 音乐项目卡1 列 List高(emoji+标题+标签+进度条)

"Grid vs List"选择标准

  • 信息少 + 数量多(设备 6 台、规格短)→2 列 Grid(一屏看更多)
  • 信息多 + 操作多(项目有进度条+按钮)→1 列 List(每行完整展示)

"卡片信息量决定布局"——信息少的卡片适合 Grid(高密度)、信息多的适合 List(完整性)

"2 列 Grid"的注意点

  • 卡片宽度减半 →文字必须截断maxLines(1)+ Ellipsis)
  • 状态/操作按钮空间小 →只用"状态文字"不用按钮
  • 点击区域小 →整卡可点(GridItem onClick)

App 23 设备卡的"Grid 三原则"(截断/无按钮/整卡可点)是 2 列 Grid 的标准实践。

八、设备列表的"搜索与筛选"扩展

App 23 首页有分类 Chip(光学/电子/机械/化学)但无搜索框——真实设备管理应有**"分类 + 搜索"双筛选**:

// 真实项目的双筛选 private filteredDevices(): Device[] { let result = this.devices; if (this.activeCat > 0) { const catName = this.cats[this.activeCat]; result = result.filter(d => this.catOf(d.id) === catName); } if (this.keyword.trim() !== '') { result = result.filter(d => d.name.includes(this.keyword.trim()) || d.spec.includes(this.keyword.trim())); } return result; }

"分类 + 搜索"双条件过滤——activeCat(分类)+keyword(搜索词)两个 @State 组合过滤——"多条件筛选"是设备/商品列表的标准

真实设备的"分类映射"

// 设备 → 分类映射 const DEVICE_CATEGORY: Record<number, string> = { 1: '光学', 2: '电子', 3: '化学', 4: '机械', 5: '光学', 6: '电子' };

"分类映射表"catOf()一行查表——"设备与分类的关系数据化"(当前 demo 的 devices 数组没有 category 字段,是"假分类")——"分类字段缺失是'假筛选'的根源"——真实项目每个设备应有category字段。

九、设备卡的"信息密度"与"科研设备命名"

App 23 的 6 台设备卡的"信息密度"设计:

每张卡 4 行信息的层级

  1. emoji 图标(30sp)——视觉锚点(最高信息密度)
  2. 设备名(13sp 加粗)——核心识别
  3. 规格(11sp 灰)——补充参数
  4. 状态(11sp 状态色)——行动信号

"图标 + 名称 + 规格 + 状态"4 层——从"最直观"到"最行动"的视觉递减——"科研设备卡"的信息架构

"科研设备命名"的专业性

  • 高倍显微镜(1000x · 偏光)
  • 高效液相色谱仪(UV 检测器)
  • 万能试验机(100kN)
  • 光谱分析仪(200-800nm)
  • 网络分析仪(9kHz-6GHz)

"型号规格"都是真实科研参数(倍率/通道/检测器/量程/频段)——"专业参数 = 科研可信度"——用户(科研人员)一眼看懂"这设备能干什么"——"设备卡是给专家看的"(对比 App 16 商品卡给消费者看价格,设备卡给科研人员看参数)。

十、"任务型首页"的 3 原则

App 23 首页是"任务型首页"的范本——3 个设计原则:

原则 1:分类优先(Chip 在最上方)——用户第一件事是"找分类"(光学/电子/机械/化学)——"分类 = 任务的第一步"

原则 2:列表高效(2 列 Grid 一屏 4 台)——用户快速扫设备——"一屏看到尽可能多"

原则 3:状态信号(状态色右对齐)——用户判断"哪台能约"——"状态 = 决策依据"

**"分类 → 扫视 → 决策"**是任务型首页的用户路径——与内容型首页(App 19 摄影"欣赏→收藏")的差异——任务型用户"目的明确"、内容型用户"浏览探索"。

读者做"任务型首页"时 3 原则自查

  • 分类在最上面了吗?
  • 列表一屏够多吗?
  • 关键状态一眼可见吗?

十一、总结

App 23 首页解析完毕。3 块紧凑结构 + 5 分类 Chip + 2 列 Grid 6 设备卡(3 状态色)是核心组件。"设备状态 → 预约意愿"的联动是设备预约场景的特色。**"2 列 Grid 紧凑设备列表"是任务型首页的范本。"Grid vs List 选择标准"、"分类映射表"、"任务型首页 3 原则"**是真实项目的关键改进。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 13:04:02

版图设计入门必备:L-Edit 11.1安装配置实战与高效绘图技巧

简介&#xff1a;L-Edit 11.1 是一款面向半导体设计领域的版图布局工具&#xff0c;常用于集成电路物理布局、封装设计、传感器微系统设计以及教学科研。资源共包含 620 个文件&#xff0c;压缩包约 26.76MB&#xff0c;涵盖可执行程序、动态链接库、头文件与 C 源码、批量处理…

作者头像 李华
网站建设 2026/9/9 13:03:29

Python一站式开发指南:从环境配置到打包exe全流程

提到Python&#xff0c;很多人张嘴就是“写代码”&#xff0c;但真到自己上手&#xff0c;光是把开发环境跑通就能折腾一晚上。我搞Python这些年&#xff0c;最深的体会是&#xff1a;Python本身并不难&#xff0c;难的是把环境、编辑器、依赖、调试、打包这一整条链路一次性理…

作者头像 李华
网站建设 2026/9/9 13:02:35

C++实时曲线绘制全攻略:环形缓冲区与QCustomPlot优化

简介&#xff1a;这是面向C开发者的一份实时曲线绘制示例工程&#xff0c;适合需要快速实现数据可视化的科学计算、工程监测和数据分析场景。项目基于MFC框架&#xff0c;提供了一个名为MultiColorPlotCtrl的多色曲线控件&#xff0c;能够支持多条数据系列的同时显示与更新&…

作者头像 李华
网站建设 2026/9/9 13:00:42

Qt 4.8.6 MSVC2010 X64开发环境搭建与部署实战指南

简介&#xff1a;面向Windows 64位平台的QT4.8.6安装包&#xff0c;基于MSVC2010编译器构建&#xff0c;适合需要在Visual Studio 2010中编写C程序、使用qmake构建工具或维护旧版Qt项目的开发者&#xff0c;也方便入门Qt的Windows开发者快速搭建桌面应用环境。压缩包共13918个文…

作者头像 李华
网站建设 2026/9/9 12:58:46

LeetCode 230:二叉搜索树第K小元素三种解法与面试详解

LeetCode 230题“二叉搜索树中第k小的元素”是Java面试里出现频率极高的一道题。题目本身不长&#xff1a;给定一棵二叉搜索树&#xff08;BST&#xff09;的根节点root&#xff0c;和一个整数k&#xff0c;返回其中第k小的元素。简单说&#xff0c;就是在一个树结构里做一次“…

作者头像 李华