鸿蒙原生应用实战:资料页的左右分栏布局实现

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 块结构

  1. Header — 白色背景 + "资料库"标题
  2. CourseSide — 左侧课程导航栏(96 宽)
  3. DocArea — 右侧文档列表

Row() { this.CourseSide(); this.DocArea() } 左右分栏——"Row 水平分栏"——"左导航 + 右内容"——"经典分栏布局"——"系列首个左右分栏页"——"从上下滚动到左右分栏"——"布局的进化"

与 App 34 首页对比:首页是"上下滚动"四区布局、资料页是"左右分栏"布局——"34 内部两种布局"——"首页展示、资料浏览"——"两种布局的业务适配"——"资料分类用分栏"

与系列其他 App 对比

  • App 32 地图:上下滚动
  • App 33 首页:网格
  • App 34 资料:左右分栏(系列首次)

"左右分栏的优势"——"课程切换不跳页"——"导航 + 内容同屏"——"分类浏览效率高"——"桌面/平板常用布局"——"手机上的分栏"——"分栏的适配"

主题色 #27AE60 草绿——同首页——"品牌色贯穿全 App"

校园打印资料共享资料首屏 · 草绿Header(资料库)+左侧课程栏(高等数学选中白底草绿字/大学英语/数据结构/线性代数/大学物理 96宽浅绿底)+右侧文档列表(📄第一章极限与连续 2.1MB 12页/第二章导数与微分 1.8MB 10页/历年真题合集 5.6MB 48页/公式速查手册 0.9MB 6页 各带⬇️下载)

项目源码开源: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) 底部对齐——"避开状态栏"——"标准适配"

与首页 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"——"分类 = 资料组织"

文档下载交互 · 点击第一条文档"第一章 极限与连续"右侧的 ⬇️ 下载按钮后屏幕底部弹出"下载: 第一章 极限与连续"Toast

四、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.1MB12 页
📄第二章 导数与微分1.8MB10 页
📄历年真题合集5.6MB48 页
📄公式速查手册0.9MB6 页

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 个设计哲学

  1. 分类优先——课程栏主导航
  2. 内容优先——文档列表主内容
  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 个设计亮点

  1. 左右分栏布局——系列首个"左导航 + 右内容"分栏页
  2. 三重选中态——绿字 + 加粗 + 白底冗余强化
  3. 下载按钮——⬇️ 一键下载 + 页数打印成本关联

主题色设计逻辑:草绿 = 学习/打印/环保——"资料页用草绿,与首页品牌色一致"——"品牌贯穿"

与系列呼应:固定 Header(系列)、ForEach 列表(系列)、@State 单选(31 菜单/33 骑行)、emoji 图标(系列)、下载按钮(26 上传)——"34 资料把系列的状态 + 列表 + 下载手法组合出'资料库'场景"

体验细节:课程切换、三重选中、下载反馈、页数信息——"资料页的核心 = 让用户'3 秒选课程 + 5 秒下文档'"

可扩展性展望:课程过滤联动、真实下载、文档预览、打印跳转、搜索、收藏——"demo 的资料页骨架完整"

六、扩展思考:资料页的分栏架构与设计哲学

6.1 资料页的"浏览路径"

完整浏览路径

看 Header(资料库)→ 选课程(左侧导航)→ 看文档(右侧列表)→ 点下载 → 打印

"分栏的浏览路径"——"导航 + 内容同屏"——"课程切换不跳页"——"效率最大化"——"资料浏览的标准范式"

6.2 资料页的"信息架构"

3 层信息

  1. L1 标题(Header)——"资料库"
  2. L2 分类(CourseSide)——"什么课程"
  3. L3 内容(DocArea)——"什么文档"

"3 层渐进式"——"从标题到分类到内容"——"分栏的信息金字塔"——"用户按需深入"

6.3 资料页的"业务建模"

Doc 模型 5 字段(id/emoji/title/size/pages)——"5 字段建模"——"文档的核心字段"——"最小可用集"——加作者(author)、加时间(time)、加下载量(downloads)即可扩展——"数据模型的扩展点"

6.4 资料页的"对比与统一"

统一:4 文档同结构(emoji/标题/大小/下载)——"列表项的统一"对比:4 文档数据不同(标题/大小/页数)——"差异在数据"——"结构同构 + 数据异构"

6.5 资料页的"设计哲学"

资料页的 3 个设计哲学

  1. 分类优先——课程栏左侧主导航
  2. 内容优先——文档列表右侧主内容
  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) 联动过滤文档,分栏架构为这一扩展预留了清晰接口。

Logo

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

更多推荐