ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

鸿蒙原生应用实战:用 ArkUI 搭投票首页 —— Header 内嵌三 Tab 设计

鸿蒙原生应用实战:用 ArkUI 搭投票首页 —— Header 内嵌三 Tab 设计 鸿蒙原生应用实战用 ArkUI 搭投票首页 —— Header 内嵌三 Tab 设计App 22「校园投票管理」首页HomeTab主题色#7C3AED紫色4 个 Tab 分别为首页️、投票✅、结果、我的。首页采用**Header 内嵌 3 Tab独特设计**——固定 Header标题校园投票 内嵌进行中/即将结束/热门 3 个下划线 Tab 4 张投票卡56×56 emoji 标题 总票数 状态色 剩余时间 紫色参与投票按钮。本篇基于22-campus-vote/entry/src/main/ets/pages/HomeTab.ets约 113 行逐段拆解附 4 张实机截图。一、整体结构Header 双层 投票列表App 22 首页是Header Scroll 投票列表——但 Header 是双层结构标题层 Tab 层投票列表只有 1 个 Builderbuild() { Column() { this.Header() Scroll() { Column({ space: 14 }) { this.VoteList() } .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) }2 块结构Header— 标题校园投票 3 Tab进行中/即将结束/热门VoteList— 4 张投票卡与系列其他首页对比App 21 问卷首页 3 块Header Chip List——Header 单独 1 行App 22 投票首页 2 块Header 2 行 List——Header 内嵌 TabHeader 内嵌 Tab是 App 22 的特色——首页需要按时间状态分类进行中/即将结束/热门时把 Tab 放在 Header 内比放在 List 上方更紧凑。项目源码开源https://gitee.com/codenestFlow/HarmonyOSHub二、Header双层结构标题 3 TabHeader 是标题层 Tab 层双层结构系列唯一Builder Header() { Column() { Row() { Text(校园投票) .fontSize(22).fontWeight(FontWeight.Bold).fontColor(C.text) } .width(100%).height(this.safeTop 52) .padding({ top: this.safeTop, left: D.pad, right: D.pad }) .alignItems(VerticalAlign.Bottom) Row() { ForEach(this.tabs, (t: string, idx: number) { Text(t) .fontSize(14) .fontColor(this.tab idx ? C.primary : C.textSub) .fontWeight(this.tab idx ? FontWeight.Bold : FontWeight.Normal) .layoutWeight(1).textAlign(TextAlign.Center).padding({ bottom: 12 }) .onClick(() { this.tab idx; }) }, (t: string) t) } .width(100%) } .width(100%).backgroundColor(C.card) }第 1 层标题校园投票 22sp 加粗深色height(this.safeTop 52)让出状态栏 52vp 标题alignItems(VerticalAlign.Bottom)内容靠底没用bottom边框与 Tab 层自然衔接第 2 层Tab3 个 Tab进行中/即将结束/热门等宽分布layoutWeight(1)3 个均分textAlign(TextAlign.Center)文字居中padding({ bottom: 12 })给 Tab 文字下留 12vp视觉缓冲没有下划线与 App 14/16/18 的24×2 下划线不同——只靠文字色 字重区分选中State tab: number 0默认选中进行中——onClick(() { this.tab idx; })切换——注意 demo 未联动过滤点击 Tab 只切换文字样式列表永远是全部 4 张——假筛选——真实项目应加filteredVotes()按status过滤。2.1 无下划线 Tab vs 有下划线 TabApp 14/16/18 的 Tab 是24×2 下划线指示器系列标准App 22 简化成无下划线——只靠文字色紫/灰 字重加粗/常规区分选中Text(t) .fontSize(14) .fontColor(this.tab idx ? C.primary : C.textSub) .fontWeight(this.tab idx ? FontWeight.Bold : FontWeight.Normal) .layoutWeight(1).textAlign(TextAlign.Center).padding({ bottom: 12 })无下划线的优势更简洁、更轻量——Header 不显笨重。无下划线的劣势用户不知道哪个是当前选中的——靠字重加粗不够明显轻度色弱用户难识别。轻量级 Tab 用无下划线、强调 Tab 坐下划线——本系列两种风格并存。三、VoteList4 张投票卡本页核心VoteList 是 4 张投票卡每张含 56×56 emoji 标题 总票数 状态色 剩余时间 紫色参与投票按钮Builder VoteList() { Column({ space: 12 }) { ForEach(this.votes, (v: Vote) { Column({ space: 10 }) { Row({ space: 12 }) { Row() { Text(v.emoji).fontSize(30) } .width(56).height(56) .backgroundColor(C.primarySoft).borderRadius(D.rMd) .justifyContent(FlexAlign.Center) Column({ space: 4 }) { Text(v.title).fontSize(15).fontWeight(FontWeight.Medium).fontColor(C.text) Text(v.total).fontSize(12).fontColor(C.textDim) } .alignItems(HorizontalAlign.Start).layoutWeight(1) Column({ space: 4 }) { Text(v.status).fontSize(11).fontColor(v.statusColor) Text(v.left).fontSize(11).fontColor(C.warn) } } .width(100%) Button(参与投票) .width(100%).height(38) .fontSize(13).fontColor(#FFFFFF).backgroundColor(C.primary) .borderRadius(D.rSm) .onClick(() { promptAction.showToast({ message: v.title }); }) } .width(100%) .padding(14) .backgroundColor(C.card).borderRadius(D.rLg) .border({ width: 1, color: C.stroke }) }, (v: Vote) v.id.toString()) } .width(100%) }3.1 4 张投票的数据private votes: Vote[] [ { id: 1, emoji: , title: 最佳校园歌手评选, total: 1,856 票, status: 进行中, statusColor: C.ok, left: 剩 3 天 }, { id: 2, emoji: , title: 校园logo设计方案投票, total: 920 票, status: 即将结束, statusColor: C.warn, left: 剩 6 小时 }, { id: 3, emoji: ⚽, title: 最受欢迎运动评选, total: 2,100 票, status: 进行中, statusColor: C.ok, left: 剩 5 天 }, { id: 4, emoji: , title: 食堂最佳菜品投票, total: 3,560 票, status: 热门, statusColor: C.danger, left: 剩 2 天 } ];4 张投票的3 状态 校园主题Emoji标题状态总票数剩余最佳校园歌手评选进行中绿1,856 票剩 3 天校园 logo 方案即将结束橙920 票剩 6 小时⚽最受欢迎运动进行中绿2,100 票剩 5 天食堂最佳菜品热门红3,560 票最高剩 2 天3 状态三色映射进行中→C.ok绿活跃/好状态即将结束→C.warn橙警示/快截止热门→C.danger红高热度/紧急剩 6 小时是即将结束——C.warn橙色警告用户快去投——**截止倒计时 警示色**的合理映射。3,560 票是热门食堂投票参与度最高——高票数 热门——食堂是校园最关心的话题民以食为天1 万学生投票参与形成热门。3.2 投票卡的三色信息每张投票卡含 3 种信息左侧 56×56 emoji 块C.primarySoft浅紫底 //⚽/ emoji中间 标题 总票数layoutWeight(1)占主要空间右侧 状态色 剩余时间两行紧凑状态色 剩余时间——两个紧迫感信号状态色告诉用户这个投票处于什么状态进行中/即将结束/热门剩余时间告诉用户还剩多久3 天/6 小时/2 天双信号让用户做出投票决策——还剩 6 小时 橙色 立刻行动。3.3 紫色参与投票按钮Button(参与投票)100% 宽 38vp 紫底白字按钮——整张卡唯一的行动入口点击跳到 Func1Tab 投票页。100% 宽让按钮贯穿整张卡——视觉上参与投票是这张卡唯一的目的不是查看详情那种次要操作。borderRadius(D.rSm)圆角 10按钮——比卡片圆角 20 略小——**按钮圆角 ≤ 卡片圆角**是设计原则按钮嵌在卡片内圆角不能比卡片大。四、假筛选与 3 Tab 的关系State tab: number 0控制 3 个 Tab 的视觉哪个选中但VoteList的ForEach(this.votes, ...)没有联动过滤——4 张卡永远全部展示。真实项目应实现按 status 过滤private filtered(): Vote[] { if (this.tab 0) return this.votes; // 全部 if (this.tab 1) return this.votes.filter(v v.status 进行中); if (this.tab 2) return this.votes.filter(v v.status 即将结束); return this.votes.filter(v v.status 热门); }tab一变 →filtered()重算 → ForEach 重渲染。这是本系列假筛选共有的简化App 13/17/20/22 都是。假筛选在 3 Tab 的设计里影响用户点即将结束看不到其他 Tab 的内容会以为现在只有 1 个即将结束的投票——误导用户——真实项目必须联动过滤。五、State 与主题色HomeTab 只有1 个 Statetab当前 Tab 0-2。其余数据private不可变。主题色#7C3AED紫色——投票/决策/调查类 App 的常见色SurveyMonkey 用紫色、Tally Form 用绿色、Typeform 用深色——紫色 智能/选择/民主决策的隐喻。紫色调性契合投票的庄严感。C.primarySoft: #F1EAFE浅紫——背景块/胶囊底色。C.accent: #A78BFA浅紫——渐变副色。六、Header 内嵌 Tab 的设计模式App 22 的Header 内嵌 Tab是双层 Header——标题层 Tab 层┌──────────────────────────┐ │ 校园投票 (标题) │ - 标题层 ├──────────────────────────┤ │ 进行中 即将结束 热门 │ - Tab 层 ├──────────────────────────┤ │ [投票卡 1] │ │ [投票卡 2] │ │ [投票卡 3] │ - List │ [投票卡 4] │ └──────────────────────────┘双层 Header适用场景主页有按状态/类型分类的需求进行中/即将结束/热门Tab 数量少2-3 个Tab 切换不联动复杂过滤双层 Header不适用场景Tab 数量多4——应单独 Header 独立 Tab 区Tab 切换联动复杂过滤——应让 List 区域更大Header 内嵌 Tab是 App 22 的设计选择——哪些场景用 Header 内嵌 Tab取决于Tab 与 List 的耦合度。七、剩余时间的双通道设计App 22 投票卡显示剩 3 天/剩 6 小时/剩 5 天/剩 2 天——剩余时间是投票场景的特有维度对比问卷的截止日期、商城的剩余库存。剩余时间的 3 种精度天剩 3 天—— 长期投票时间粒度天小时剩 6 小时—— 紧急投票时间粒度小时分钟剩 30 分钟—— 临截止投票时间粒度分钟App 22 演示了天/小时两种精度——真实项目应根据截止时间动态选择精度。剩余时间是倒计时的倒序显示——投票刚发布是剩 7 天、过半是剩 3 天、临截止是剩 6 小时——剩余 截止 - 当前——真实项目应后端实时计算避免静态数据不准。八、3 Tab 切屏的 4 张实机图本文 4 张图展示 3 个 Tab 的不同状态top默认 Tab进行中4 张投票全部展示mid点即将结束Tab高亮移到即将结束4 张卡同样展示因为是假筛选lower点热门Tab高亮移到热门bottom切回进行中高亮回到进行中虽然 4 张图内容相同投票卡不变但 Tab 高亮位置不同——假筛选的可视化证据——读者可对比看 4 张图的进行中/即将结束/热门字色变化。九、本页与系列其他首页的对比App首页定位Tab 位置主列表13/17 音乐/志愿内容流无 Tab3 项目14 运动行动型无 Tab5 场地15 环保知识型无 Tab4 指南16 商城交易型无 Tab5 商品18 社交人脉型无 Tab4 同好19 摄影创作型无 Tab4 作品20 阅读学习型无 Tab4 书21 问卷任务型Chip横滑5 问卷22 投票决策型Header 内嵌 Tab4 投票投票 决策型——用户来做决定选最喜欢的歌手/菜品/运动——Header 内嵌 Tab 让按时间状态分类更醒目。任务型 Chip横滑、决策型 Header 内嵌 Tab——两种分类的不同 UI 形态。十、3 状态投票卡的优先级设计App 22 投票卡的 3 种状态进行中/即将结束/热门按用户行动优先级排序优先级从高到低即将结束剩 6 小时橙色警示——立刻投——最高优先级热门高票数红色突出——凑热闹——次高优先级进行中剩 3-5 天绿色——慢慢投——低优先级优先级 视觉强度即将结束剩 6 小时→C.warn橙——警示色 优先热门3,560 票→C.danger红——突出色 流量进行中剩 3-5 天→C.ok绿——平静色 常规颜色编码对应行动优先级——用户看到橙色会想快去投、看到绿色会想不急、看到红色会想很多人在投——颜色 行动指南。剩 6 小时特别短——这是合理的紧迫感设计让用户感觉错过就没了——虚假紧迫感是投票平台提高参与度的常用心理学淘宝剩 1 小时、滴滴3 分钟内有司机。真实项目的真实紧迫感从服务端实时计算截止 - 当前倒计时——剩 X 小时 Y 分动态显示——比静态剩 6 小时更可信。十一、Header 内嵌 Tab 与分类 Tab的对比App 22 的Header 内嵌 Tab与系列其他 Tab 类型对比类型示例位置视觉适用Header 内嵌 TabApp 22 首页Header 内部文字色字重分类少 强调分类列表上方下划线 TabApp 13/14/16/18/20 记录列表上方24×2 紫条分类 2-3 个横滑 ChipApp 14/15/16/19/21 主页列表上方胶囊横滑分类 4-6 个列表上方胶囊App 18 消息列表上方圆角胶囊分类 4 个底部 Tab BarApp 11-22 主导航屏幕底部4 个 Tab4 个一级页面5 种 Tab 类型覆盖所有分类需求——Tab 类型跟随分类数量和强调程度——读者做自己产品时先数分类数量2-3/4-6/7再选 Tab 类型下划线/横滑/树形。Header 内嵌 Tab的优势节省屏幕空间不占独立行视觉强调Header 高度 分类区与标题形成主标题 子分类层次Header 内嵌 Tab的劣势Tab 与 List 之间无视觉缓冲Tab 切换不联动过滤时List 不会变用户困惑App 22 的假筛选恰好命中劣势——读者可引以为戒内嵌 Tab 必须配过滤逻辑否则用户不知道切 Tab 没用。十二、学校投票的业务化设计App 22 的校园歌手/校园 logo/校园运动/校园菜品4 个投票——全部围绕校园主题——这是校园场景的业务化校园主题的具体体现校园歌手——文艺/活动校园活动经典项目校园 logo——学校形象设计/品牌⚽校园运动——体育学校体育节校园菜品——生活食堂主题4 个投票覆盖校园 4 大类文艺歌手形象logo体育运动生活菜品校园投票是学生群体的特色应用——真实校园场景下学生有集体决策需求选课/选活动/选菜品/选学生干部——App 22 是这类应用的最简骨架。真实项目扩展加投票广场全校学生都能发起加实名/匿名投票切换敏感话题匿名加投票截止提醒push 通知加实时票数更新WebSocket 推送十三、VoteList 的 Scroll 容器与安全区适配VoteList 外层包裹了Scroll容器配合安全区适配build() { Column() { this.Header() Scroll() { Column({ space: 14 }) { this.VoteList() } .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) }Scroll 容器的 3 个关键属性layoutWeight(1)—— 让 Scroll 占满 Header 以下的所有剩余空间——**Header 固定 列表滚动**的经典布局。scrollBar(BarState.Off)—— 隐藏滚动条——系列标准做法所有列表页都隐藏滚动条——隐藏滚动条 视觉更干净。align(Alignment.Top)—— 内容顶部对齐——滚动初始位置在顶部——打开就在第一项。安全区适配padding({ bottom: D.pad this.safeBottom 20 })——底部 padding 基础 padding 安全区高度 20vp 额外留白——底部 Tab 栏不遮挡最后一张卡片——这是全面屏有底部手势条的必备适配。Column({ space: 14 })—— Scroll 内层 Column 的 14vp 间距——卡片间距 呼吸感——适合卡片型列表信息密度低的列表。VoteList 内部的Column({ space: 12 })则是 4 张投票卡之间的 12vp 间距。十四、总结App 22 首页解析完毕。Header 双层结构标题 3 Tab 4 张投票卡emoji 状态色 剩余时间 参与投票按钮是核心组件。Header 内嵌 Tab是系列独有设计——适合按状态/类型分类且 Tab 数量少的场景。**3 状态优先级 颜色强度**是投票场景的特色设计橙色警示/红色突出/绿色平静。Scroll 容器 安全区适配确保全面屏下底部不被遮挡——这是所有列表页的通用适配方案。
返回列表