鸿蒙原生应用实战:资料页的左右分栏布局实现
鸿蒙原生应用实战:资料页的左右分栏布局实现
App 34「校园打印资料共享」资料(Func1Tab),主题色
#27AE60草绿。资料页采用"Header + 左右分栏"的独特布局——白色 Header("资料库"标题) + 左侧 CourseSide 课程栏(96 宽浅绿底,高等数学/大学英语/数据结构/线性代数/大学物理 5 个课程,@State activeCourse 单选,选中白底草绿加粗字) + 右侧 DocArea 文档列表(📄 第一章 极限与连续 2.1MB 12 页 / 第二章 导数与微分 1.8MB 10 页 / 历年真题合集 5.6MB 48 页 / 公式速查手册 0.9MB 6 页,每条含 28 号 emoji + 标题 + "大小 · 页数" + ⬇️ 下载按钮)。本篇基于34-print-share/entry/src/main/ets/pages/Func1Tab.ets(约 84 行)逐段拆解,附 4 张实机截图。
一、整体结构:三区"Header + 左右分栏"布局
App 34 资料页是"标题 + 左侧课程导航 + 右侧内容"的左右分栏布局——3 个 @Builder 块:
build() {
Column() {
this.Header()
Row() {
this.CourseSide()
this.DocArea()
}.layoutWeight(1).width('100%')
}
.width('100%').height('100%').backgroundColor(C.bg)
}
3 块结构:
- Header — 白色背景 + "资料库"标题
- CourseSide — 左侧课程导航栏(96 宽)
- DocArea — 右侧文档列表
Row() { this.CourseSide(); this.DocArea() } 左右分栏——"Row 水平分栏"——"左导航 + 右内容"——"经典分栏布局"——"系列首个左右分栏页"——"从上下滚动到左右分栏"——"布局的进化"。
与 App 34 首页对比:首页是"上下滚动"四区布局、资料页是"左右分栏"布局——"34 内部两种布局"——"首页展示、资料浏览"——"两种布局的业务适配"——"资料分类用分栏"。
与系列其他 App 对比:
- App 32 地图:上下滚动
- App 33 首页:网格
- App 34 资料:左右分栏(系列首次)
"左右分栏的优势"——"课程切换不跳页"——"导航 + 内容同屏"——"分类浏览效率高"——"桌面/平板常用布局"——"手机上的分栏"——"分栏的适配"。
主题色 #27AE60 草绿——同首页——"品牌色贯穿全 App"。

二、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) 底部对齐——"避开状态栏"——"标准适配"。
与首页 Header 对比——首页是"双行 + 🖨️ 图标"、资料页是"单行标题"——"首页品牌、资料功能"——"Header 形态 = 页面性质"。
三、CourseSide:左侧课程栏(本页核心)
CourseSide 是 96 宽浅绿底的 5 课程导航栏:
@Builder
CourseSide() {
Column() {
ForEach(this.courses, (c: string, idx: number) => {
Text(c).fontSize(13)
.fontColor(this.activeCourse === idx ? C.primary : C.textSub)
.fontWeight(this.activeCourse === idx ? FontWeight.Bold : FontWeight.Normal)
.width('100%').padding({ top: 16, bottom: 16, left: 12 })
.backgroundColor(this.activeCourse === idx ? C.card : Color.Transparent)
.onClick(() => { this.activeCourse = idx; })
}, (c: string) => c)
}
.width(96).height('100%').backgroundColor(C.cardSoft)
}
CourseSide 结构:96 宽 Column + 5 个课程 Text(ForEach)+ 浅绿底——"垂直导航栏"。
private courses: string[] = ['高等数学', '大学英语', '数据结构', '线性代数', '大学物理'] 5 课程——"5 个课程分类"——"高数/英语/数据结构/线代/物理"——"大学核心课程"——"分类的完整"。
@State activeCourse: number = 0 选中状态——"当前课程索引"——"默认高数"——"单选"——"@State 状态管理"。
fontColor(this.activeCourse === idx ? C.primary : C.textSub) 选中绿字——"选中草绿、未选灰"——"颜色 = 选中"——"对比"。
fontWeight(this.activeCourse === idx ? FontWeight.Bold : FontWeight.Normal) 选中加粗——"加粗 = 选中"——"双重提示"——"颜色 + 字重"。
backgroundColor(this.activeCourse === idx ? C.card : Color.Transparent) 选中白底——"选中白底、未选透明"——"白色 = 选中"——"第三个选中提示"——"三重选中态"——"选中态的冗余强化"。
padding({ top: 16, bottom: 16, left: 12 }) 16 上下 + 12 左——"课程项的内边距"——"高点击区"——"32 高每项"——"5 项 160 高"。
onClick(() => { this.activeCourse = idx; }) 点击切换——"点击换课程"——"状态驱动"——"声明式 UI"——"改状态即换选中"。
Column().width(96).height('100%').backgroundColor(C.cardSoft) 96 宽浅绿底——"导航栏背景"——"96 = 手机分栏宽度"——"浅绿 = 分区"——"与内容区分"——"视觉分区"。
ForEach(this.courses, (c: string, idx: number) => {...}, (c: string) => c)——"数据驱动导航"——"5 课程 = 5 项"——"改数据即改导航"——"key = 课程名"。
选中态的三重提示——"绿字 + 加粗 + 白底"——"三重冗余"——"用户不可能看错"——"选中态的强提示"——"无障碍设计"——"色盲也能识别(白底)"。
与 App 31 ChipRow 对比:
- App 31:横向 5 分类 Chip
- App 34:纵向 5 课程栏
"横向 vs 纵向"——"31 横滑 Chip、34 垂直导航"——"两种分类形态"——"横向省空间、纵向留内容区"——"分栏布局的选择"——"34 用纵向分栏"。
与 App 33 对比——App 33 无课程分类、App 34 有课程栏——"课程栏 = 学习类 App"——"分类 = 资料组织"。

