鸿蒙原生应用实战:借还页的双胶囊与扫码卡文字联动

App 32「校园共享雨伞」借还(Func2Tab),主题色 #4A90D9 晴空蓝。借还页采用"Header + 模式切换 + 扫码卡 + 记录列表"四区布局——白色 Header("借还伞"标题) + ModeRow 借伞/还伞双胶囊(@State mode: number,单选切换,选中蓝色实底白字) + ScanCard 虚线边框扫码卡(蓝色虚线 + 📷 56 号相机 emoji + "扫码借伞/还伞"动态文字 + "对准伞桩二维码扫描"提示) + SectionTitle + 3 条借用记录(借伞·今天 08:30 教学楼 A 楼 使用中(橙) / 还伞·昨天 18:00 图书馆 已归还(绿) / 借伞·8月10日 体育馆 已归还(绿))。本篇基于 32-campus-umbrella/entry/src/main/ets/pages/Func2Tab.ets(约 107 行)逐段拆解,附 4 张实机截图。

一、整体结构:四区"Header + 模式 + 扫码 + 记录"布局

App 32 借还页是"标题 + 模式切换 + 扫码 + 历史记录"的工具型页面——5 个 @Builder 块:

build() {
  Column() {
    this.Header()
    Scroll() {
      Column({ space: 16 }) {
        this.ModeRow()
        this.ScanCard()
        this.SectionTitle('借用记录')
        this.RecordList()
      }
      .width('100%')
      .padding({ left: D.pad, right: D.pad, top: 16, bottom: D.pad + this.safeBottom + 20 })
    }
    .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top)
  }
  .width('100%').height('100%').backgroundColor(C.bg)
}

4 块结构

  1. Header — 白色背景 + "借还伞"标题
  2. ModeRow — 借伞/还伞双胶囊
  3. ScanCard — 虚线扫码卡
  4. SectionTitle('借用记录') + RecordList — 3 条记录

与 App 32 首页/地图对比

  • 首页:Header + 天气 + 4 伞点(库存决策)
  • 地图:Header + 地图 + 图例 + 5 伞点(位置决策)
  • 借还:Header + 模式 + 扫码 + 3 记录(操作执行)

"借还页 = 操作执行"——首页和地图都是"决策"页、借还是"执行"页——"决策 → 执行的转化"——用户决定借伞后到借还页扫码执行——"3 页的转化路径"——"决策 → 位置 → 执行"

Column({ space: 16 }) 16 间距——比首页/地图 14 大——"借还页的更宽间距"——借还页内容少(4 块),用更大间距让页面更舒展——"间距 = 内容密度"

与系列其他扫码/操作类 App 对比

  • App 26: 文字编辑器
  • App 30: 公益宠物
  • App 32 借还:扫码借还 + 记录

"32 借还页的工具型"——"扫码 = 物理动作"——借还伞要扫伞桩的二维码——"扫码的物理映射"——"工具型 App 的扫码"

主题色 #4A90D9 晴空蓝——同首页/地图——"品牌色贯穿全 App"

校园共享雨伞借还首屏 · 晴空蓝Header(借还伞)+双胶囊(借伞选中蓝底白字/还伞白底灰字)+虚线扫码卡(蓝色虚线边框+📷相机emoji+"扫码借伞"+"对准伞桩二维码扫描")+借用记录(借伞·今天08:30 教学楼A楼 使用中橙/还伞·昨天18:00 图书馆 已归还绿/借伞·8月10日 体育馆 已归还绿)

项目源码开源: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"

"借还伞" 的命名——"借+还+伞 = 3 字命名"——"借还伞 = 业务名"——比"借伞"更完整(不只是借,还能还)——"业务的完整性"——"动词+名词的命名"

与首页/地图/我的 Header 对比

  • 首页:Column 包 Text(22 号"共享雨伞")
  • 地图:Row 包 Text(20 号"伞点地图")
  • 借还:Row 包 Text(20 号"借还伞")
  • 我的:无 Header(用 UserCard 代替)

"20 号 = 内容头"——地图/借还都是 20 号——"内容页用 20"、首页 22 是"品牌头"——"Header 字号 = 页面性质"

三、ModeRow:借伞/还伞双胶囊(本页核心)

ModeRow 是 借伞/还伞双胶囊,用 @State mode: number 控制选中:

@Builder
ModeRow() {
  Row({ space: 10 }) {
    ForEach(this.modes, (m: string, idx: number) => {
      Text(m).fontSize(14)
        .fontColor(this.mode === idx ? '#FFFFFF' : C.textSub)
        .padding({ left: 20, right: 20, top: 8, bottom: 8 })
        .backgroundColor(this.mode === idx ? C.primary : C.card).borderRadius(18)
        .onClick(() => { this.mode = idx; })
    }, (m: string) => m)
  }.width('100%')
}

ModeRow 结构Row 容器(10 间距)+ 2 个 Text 胶囊(ForEach 渲染)——"双胶囊的并列布局"

this.modes: string[] = ['借伞', '还伞'] 双模式数据——"2 个业务模式"——"借伞 + 还伞"——"借还的双向业务"——"模式的两个方向"

@State mode: number = 0 状态管理——"当前模式(0=借伞/1=还伞)"——"@State 的本地状态"——"模式切换的状态"——"ArkUI 的状态管理"

fontColor(this.mode === idx ? '#FFFFFF' : C.textSub) 文字颜色——选中白字、未选灰字——"选中态的文字"——"颜色对比的强调"

backgroundColor(this.mode === idx ? C.primary : C.card) 背景色——选中蓝实底、未选白底——"选中态的背景"——"蓝白对比的强提示"——"主题色 = 选中"

padding({ left: 20, right: 20, top: 8, bottom: 8 }) 20 横向 + 8 纵向 padding——"胶囊的舒适内边距"——"20 = 较宽的横向"——"8 = 紧凑的纵向"——"胶囊的横向比例"

borderRadius(18) 18 圆角——"胶囊的圆角"——18 接近半圆(胶囊高度 14+8+8=30,半径 15)——"18 = 胶囊的圆角"——"圆角 = 胶囊的视觉"

onClick(() => { this.mode = idx; }) 点击切换——点击切换 mode 值——"点击改变状态"——"声明式 UI 的状态驱动"——"状态 = 选中"

ForEach(this.modes, (m: string, idx: number) => {...}, (m: string) => m)——"双胶囊的 ForEach 渲染"——"2 个数据 = 2 个胶囊"——key 用 m.toString() 稳定——"数据驱动的胶囊"

与 App 31 菜单页的双单选对比

  • App 31 菜单:杯型/甜度(4 选项 / 2 选项 = 双单选)
  • App 32 借还:借伞/还伞(2 选项 = 单选)

"双单选 vs 单双选"——App 31 是 2 个维度各 2 选项 = 双单选、App 32 是 1 个维度 2 选项 = 单双选——"单选 vs 多选"——单选只有一个状态(mode=0 或 1)、多选有多个状态组合(杯型+甜度)——"状态的复杂度"

this.mode === idx ? ... : ... 三目运算——"条件渲染的简洁"——"三目 vs if/else"——ArkUI 中三目常用——"ArkUI 的条件渲染"

借伞模式截图

@State mode: number = 0;

private modes: string[] = ['借伞', '还伞'];

"借伞默认"——mode = 0 默认借伞——"借伞 = 主操作"——"为什么默认借伞?"——共享雨伞主要场景是借(还伞较少)——"业务的主次"——"借伞 = 高频操作"

四、ScanCard:虚线扫码卡(文字随 mode 联动)

ScanCard 是 蓝色虚线边框 + 📷 + 动态文字的扫码卡:

@Builder
ScanCard() {
  Column({ space: 10 }) {
    Stack({ alignContent: Alignment.Center }) {
      Column().width(180).height(180).backgroundColor(C.primarySoft).borderRadius(D.rLg)
      Column({ space: 8 }) {
        Text('📷').fontSize(56)
        Text('扫码' + (this.mode === 0 ? '借伞' : '还伞')).fontSize(16).fontWeight(FontWeight.Bold).fontColor(C.primary)
        Text('对准伞桩二维码扫描').fontSize(12).fontColor(C.textDim)
      }
    }
    .width('100%').onClick(() => { promptAction.showToast({ message: this.mode === 0 ? '借伞' : '还伞' }); })
  }
  .width('100%').padding({ top: 20, bottom: 20 }).backgroundColor(C.card).borderRadius(D.rLg)
  .border({ width: 1, color: C.primary, style: BorderStyle.Dashed })
}

ScanCard 结构(外层 + 内层):

