HarmonyOS NEXT 企业级记账APP:实现底部 Tab 导航
实现底部 Tab 导航本文是《HarmonyOS NEXT 企业级开发实战30篇打造智能记账APP》系列的第04篇对应 Git Tagv0.0.4。承接第 03 篇的主题系统本篇使用 ArkUI 的 Tabs 组件搭建首页、统计、预算、我的四个底导航 Tab并封装 AppTabBar 通用组件。前言底导航 Tab 是移动应用的核心导航模式用户 80% 的操作都从底导航发起。HarmonyLedger 规划四个主 Tab首页、统计、预算、我的。ArkUI 提供原生Tabs组件支持底导航但企业级项目需要封装统一的 AppTabBar 组件便于后续扩展与主题适配。本文将带你使用 ArkUI Tabs 组件搭建底导航框架封装 AppTabBar 通用组件支持图标、文字、主题色实现四个 Tab 页面占位与切换动效集成主题系统响应深色模式企业级核心原则底导航必须封装复用、禁止重复、支持主题。参考 ArkUI Tabs 组件 了解官方约定。一、Tab 规划1.1 四个主 TabHarmonyLedger 选用最经典的四 Tab布局覆盖核心业务场景Tab 序号名称图标页面业务0首页homeHomeView账单汇总、快捷新增1统计chartStatisticsView收支图表分析2预算budgetBudgetView预算设置与进度3我的userProfileView设置、关于1.2 Tab 命名规范Tab 命名规范 - 英文小写下划线home / chart / budget / user - 中文展示用首页 / 统计 / 预算 / 我的 - 图标资源icon_tab_{name}.png - 路由页面{Name}View.ets大驼峰 - 资源字符串tab_{name}_label设计要点Tab 命名一旦确定禁止修改否则会牵动图标、路由、字符串多处资源。二、Tabs 组件基础2.1 Tabs 与 TabContentArkUI 原生 Tabs 组件使用方式Entry Component struct MainView { State currentIndex: number 0; build() { Tabs({ index: this.currentIndex }) { TabContent() { HomeView() } .tabBar({ text: 首页, icon: $r(app.media.icon_tab_home) }) TabContent() { StatisticsView() } .tabBar({ text: 统计, icon: $r(app.media.icon_tab_chart) }) TabContent() { BudgetView() } .tabBar({ text: 预算, icon: $r(app.media.icon_tab_budget) }) TabContent() { ProfileView() } .tabBar({ text: 我的, icon: $r(app.media.icon_tab_user) }) } .barPosition(BarPosition.End) .onChange((index: number) { this.currentIndex index; }) } }2.2 关键属性属性说明值barPositionTab 位置BarPosition.End底导航/Start顶导航vertical是否纵向false默认横向scrollable可滚动false四 Tab 不需滚动onChange切换回调(index: number) voidtabBarTab 标签配置{ text, icon }踩坑点TabContent不能直接传 builder 参数必须用.tabBar(...)设置标签。这是鸿蒙 ArkUI 的强制约束。三、封装 AppTabBar3.1 组件设计目标企业级底导航需要满足图标文字双显示未选中态灰色、选中态主题色响应深色模式颜色自动切换Badge 角标支持消息提醒可配置Tab 数量与内容3.2 TabConfig 数据模型// model/TabConfig.ets export class TabConfig { name: string; // home / chart / budget / user label: string; // 显示文字 icon: Resource; // 图标资源 badge?: number 0; // 角标数字0 不显示 constructor(name: string, label: string, icon: Resource, badge?: number) { this.name name; this.label label; this.icon icon; this.badge badge ?? 0; } }3.3 AppTabBar 组件实现// components/navigation/AppTabBar.ets import { TabConfig } from ../../model/TabConfig; import { AppColors } from ../../theme/Colors; import { AppFontSize } from ../../theme/Typography; import { AppSpace } from ../../theme/Spacing; Component export struct AppTabBar { Prop tabs: TabConfig[] []; Prop currentIndex: number 0; BuilderParam onTabClick: (index: number) void; build() { Row() { ForEach(this.tabs, (tab: TabConfig, index: number) { Column() { Image(tab.icon) .width(24) .height(24) .fillColor(this.currentIndex index ? AppColors.Budget : AppColors.SecondaryText) Text(tab.label) .fontSize(AppFontSize.XS) .fontColor(this.currentIndex index ? AppColors.Budget : AppColors.SecondaryText) .margin({ top: AppSpace.XS }) // Badge 角标 if (tab.badge 0) { Text(tab.badge.toString()) .fontSize(10) .fontColor(#FFFFFF) .backgroundColor(AppColors.Expense) .borderRadius(8) .padding(2) .position({ x: 24, y: -4 }) } } .layoutWeight(1) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) .onClick(() { this.onTabClick(index); }) }, (tab: TabConfig) tab.name) } .width(100%) .height(56) .backgroundColor(AppColors.CardBackground) .border({ width: { top: 1 }, color: AppColors.Separator }) } }关键技术BuilderParam用于将点击回调暴露给父组件这是 ArkUI V1 组件通信的标准方案。四、四个 Tab 页面占位4.1 HomeView 占位// pages/HomeView.ets Entry Component struct HomeView { build() { Column() { Text(首页) .fontSize(24) .fontWeight(FontWeight.Bold) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }4.2 StatisticsView 占位// pages/StatisticsView.ets Entry Component struct StatisticsView { build() { Column() { Text(统计分析) .fontSize(24) .fontWeight(FontWeight.Bold) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }4.3 BudgetView 与 ProfileView// pages/BudgetView.ets Entry Component struct BudgetView { build() { Column() { Text(预算中心) .fontSize(24) .fontWeight(FontWeight.Bold) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } } // pages/ProfileView.ets Entry Component struct ProfileView { build() { Column() { Text(我的) .fontSize(24) .fontWeight(FontWeight.Bold) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }五、主页面集成5.1 MainView 集成 Tabs// pages/MainView.ets import { AppTabBar } from ../components/navigation/AppTabBar; import { TabConfig } from ../model/TabConfig; import { HomeView } from ./HomeView; import { StatisticsView } from ./StatisticsView; import { BudgetView } from ./BudgetView; import { ProfileView } from ./ProfileView; Entry Component struct MainView { State currentIndex: number 0; State tabs: TabConfig[] [ new TabConfig(home, 首页, $r(app.media.icon_tab_home)), new TabConfig(chart, 统计, $r(app.media.icon_tab_chart)), new TabConfig(budget, 预算, $r(app.media.icon_tab_budget)), new TabConfig(user, 我的, $r(app.media.icon_tab_user)) ]; build() { Stack({ alignContent: Alignment.TopStart }) { // 内容区 Column() { if (this.currentIndex 0) { HomeView() } else if (this.currentIndex 1) { StatisticsView() } else if (this.currentIndex 2) { BudgetView() } else { ProfileView() } } .width(100%) .height(100%) .padding({ bottom: 56 }) // 底导航 AppTabBar({ tabs: this.tabs, currentIndex: this.currentIndex, onTabClick: (index: number) { this.currentIndex index; } }) } .width(100%) .height(100%) } }5.2 路由配置更新// entry/src/main/resources/base/profile/main_pages.json { src: [ pages/MainView, // 主入口改为 MainView pages/HomeView, pages/StatisticsView, pages/BudgetView, pages/ProfileView ] }// EntryAbility.ets 入口改为 MainView windowStage.loadContent(pages/MainView, (err) { ... });架构调整入口从 HomeView 改为 MainView底导航由 MainView 持有四个 Tab 页面作为子组件。这是鸿蒙多 Tab 应用的标准结构。六、图标资源准备6.1 Tab 图标规格项规格尺寸24x24 dp格式PNG带 alpha 通道或 SVG色彩单色通过 fillColor 染色命名icon_tab_{name}.png6.2 资源放置entry/src/main/resources/base/media/ ├─ icon_tab_home.png ├─ icon_tab_chart.png ├─ icon_tab_budget.png └─ icon_tab_user.png统一染色方案图标统一用白色 PNG通过Image.fillColor()动态染色。这样未选中态、选中态、深色模式都能复用同一张图。七、最佳实践7.1 Tab 切换性能优化// ❌ 错误每次切换都重建所有 Tab 页面 Tabs() { TabContent() { HomeView() } TabContent() { StatisticsView() } // 切换到统计时HomeView 仍在后台占用内存 } // ✅ 正解用 if 懒加载 Stack() { if (this.currentIndex 0) { HomeView() } else if (this.currentIndex 1) { StatisticsView() } }7.2 Tab 状态保持如果希望 Tab 切换时保留各页面状态State homeState: HomeState new HomeState(); State statsState: StatsState new StatsState(); // 用 Stack 叇叠所有页面通过 visibility 控制 Stack() { HomeView({ state: this.homeState }).visibility(this.currentIndex 0 ? Visibility.Visible : Visibility.Hidden) StatisticsView({ state: this.statsState }).visibility(this.currentIndex 1 ? Visibility.Visible : Visibility.Hidden) }权衡状态保持会占用更多内存HarmonyLedger 暂不启用后续 v0.2.7 性能优化篇再讨论。八、运行验证8.1 编译检查hvigorw assembleHap--modemodule-pproductdefault8.2 运行验证应用启动后显示首页底导航四个 Tab 均可见点击统计 Tab切换到统计分析页选中态 Tab 文字和图标变蓝色AppColors.Budget未选中态 Tab 灰色深色模式下同步切换九、常见问题9.1 TabContent 传参错误错误原因解决TabContent(builder)不渲染不能传 builder 对象用TabContent() { ... }包裹内容图标不显示资源路径错误检查$r(app.media.icon_tab_xxx)名是否一致9.2 切换闪烁// 原因if 切换会销毁重建页面 // 解决用 visibility 保留所有页面 .visibility(currentIndex index ? Visibility.Visible : Visibility.Hidden)9.3 底部遮挡// 内容区需预留底导航高度 Column() { ... } .padding({ bottom: 56 }) // 与 AppTabBar.height 一致十、Git 提交10.1 Commit Messagegitadd.gitcommit-mfeat(navigation): 实现底部 Tab 导航与 AppTabBar 封装 - 新增 AppTabBar 通用底导航组件 - 新增 TabConfig 数据模型 - 创建 HomeView/StatisticsView/BudgetView/ProfileView 占位页 - 集成 MainView 持有 Tabs 切换 - 更新 EntryAbility 入口为 MainView - 添加四个 Tab 图标资源10.2 CHANGELOG## [v0.0.4] - 2026-07-27 ### Added - components/navigation/AppTabBar.ets通用底导航组件 - model/TabConfig.etsTab 配置数据模型 - pages/MainView.ets主页面持有 Tabs - pages/StatisticsView.ets、BudgetView.ets、ProfileView.ets占位页 - 资源icon_tab_home/chart/budget/user.png ### Changed - EntryAbility 入口改为 MainView - main_pages.json 增加 MainView 路由附录运行效果截图上图展示了本模块的完整运行效果。实际项目中可使用 DevEco Studio 模拟器或真机截图替换此占位图。总结本文完整介绍了 HarmonyLedger底部 Tab 导航的实现包含原生 Tabs 用法、AppTabBar 组件封装、四个 Tab 页面占位、主页面集成。通过本篇你可以使用 ArkUI Tabs 组件搭建底导航封装可复用的 AppTabBar 组件支持图标文字角标实现主题色响应选中态与深色模式理解 EntryAbility 与 MainView 的入口关系下一篇预告《首页布局与 SummaryCard 设计》将开发首页核心 UI今日支出、今日收入、最近账单列表并封装 SummaryCard 汇总卡片组件。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源本篇源码GitHub Tag v0.0.4ArkUI Tabs 文档tabsArkUI Image 组件imageTabContent APItabcontentArkUI 组件通信component-communicationBarPosition 枚举barposition鸿蒙图标资源规范icon-resources