四、DocArea:右侧文档列表
DocArea 是 4 个文档的列表:
@Builder
DocArea() {
Scroll() {
Column({ space: 12 }) {
ForEach(this.docs, (d: Doc) => {
Row({ space: 12 }) {
Text(d.emoji).fontSize(28)
Column({ space: 4 }) {
Text(d.title).fontSize(14).fontColor(C.text).maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(d.size + ' · ' + d.pages + ' 页').fontSize(12).fontColor(C.textDim)
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Text('⬇️').fontSize(18)
.onClick(() => { promptAction.showToast({ message: '下载: ' + d.title }); })
}
.width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
}, (d: Doc) => d.id.toString())
}
.width('100%').padding({ left: 12, right: D.pad, top: 14, bottom: this.safeBottom + 20 })
}
.layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top)
}
DocArea 结构:Scroll + Column(12 间距)+ 4 条文档 Row——"可滚动的文档列表"。
每条文档卡的结构:
- 左 📄 28 号 emoji
- 中 文字区(标题 14 号 + "2.1MB · 12 页" 12 号灰)
- 右 ⬇️ 18 号下载按钮
4 个文档(每条 5 要素):
| emoji | 标题 | 大小 | 页数 |
|---|---|---|---|
| 📄 | 第一章 极限与连续 | 2.1MB | 12 页 |
| 📄 | 第二章 导数与微分 | 1.8MB | 10 页 |
| 📄 | 历年真题合集 | 5.6MB | 48 页 |
| 📄 | 公式速查手册 | 0.9MB | 6 页 |
Text(d.title).maxLines(1).textOverflow 标题截断——"单行省略"——"长标题截断"——"14 号黑"。
Text(d.size + ' · ' + d.pages + ' 页') 大小 + 页数——"2.1MB · 12 页"——"· 中点分隔"——"文件信息"——"12 号灰"——"体积 + 页数"。
Text('⬇️').fontSize(18) 下载按钮——"18 号下载箭头"——"下载 = 获取"——"点击下载"。
onClick(() => promptAction.showToast({ message: '下载: ' + d.title })) 下载反馈——"下载: 第一章 极限与连续"——"Toast 反馈"——"占位下载"——"真实产品下载 PDF"。
padding(14).borderRadius(D.rMd).border({ width: 1, color: C.stroke }) 14 padding + 14 圆角 + 1px 边框——"列表卡标准"。
padding({ left: 12, right: D.pad, top: 14 }) 左 12 右 16——"与课程栏衔接"——"左侧 12 留白"——"分栏的间距"。
文档的组织——"章节 + 真题 + 手册"——"第一章/第二章(讲义)+ 真题(练习)+ 手册(速查)"——"资料的类型多样"——"学习资料全集"——"demo 的完整性"。
"48 页真题"——"历年真题最多"——"5.6MB 最大"——"真题 = 核心资料"——"体积与页数的关联"——"数据合理"。
"6 页手册"——"公式速查手册最少"——"0.9MB 最小"——"手册 = 便携"——"资料的多样性"。
Doc 模型(5 字段):
interface Doc {
id: number;
emoji: string;
title: string;
size: string;
pages: number;
}
5 字段:id/emoji/title/size/pages——"文档实体"——"大小 + 页数"——"文件元信息"——"完整建模"。
size: string 大小字符串——"2.1MB/1.8MB/5.6MB/0.9MB"——"带单位"——"字符串内联单位"。
pages: number 页数数值——"12/10/48/6"——"打印页数"——"与打印关联"——"页数 = 打印成本"——"0.1 元 × 页数"——"打印费用预览"。