外层(Column)

  • 背景 C.card 白色
  • 圆角 D.rLg 20
  • 虚线边框 border({ width: 1, color: C.primary, style: BorderStyle.Dashed })——蓝色虚线 1px
  • 20 padding 上下

内层(Stack 居中)

  • 背景 180×180 浅蓝圆角(C.primarySoft
  • 居中 3 行(56 📷 + 16 "扫码借伞/还伞" + 12 "对准伞桩二维码扫描")

BorderStyle.Dashed 虚线边框——"虚线 = 占位/扫描"——"为什么用虚线?"——虚线暗示"这里是扫描区"——"虚线的视觉语义"——"扫码区的视觉"——"虚线 ≠ 实线"——实线是已确定区域、虚线是待扫描区域——"虚线的未完成感"

color: C.primary 蓝色虚线——"主题色虚线"——"主题色强化"——蓝色虚线既显主题又显扫码区——"颜色的双重作用"

Text('扫码' + (this.mode === 0 ? '借伞' : '还伞')) 动态文字——"随 mode 切换文字"——"动态文案 = 模式映射"——"文字的模式联动"——mode=0 → "扫码借伞"、mode=1 → "扫码还伞"——"状态驱动文案"——"文案的状态化"

Stack({ alignContent: Alignment.Center }) Stack 居中——"内层居中"——背景卡 + 居中图标文字——"扫码卡的视觉中心"——"180×180 中心"

Text('📷').fontSize(56) 56 号相机 emoji——"相机 = 扫码"——"大 emoji 作为图标"——"56 号是大图标"——"扫码图标的视觉"

Text('扫码借伞').fontSize(16).fontWeight(FontWeight.Bold).fontColor(C.primary) 蓝色加粗 16 号——"主标题"——"主题色加粗"——"扫码的视觉"——"主题色 = 强调"

Text('对准伞桩二维码扫描').fontSize(12).fontColor(C.textDim) 12 号灰——"副标题"——"提示 = 灰色"——"操作指引"——告诉用户对准哪里——"操作指引的次要感"

onClick(() => promptAction.showToast({ message: this.mode === 0 ? '借伞' : '还伞' })) 点击反馈——整卡点击弹"借伞/还伞"Toast——"占位扫码"——真实产品调起相机扫码——"Toast 的占位"——"Toast 文字也随 mode 联动"

backgroundColor(C.card).borderRadius(D.rLg) 白色 20 圆角外层——"扫码卡的外层"——"20 圆角 = 大卡"

backgroundColor(C.primarySoft).borderRadius(D.rLg) 浅蓝 20 圆角内层——"扫码区的内层"——"180×180 浅蓝"——"扫码区的视觉中心"

与系列其他扫码占位对比

  • App 27 通知:日期选择
  • App 32 借还:扫码占位 + 模式联动

"扫码占位的极简"——"180×180 浅蓝 + 📷"——"占位的演示"——"真实相机调起的占位"——"扫码卡 = 占位"

"为什么用虚线边框?"——"虚线暗示动态区域"——"扫码区 = 动态"——"虚线 = 待扫描"——"扫码区的视觉表达"——"占位 vs 实线"

"动态文案" 的设计——"为什么文案要随 mode 变?"——"扫码的语义 = mode 决定"——借伞扫码 = 借、还伞扫码 = 还——"扫码的方向性"——"动态 = 准确"——"避免歧义"

"对准伞桩二维码扫描" 的提示——"操作指引"——"12 号灰的次要"——告诉用户扫哪里——"伞桩 = 借还设备的物理位置"——"实体设备的指代"

借伞模式扫码交互 · 重新点击"借伞"胶囊切换回借伞模式后,再点击扫码卡弹出"借伞"Toast(mode=0 借伞),演示扫码卡文字与 Toast 文字都随 mode 联动的完整状态机

五、SectionTitle:借用记录

@Builder
SectionTitle(title: string) {
  Row() { Text(title).fontSize(16).fontWeight(FontWeight.Bold).fontColor(C.text) }.width('100%')
}

极简 SectionTitle——16 号加粗黑色"借用记录"——"同首页/地图 SectionTitle"——"系列 SectionTitle 的复用"——@Builder 抽离可复用——"组件化设计"

"借用记录" 的命名——"借用 = 借出"——"借 vs 借用"——"借是动词、借用是名词性"——"借伞 = 借 + 伞、借用记录 = 借出去 + 记录"——"命名的细节"

六、RecordList:3 条记录(带状态色)

RecordList 是 3 条借用记录——每项含 emoji 头像、动作+时间、地点、状态

@Builder
RecordList() {
  Column({ space: 12 }) {
    ForEach(this.records, (r: Record) => {
      Row({ space: 12 }) {
        Text(r.emoji).fontSize(24)
        Column({ space: 3 }) {
          Text(r.action + ' · ' + r.time).fontSize(14).fontColor(C.text)
          Text(r.point).fontSize(12).fontColor(C.textDim)
        }.alignItems(HorizontalAlign.Start).layoutWeight(1)
        Text(r.status).fontSize(12).fontColor(r.statusColor)
      }
      .width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
    }, (r: Record) => r.id.toString())
  }.width('100%')
}

每张记录卡的结构

  • 左 emoji 头像(24 号 ☂️)
  • 中 文字区("动作 · 时间" 14 号 + "地点" 12 号灰)
  • 右 状态文字(12 号带颜色)

3 条记录(每条 5 要素):

动作时间地点状态状态色
借伞今天 08:30教学楼 A 楼使用中橙(warn)
还伞昨天 18:00图书馆已归还绿(ok)
借伞8月10日体育馆已归还绿(ok)

"使用中" 与 "已归还" 的状态色——"两态 = 颜色"——橙色"使用中"= 进行中、绿色"已归还"= 完成——"状态的颜色编码"——"颜色 = 业务状态"

r.statusColor: string 状态颜色字段——"颜色作为数据"——同 PointList 的 typeColor——"颜色内联在数据"——"数据驱动的颜色"——"状态的颜色编码"

Text(r.action + ' · ' + r.time) 动作+时间——"中点连接"——"·" 分隔符——"动作 + 时间的并排"——"信息的紧凑"**——14 号黑色。

Text(r.point).fontColor(C.textDim) 12 号灰地点——"次要信息"——"地点作为参考"——"12 灰的次要"

Column({space: 3}) 文字区内部 3 间距——"紧凑文字区"——"动作 + 地点的紧凑"——"3 = 极小间距"——"信息的密集"

padding(14).borderRadius(D.rMd) 14 padding + 14 圆角——"记录卡的小圆角"——比 ScanCard 的 20 小——"记录卡用 14 圆角"——"圆角层级:20 渐变/14 普通/10 小"

border({ width: 1, color: C.stroke }) 1px 边框——"卡片的细边框"——同系列其他卡。

3 条记录的"时间分布"

  • 今天 08:30(最新)
  • 昨天 18:00(昨天)
  • 8月10日(多天前)

"时间的递减"——"时间从新到旧"——"3 条记录的时间线"——"使用中在最上"——"状态优先级 = 时间"——"使用中 = 当前 + 优先"

"使用中" 的特殊位置——"使用中 = 还在借"——"使用中 = 需要关注"——"为什么使用中在最上?"——用户在首页就能看到"还有伞没还"——"状态优先 = 业务提醒"——"使用中 = 提醒用户归还"

与首页 PointList 4 伞点对比——"记录 vs 伞点"——"伞点 = 静态位置、记录 = 动态行为"——"4 vs 3 项"——"首页伞点多、记录少(只显示最近 3)"——"信息密度的差异"

Record 模型(7 字段):

interface Record {
  id: number;
  emoji: string;
  action: string;
  time: string;
  point: string;
  status: string;
  statusColor: string;
}

字段说明

  • id/emoji — 标识与图标
  • action — 动作(借伞/还伞)
  • time — 时间(今天 08:30)
  • point — 地点
  • status — 状态文字
  • statusColor — 状态颜色

7 字段 vs 6 字段(首页 UmbrellaPoint/地图 Point)——"7 字段的扩展"——Record 多 1 个 action 字段——"借还 = 动作"——"动作 = 业务方向"——"动作字段的必要性"

statusColor: string 颜色内联——同 PointList 的 typeColor——"数据 + 颜色"——"耦合 vs 解耦"——demo 简化、真实产品用枚举。

time: string 字符串时间——"时间作为字符串"——"今天 08:30" / "昨天 18:00" / "8月10日"——"相对时间表达"——"相对时间 = 用户友好"——绝对时间戳对用户不友好——"时间的人性化"

"使用中" 状态色 C.warn——#FF9F1C——"橙色 = 警告/进行中"——"橙色的语义"——"为什么使用中用橙?"——进行中 = 等待中 = 提醒——"橙色的提醒"

"已归还" 状态色 C.ok 绿——#2BB673——"绿色 = 完成/成功"——"绿色的语义"——"已归还 = 安心"——"绿色的安心"——同首页的"可借"绿色——"OK 色的复用"

还伞模式切换 · 点击"还伞"胶囊后胶囊切换为蓝色实底白字、"借伞"切换为白底灰字、扫码卡中央文字从"扫码借伞"动态切换为"扫码还伞"

七、借还页的交互细节与可用性分析

7.1 模式切换的"双向业务"

借伞 ↔ 还伞——"双向业务"——"借 = 拿走、还 = 归还"——"两个方向"——"为什么用双向?"——共享雨伞借了要还能形成闭环——"闭环业务"——"借 + 还 = 完整链路"

7.2 双胶囊的"互斥性"

借伞/还伞互斥——"选了借伞就不能选还伞"——@State mode: number 单值——"单值的互斥"——"互斥的视觉"——蓝 vs 白——"对比强烈的互斥"

7.3 扫码卡的"虚线视觉"

虚线 = 扫描区——"虚线 = 待扫"——"虚线的暗示"——"为什么用虚线?"——"扫描的视觉"——"虚线 = 动态"——"扫码区的设计"

7.4 动态文案的"状态联动"

"扫码借伞" / "扫码还伞"——"文案 = 状态"——"文案的状态化"——"避免歧义"——"明确告诉用户扫什么"——"文案的精准"

7.5 3 条记录的"状态"

使用中 ×1 + 已归还 ×2——"3 条 = 1+2"——"使用中 = 提醒"——"已归还 = 历史"——"状态分布合理"——"业务状态的多样"

7.6 整卡可点 vs 按钮可点

扫码卡整卡可点——"整卡的易用性"——"用户点哪都响应"——"占位跳转"——"Toast 反馈"——"操作成本低"

7.7 借伞 vs 还伞的"颜色一致性"

借伞蓝/还伞蓝——"两个模式用同色"——"颜色不区分模式"——"模式的区分用文字"——"借伞/还伞文字区分"——"颜色的统一"——"模式的视觉"

7.8 记录状态的"用户引导"

使用中(橙)= 提醒归还——"状态 = 行动"——"使用中 = 还伞提醒"——"用户看到使用中会想还"——"状态的引导价值"

7.9 扫码卡的"180×180"

180×180 浅蓝——"扫码区的尺寸"——"180 = 接近正方形"——"扫码区 = 视口"——"视口的视觉"——"扫描区的大小"

7.10 借还页的"工具型"

扫码 + 记录——"工具型页面"——"操作 + 历史"——"工具的两要素"——"操作 = 扫码、历史 = 记录"——"工具页的完整性"

7.11 3 条记录的"时间递减"

今天 → 昨天 → 8月10日——"时间从新到旧"——"时间排序"——"用户友好"——"最近的在最上"——"时间排序的常识"

7.12 借还模式的"默认选择"

借伞默认——"为什么默认借伞?"——借伞是主操作(用户多)——"主操作 = 默认"——"默认的合理性"——"借伞 = 高频"

7.13 状态色的"双重语义"

橙色"使用中" = 提醒 + 进行中——"橙色的双重"——"绿色"已归还" = 完成 + 安心"——"绿色的双重"——"颜色的多义"——"颜色的业务"

7.14 借还页的"色彩心理学"

晴空蓝——"蓝色 = 工具"——"工具型 App 的蓝色"——"蓝色的冷静"——"借还是冷静操作"——"蓝色的可信赖"——"工具配色的心理"

7.15 虚线边框的"系列统一"

虚线 = 占位/动态——"虚线的视觉"——"系列虚线复用"——同 App 27 通知的虚线占位——"虚线的语义"——"虚线 = 未完成"

7.16 借还模式的"快捷性"

双胶囊快速切换——"切换 = 一键"——"点击胶囊 = 改模式"——"操作成本低"——"模式的便捷"——"单值状态的便利"

7.17 3 条记录的"业务建模"

Record 7 字段——"业务建模的完整"——"动作/时间/地点/状态"——"共享雨伞的完整记录"——"数据的丰富"——"7 字段的必要性"

7.18 借还页的"完整性"

模式 + 扫码 + 记录——"三要素的完整"——"操作 + 物理 + 历史"——"借还的闭环"——"工具页的完整"——"借还页的设计"

7.19 借还 vs 扫码的"层次"

借还 = 业务层、扫码 = 物理层——"两层的设计"——"业务 = 模式、物理 = 扫码"——"业务层 = 高层、物理层 = 底层"——"两层的协同"

7.20 借还页的"易用性"

3 步完成借伞——"1. 选模式 2. 扫码 3. 完成"——"3 步的极简"——"操作路径短"——"易用性高"——"工具页的简洁"

7.21 3 条记录 vs 4 伞点

3 记录 vs 4 伞点——"数量差异"——"记录少(最近)、伞点多(全部)"——"信息密度的对比"——"demo 的合理"

7.22 借还页的"色彩一致性"

全页 #4A90D9 蓝——"主题色统一"——"首页/地图/借还/我的 = 同一蓝色"——"品牌一致"——"蓝色的贯穿"——"品牌的稳定性"

7.24 借还页的"操作反馈"

Toast 反馈——"借伞/还伞 Toast"——"反馈的精准"——"占位 = 反馈"——"操作 = 反馈"——"反馈链的完整"

7.25 借还页的"数据驱动"

mode 状态驱动文案——"数据驱动 UI"——"state → view"——"声明式 UI 的价值"——"改状态 = 改文案"——"状态化的优势"

7.26 借还页的"扩展性"

mode 改值 = 文案改——"扩展的便利"——"加模式 = 加数据"——"加借伞/还伞外的业务 = 加数组项"——"扩展点清晰"

7.27 借还页的"对比与统一"

统一:3 记录同结构、统一边框、状态色编码——"列表项的统一"对比:3 记录不同动作/时间/状态——"列表项的差异"

7.28 借还页的"色彩记忆"

3 状态色:橙(使用中)/绿(已归还)+ 蓝(扫码)——"3 色的记忆"——"色彩 = 状态"——"用户记住颜色"——"色彩的用户认知"

7.29 借还页的"系列呼应"

双胶囊(31 杯型/甜度)、虚线边框(27 通知)、状态色(系列)——"32 借还的系列手法"——"复用 = 一致"——"系列统一"

7.30 借还页的"终评"

双胶囊 + 虚线扫码 + 3 记录 = 完整借还页——"借还页的完成度"——"可上线级"——"系列工具型页面的标杆"

八、总结:晴空蓝 + 双模式 + 虚线扫码

App 32 借还页一句话用晴空蓝(#4A90D9)组织一个"模式 + 扫码 + 记录"的工具借还页——借伞/还伞双胶囊切换 mode 状态,蓝色虚线扫码卡用 📷 + 动态文字"扫码借伞/还伞"占位真实扫码,3 条记录用状态色(橙使用中/绿已归还)展示历史。

3 个设计亮点

  1. 借还双胶囊——@State mode 单值互斥,主题色 = 选中
  2. 虚线扫码卡——BorderStyle.Dashed 蓝色虚线暗示动态扫描区
  3. 动态文案联动——mode 决定"扫码借伞/还伞"文字

主题色设计逻辑:晴空蓝 = 工具型 App 的冷静色——"借还 = 物理操作,需要冷静的可信赖感"——与首页/地图同色——"品牌色贯穿"

与系列呼应:双单选(31 杯型/甜度)、虚线占位(27 通知)、状态色(系列)、ForEach 列表(系列)、@State 状态(系列)——"32 借还把系列的手法组合出'借还'场景"

体验细节:双胶囊快速切换、虚线扫码占位、动态文案、3 条记录状态色——"借还页的核心 = 让用户'3 秒选模式 + 5 秒扫码'"

可扩展性展望:相机扫码集成、押金支付、信用积分扣减、还伞校验、消息推送——"demo 的借还页骨架完整"

还伞扫码交互 · 点击虚线扫码卡任意位置后屏幕底部弹出"还伞"Toast(当前 mode=1 还伞模式),演示虚线扫码卡的整卡可点 + 动态 Toast 文字联动

八、扩展思考:借还页的转化路径与设计哲学

8.1 借还页的"操作流程"

完整借伞 3 步

  1. 选模式(借伞/还伞)——1 步决策
  2. 扫码(虚线卡 + 📷)——1 步物理操作
  3. 完成(Toast 反馈)——1 步反馈

"3 步的极简流程"——"操作路径短"——"易用性高"——"3 步完成借伞"——"工具页的简洁"——"demo 的可用性"

8.2 借还页的"信息架构"

4 层信息

  1. L1 标题(Header)——"借还页"
  2. L2 模式(ModeRow)——"做什么操作"
  3. L3 扫码(ScanCard)——"怎么操作"
  4. L4 历史(RecordList)——"做过什么"

"4 层渐进式"——"从意识到执行"——"标题 → 模式 → 扫码 → 历史"——"操作的完整链路"

8.3 借还页的"双向业务"

借伞 + 还伞 = 双向——"借是拿走、还是归还"——"共享雨伞的闭环"——"借了不还不是闭环"——"借 + 还 = 完整业务"——"双向 = 业务完整性"

8.4 借还页的"模式切换的物理映射"

借伞 → 拿起伞、还伞 → 归还伞——"模式 = 物理动作"——"借还的实体动作"——"扫码 = 触发物理动作"——"模式 = 物理意图"——"线上模式 = 线下动作"

8.5 借还页的"虚线设计"

虚线 = 待扫描——"虚线的物理隐喻"——"扫码的'扫' = 虚线'待扫'"——"虚线的状态"——"实线 = 已确定、虚线 = 待定"——"扫码的视觉表达"

8.6 借还页的"动态文案"

"扫码借伞" / "扫码还伞"——"文案 = 状态"——"动态文案的状态化"——"避免歧义"——"明确告诉用户"——"文案的精准"——"状态驱动文案"

8.7 借还页的"设计哲学"

借还页的 3 个设计哲学

  1. 模式优先——借/还先选再执行
  2. 占位优先——虚线 + emoji 占位真实扫码
  3. 状态优先——使用中 = 橙色提醒

"模式 + 占位 + 状态的借还页"——"工具型借还页的设计原则"——"从哲学看设计"——"这套方法论可直接迁移到任何扫码/借还类 App"

8.9 借还页的"终评"

App 32 借还页综合评估——"四区结构 + 晴空蓝主题 + 完整模式 + 扫码 + 记录"——"借还页的完成度评级"——"一个可上线级的工具借还页"——"系列工具型页面的标杆"——"demo 的高完成度"

九、彩蛋:借还页的细节设计

9.1 双胶囊的"圆角选择"

borderRadius(18) 18 圆角——"为什么是 18?"——"胶囊高度 14+8+8=30,半圆角 15"——"18 接近 15 = 接近胶囊"——"胶囊的视觉"——"圆角的精准"

9.2 扫码卡 180×180 的尺寸

180×180 浅蓝——"为什么是 180?"——"180 = 1.5 × 120"——"扫码区足够大"——"视口的视觉"——"180 是扫码的合理尺寸"

9.3 借伞默认的"业务考量"

借伞默认——"业务的高频"——"借伞 = 用户多"——"还伞 = 用户少(同一用户多次借才还)"——"默认 = 主操作"——"业务的优先级"

9.4 "对准伞桩二维码扫描" 的指引

"对准伞桩"——"伞桩 = 借还设备"——"物理位置的指引"——"实体设备"——"用户知道扫哪里"——"物理映射"

9.5 3 条记录的时间表达

"今天 08:30" / "昨天 18:00" / "8月10日"——"相对时间"——"用户友好"——"不显示完整时间戳"——"时间的智能"——"相对时间 vs 绝对时间"

十、总结与展望

App 32 借还页的核心价值用晴空蓝 + 双模式 + 虚线扫码 + 3 记录,构建一个"3 步完成借还"的工具借还页——这是共享类 App 借还页的标准范式。

与系列对比

App操作/记录类页面决策
26编辑器写什么
27日历何时
28衣橱怎么穿
29餐厅吃什么
30公益帮什么
31菜单喝什么
32借还借/还什么

"32 借还页的决策是'借还是还'"——"借还页 = 操作执行"——"借还有动作方向"——"借 = 拿走、还 = 归还"——"32 帮用户完成借或还"

终评晴空蓝 + 双胶囊 + 虚线扫码 + 3 记录 = 完整工具借还页——"从配色到信息架构的完整设计"——"借还页的标杆"

Logo

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

更多推荐