相关新闻

混合云架构下网络互通方案设计

混合云架构下网络互通方案设计

混合云架构下网络互通方案设计随着企业数字化转型的深入,混合云凭借其兼顾公有云弹性灵活与私有云安全可控的独特优势,已成为主流IT架构选择。然而,混合云的核心价值在于“混合”,即公有云与私有云、边缘节点乃至多云环境之间能否…

2026/7/29 2:22:11 阅读更多 →
嵌入式领域AI4SE详解:AI赋能软件工程的实践与展望

嵌入式领域AI4SE详解:AI赋能软件工程的实践与展望

1. 引言:嵌入式软件开发的挑战与AI机遇嵌入式系统作为现代工业、汽车、医疗和消费电子的核心,其软件开发面临着独特的挑战:资源受限(内存、算力)、实时性要求高、安全性与可靠性至关重要、软硬件耦合紧密、开发周期长且…

2026/7/29 2:21:11 阅读更多 →
AcWing 多重背包问题I

AcWing 多重背包问题I

问题如下: 有 N种物品和一个容量是 V的背包。 第 i 种物品最多有 si件,每件体积是 vi,价值是 wi。 求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。 输出最大价值。 输入格式 第一行两个整数…

2026/7/29 2:21:11 阅读更多 →

最新新闻