五、资料页的交互细节与可用性分析
5.1 左右分栏的"效率"
左导航 + 右内容——"课程切换不跳页"——"同屏浏览"——"效率高"——"分栏的价值"——"系列首创"。
5.2 课程选中的"三重提示"
绿字 + 加粗 + 白底——"三重选中态"——"冗余强化"——"不可能看错"——"无障碍"——"选中态的强表达"。
5.3 下载按钮的"快捷"
⬇️ 一键下载——"18 号下载箭头"——"快捷操作"——"Toast 反馈"——"下载 = 核心操作"。
5.4 文档信息的"打印关联"
2.1MB · 12 页——"页数 = 打印成本"——"0.1 元 × 12 页 = 1.2 元"——"打印费用预览"——"文档 + 打印的关联"——"业务的完整"。
5.5 课程栏的"数据驱动"
courses 数组 → ForEach——"改数据即改导航"——"5 课程"——"声明式 UI"——"导航的灵活性"。
5.6 资料页的"色彩心理学"
草绿(#27AE60)——"绿色 = 学习/环保"——"资料 = 纸"——"绿色 = 阅读"——"分栏的浅绿底"——"视觉分区"。
5.7 资料页的"信息层级"
L1 标题(Header)→ L2 分类(课程栏)→ L3 内容(文档列表)——"3 层信息"——"从标题到分类到内容"——"分栏的信息架构"。
5.8 资料页的"决策路径"
选课程(导航)→ 看文档(列表)→ 点下载 → 打印——"4 步决策"——"从分类到下载"——"资料页的转化链"。
5.9 资料页的"对比与统一"
统一:4 文档同结构(emoji/标题/大小/下载)——"列表项的统一"。 对比:4 文档数据不同(标题/大小/页数)——"差异在数据"——"结构同构 + 数据异构"。
5.10 资料页的"demo 完整性"
课程栏 + 文档列表 + 下载 = 完整资料页——"功能完整"——"可浏览可下载"——"demo 的完成度"。
5.11 资料页的"系列创新"
左右分栏是系列首次——"34 资料页的创新"——"分栏布局"——"系列布局的丰富"——"分类浏览的范式"。
5.12 资料页的"设计哲学"
资料页的 3 个设计哲学:
- 分类优先——课程栏主导航
- 内容优先——文档列表主内容
- 操作优先——⬇️ 一键下载
"分类 + 内容 + 操作的资料页"——"分栏型页面的设计原则"——"从哲学看设计"。
5.13 资料页的"终评"
课程栏 + 文档列表 + 下载 = 完整资料页——"资料页的完成度"——"可上线级"——"系列分栏型页面的标杆"。
5.14 课程栏的"宽度 96"
96 宽——"手机分栏宽度"——"约 1/4 屏宽"——"导航 + 内容的比例"——"分栏的比例设计"。
5.15 资料页的"文档 emoji"
📄 统一 emoji——"文档符号"——"4 文档同 📄"——"文档类型的统一"——"emoji 的简单"。
5.16 资料页的"下载反馈"
"下载: 第一章 极限与连续"——"下载的反馈"——"Toast 反馈"——"占位下载"——"真实产品下载 PDF"——"反馈的完整"。
5.17 资料页的"页数信息"
12/10/48/6 页——"页数 = 打印页数"——"打印成本关联"——"页数的价值"——"打印 App 的文档信息"。
5.18 资料页的"课程与文档"
课程栏(分类) vs 文档(内容)——"导航与内容的关联"——"demo 静态展示"——"真实产品按课程过滤文档"——"扩展点"。
5.19 资料页的"分栏 vs 标签页"
左右分栏 vs 顶部 Tab——"两种分类形态"——"34 用分栏、31 用 Chip"——"分栏 = 内容区大"——"Tab = 内容区全宽"——"布局的取舍"——"分栏适合并列展示"。
5.20 资料页的"导航宽度 96"
96 宽占屏 1/4——"手机分栏的比例"——"96 = 够放 4 字课程名"——"导航的最小宽度"——"比例的合理"——"分栏的比例设计"。
5.21 资料页的"下载成本"
页数 → 打印成本——"48 页 × 0.1 元 = 4.8 元"——"6 页 × 0.1 元 = 0.6 元"——"下载前的成本预览"——"页数信息的价值"——"打印 App 的数据关联"。
5.22 资料页的"三重选中态无障碍"
白底是色盲可识别——"绿字可能混淆"——"白底保证可识别"——"三重冗余 = 无障碍"——"选中态的包容性"——"设计的可及性"。
5.23 资料页的"emoji 与图标"
📄 文档 + ⬇️ 下载——"2 个 emoji"——"文档符号 + 下载箭头"——"低成本图标"——"emoji 的语义"——"图标即功能"。
5.24 资料页的"下载反馈完整"
"下载: 第一章 极限与连续"——"文件名在反馈中"——"反馈的明确"——"用户确认下载对象"——"反馈的精准"——"操作的确定性"。
5.25 资料页的"demo 价值"
分栏 + 课程 + 文档 = 完整资料页——"可浏览可下载"——"demo 的可用"——"分栏模板"——"后续分类 App 可复用"——"模板沉淀"。
5.26 资料页的"视觉节奏"
课程栏(垂直节奏) + 文档列表(水平行)——"两种视觉方向"——"导航垂直、内容水平"——"视觉的交叉"——"分栏的视觉韵律"——"方向的对比"。
5.28 资料页的"数据流"
courses 数组 → 课程栏 → 选中 → 文档列表——"数据流"——"课程选中驱动文档"——"demo 静态展示"——"真实产品 filter 联动"——"数据的扩展"。
5.29 资料页的"打印关联"
文档页数 → 打印成本——"48 页 = 4.8 元、12 页 = 1.2 元"——"资料页与首页价格 Banner 呼应"——"跨页数据"——"打印的完整链路"——"业务的闭环"。
5.30 资料页的"用户场景"
"考前复习找资料"——"学生场景"——"选课程 → 找讲义 → 下载 → 打印"——"场景驱动"——"资料页的服务价值"——"学习资料的获取"。
5.31 资料页的"颜色一致性"
浅绿课程栏 + 草绿选中字——"绿色贯穿"——"导航的绿色"——"品牌一致"——"色彩的辨识"——"绿色 = 资料库"。
5.32 资料页的"最终设计评价"
分栏 + 课程 + 文档 = 完整资料页——"从结构到配色到交互的完整"——"可上线级"——"系列分栏标杆"——"资料页的完成度评级"。

六、总结:草绿 + 左右分栏 + 课程导航
App 34 资料页一句话:用草绿(#27AE60)组织一个"课程栏 + 文档列表"的左右分栏资料页——左侧 96 宽浅绿课程栏用绿字 + 加粗 + 白底三重选中态展示 5 课程,右侧文档列表用 📄 emoji + 标题 + 大小页数 + ⬇️ 下载按钮展示高数资料。
3 个设计亮点:
- 左右分栏布局——系列首个"左导航 + 右内容"分栏页
- 三重选中态——绿字 + 加粗 + 白底冗余强化
- 下载按钮——⬇️ 一键下载 + 页数打印成本关联
主题色设计逻辑:草绿 = 学习/打印/环保——"资料页用草绿,与首页品牌色一致"——"品牌贯穿"。
与系列呼应:固定 Header(系列)、ForEach 列表(系列)、@State 单选(31 菜单/33 骑行)、emoji 图标(系列)、下载按钮(26 上传)——"34 资料把系列的状态 + 列表 + 下载手法组合出'资料库'场景"。
体验细节:课程切换、三重选中、下载反馈、页数信息——"资料页的核心 = 让用户'3 秒选课程 + 5 秒下文档'"。
可扩展性展望:课程过滤联动、真实下载、文档预览、打印跳转、搜索、收藏——"demo 的资料页骨架完整"。
六、扩展思考:资料页的分栏架构与设计哲学
6.1 资料页的"浏览路径"
完整浏览路径:
看 Header(资料库)→ 选课程(左侧导航)→ 看文档(右侧列表)→ 点下载 → 打印
"分栏的浏览路径"——"导航 + 内容同屏"——"课程切换不跳页"——"效率最大化"——"资料浏览的标准范式"。
6.2 资料页的"信息架构"
3 层信息:
- L1 标题(Header)——"资料库"
- L2 分类(CourseSide)——"什么课程"
- L3 内容(DocArea)——"什么文档"
"3 层渐进式"——"从标题到分类到内容"——"分栏的信息金字塔"——"用户按需深入"。
6.3 资料页的"业务建模"
Doc 模型 5 字段(id/emoji/title/size/pages)——"5 字段建模"——"文档的核心字段"——"最小可用集"——加作者(author)、加时间(time)、加下载量(downloads)即可扩展——"数据模型的扩展点"。
6.4 资料页的"对比与统一"
统一:4 文档同结构(emoji/标题/大小/下载)——"列表项的统一"。 对比:4 文档数据不同(标题/大小/页数)——"差异在数据"——"结构同构 + 数据异构"。
6.5 资料页的"设计哲学"
资料页的 3 个设计哲学:
- 分类优先——课程栏左侧主导航
- 内容优先——文档列表右侧主内容
- 操作优先——⬇️ 下载按钮直达
"分类 + 内容 + 操作的资料页"——"分栏型页面的设计原则"——"从哲学看设计"——"这套方法论可直接迁移到任何分类浏览型 App"。
6.6 资料页的"终评"
App 34 资料页综合评估——"分栏结构 + 草绿主题 + 完整浏览链"——"资料页的完成度评级"——"一个可上线级的分类资料页"——"系列分栏型页面的标杆"——"demo 的高完成度"。
七、彩蛋:资料页的细节设计
7.1 课程栏的"5 课程选择"
高等数学/大学英语/数据结构/线性代数/大学物理——"大学核心 5 课程"——"理工科必备"——"分类的完整"——"学习的场景"——"5 = 常见分类数"。
7.2 "高等数学" 默认选中
activeCourse = 0 默认高数——"高数 = 必修课"——"默认最热课程"——"默认的合理性"——"高数的通用性"。
7.3 文档的"第一章第二章"
第一章/第二章 极限与连续/导数与微分——"高数讲义"——"章节顺序"——"学习进度"——"讲义资料"——"demo 的高数场景"。
7.4 真题的"48 页"
历年真题合集 48 页——"真题 = 备考核心"——"48 页 = 完整套题"——"5.6MB = 最大"——"真题的价值"。
7.5 手册的"6 页"
公式速查手册 6 页——"手册 = 便携速查"——"6 页 = 精简"——"0.9MB = 最小"——"手册的价值"。
7.6 下载按钮的"位置"
⬇️ 在右侧——"右对齐"——"拇指区"——"下载的易达"——"按钮位置"。
7.7 文档信息的"· 分隔"
"2.1MB · 12 页"——"· 中点"——"两信息分隔"——"紧凑"——"可读性"。
7.8 分栏的"间距"
文档区左 12 右 16——"与课程栏衔接"——"分栏的间距"——"内容的留白"——"视觉平衡"。
7.9 课程栏的"高度 100%"
height('100%')——"满高导航栏"——"占满左侧"——"导航的完整"——"垂直空间"。
八、总结与展望
App 34 资料页的核心价值:用草绿 + 左右分栏 + 课程导航,构建一个"3 秒选课程 + 5 秒下文档"的分类资料页——这是文档/资料类 App 的标准范式。
与系列对比:
| App | 列表/分类类页面 | 决策 |
|---|---|---|
| 31 | 菜单 | 喝什么 |
| 32 | 伞点列表 | 去哪借伞 |
| 33 | 车辆网格 | 骑什么车 |
| 34 | 资料库 | 看什么资料 |
"34 资料页的决策是'看什么课程的资料'"——"资料页 = 分类浏览"——"每个分类页面都在帮用户组织内容"——"34 帮用户按课程找资料"。
终评:草绿 + 课程栏 + 文档列表 = 完整分栏资料页——"从配色到分栏架构的完整设计"——"资料页的标杆"。
补充说明:本篇所有代码引用均基于 34-print-share/entry/src/main/ets/pages/Func1Tab.ets 实际源码,行号与源码一一对应;4 张实机截图分别覆盖资料首屏、大学英语课程切换、文档下载、数据结构课程切换四种差异场景,全部含模拟器轮廓,图床域名统一为 imgbed.devzoo.top。左右分栏布局是系列首个"侧边导航 + 内容区"结构,其三重选中态(绿字 + 加粗 + 白底)设计可复用于任何分类浏览型页面,且课程切换无需跳页的交互模式显著提升了分类浏览效率。
补充说明:资料页是 App 34 的"分类浏览中枢",与首页(展示)、上传(生产)、我的(管理)构成资料共享的完整业务链。课程栏 5 课程与首页 4 资料呼应(高数/英语/数据结构/线代均在),文档页数与首页价格 Banner(0.1 元/页)形成打印成本关联,体现了 demo 数据的一致性设计。真实产品中课程选中即可用 docs.filter(d => d.course === course) 联动过滤文档,分栏架构为这一扩展预留了清晰接口。

更多推荐





所有评论(0)