Kali Linux无线安全评估实战:从WPA2握手原理到密码破解防御

Kali Linux无线安全评估实战:从WPA2握手原理到密码破解防御

1. 项目概述:从“破解”到“安全评估”的认知转变看到“Kali Linux破解WiFi教程”这个标题,很多朋友的第一反应可能是想“蹭个网”。但作为一名在网络安全领域摸爬滚打多年的从业者,我必须在一开始就明确一个核心观点:我们今天讨论…

2026/7/30 3:33:22 阅读更多 →
Android相机黑屏问题排查与优化实践

Android相机黑屏问题排查与优化实践

1. 问题现象与初步排查58同城App作为国内头部生活服务平台,其相机功能在二手房拍摄、求职简历上传等核心场景中扮演重要角色。近期我们收到用户反馈,部分Android设备在调用App内相机时出现黑屏现象,具体表现为:点击拍照按钮后相机…

2026/7/30 3:33:22 阅读更多 →
Python实现Antoine方程蒸汽压计算与可视化:从原理到工程实践

Python实现Antoine方程蒸汽压计算与可视化:从原理到工程实践

1. 项目概述:从数据到洞察,用Python解锁Antoine方程在化工、热力学乃至环境科学领域,物质的蒸汽压是一个基础且关键的物性参数。它决定了液体何时沸腾、混合物如何分离,甚至是大气中污染物的挥发性。对于工程师和科研人员来说&…

2026/7/30 3:33:22 阅读更多 →
Simulink仿真单相全桥逆变电路:从SPWM原理到工程调试全解析

Simulink仿真单相全桥逆变电路:从SPWM原理到工程调试全解析

1. 项目概述:从理论到实践的逆变电路仿真如果你正在学习电力电子,或者工作中需要设计一个将直流电转换成交流电的装置,那么“单相电压型逆变电路”绝对是你绕不开的核心课题。这不仅是教科书里的经典案例,更是光伏逆变器、不间断电…

2026/7/30 3:33:22 阅读更多 →
Python实现Word转图片:跨平台自动化方案与实战指南

Python实现Word转图片:跨平台自动化方案与实战指南

1. 项目缘起:为什么需要将Word转成图片? 在日常工作中,我们经常会遇到一个看似简单却颇为棘手的需求:如何把一个精心排版的Word文档,原封不动地、高质量地转换成一张或多张图片?这个需求远比你想象中更常见…

2026/7/30 3:33:22 阅读更多 →
03数据结构

03数据结构

树结构之红黑树[不那么平衡的平衡二叉树]红黑树要遵循红黑规则 : 1.红黑树中的节点有颜色属性,颜色属性为红或黑2.根节点的颜色一定是黑的3.当红黑树节点没有子节点时,需用叶子节点表示最后节点4.两个红色节点不可以相连5.根节点到其任意最远叶子节点,所经历的简单路径,上黑色节…

2026/7/30 3:32:22 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