HarmonyOS 3D 拆解分析:单页多 Tab 架构的实现

发布时间:2026/7/8 2:27:20

HarmonyOS 3D 拆解分析:单页多 Tab 架构的实现
前言之前的 3D 拆解分析 App 有两个页面Index首页和AnalysisPage分析工作台。用户在首页选好场景后通过router.pushUrl跳转到分析页面。分析完按返回键回到首页。这个架构能跑但有个问题每次从分析页返回首页页面会重新渲染之前的场景选择状态会丢失。而且两个页面之间传参需要router.pushUrlrouter.getParams数据流绕了一圈。这次重构把首页和分析页合并成一个页面用底部 Tab 导航切换。不再需要页面跳转所有状态都在同一个组件里管理。架构变化旧架构两个独立页面Index.ets (首页) → router.pushUrl → AnalysisPage.ets (分析页) → router.back → Index.ets新架构单页多 TabIndex.ets ├── Tab 0: HomeTab() — 首页内容 ├── Tab 1: AnalyzeTab() — 分析工作台 └── Tab 2: HistoryTab() — 历史记录占位所有 Tab 共享同一个组件实例切换 Tab 只是改变State tab的值不会触发页面重建。底部导航栏SymbolGlyph Tab 切换导航栏布局build(){Stack({alignContent:Alignment.Bottom}){Scroll(){Column(){if(this.tab0){this.HomeTab()}elseif(this.tab1){this.AnalyzeTab()}else{this.HistoryTab()}Blank().height(90)}}Row(){this.TabBtn(0,首页)this.TabBtn(1,拆解)this.TabBtn(2,历史)}.width(100%).height(68).backgroundColor(CW).justifyContent(FlexAlign.SpaceAround).alignItems(VerticalAlign.Center).shadow({radius:12,color:rgba(0,0,0,0.05),offsetY:-2})}}用Stack让导航栏浮在内容区上面。Blank().height(90)在内容区底部留白防止最后一行内容被导航栏遮挡。Tab 按钮组件BuilderTabBtn(idx:number,label:string){Column({space:3}){SymbolGlyph(this.tabIcon(idx,this.tabidx)).fontSize(22).fontColor([this.tabidx?A:#C0BFC6])Text(label).fontSize(10).fontColor(this.tabidx?A:#C0BFC6)}.onClick((){this.tabidx})}三个 Tab首页sys.symbol.house/sys.symbol.house_fill拆解sys.symbol.scope瞄准镜图标代表分析历史sys.symbol.clock时钟图标代表时间线选中态用品牌紫A未选中用淡灰#C0BFC6。图标选择逻辑privatetabIcon(idx:number,active:boolean):Resource{if(active){if(idx0)return$r(sys.symbol.house_fill)if(idx1)return$r(sys.symbol.scope)return$r(sys.symbol.clock)}if(idx0)return$r(sys.symbol.house)if(idx1)return$r(sys.symbol.scope)return$r(sys.symbol.clock)}注意scope和clock没有_fill版本或系统不支持所以选中和未选中用同一个图标只通过颜色区分。house有_fill版本选中时用实心。这种情况很常见——不是所有系统图标都有_fill变体。处理方式没有_fill的图标就用颜色区分有的就用填充颜色双重区分。状态管理从跨页传参到组件内共享旧方案路由传参// 首页privatepush(cols,rows,uri):void{router.pushUrl({url:pages/AnalysisPage,params:{gridCols:cols,...}})}// 分析页aboutToAppear(){constprouter.getParams()asRecordstring,Objectthis.colsp[gridCols]asnumber}新方案组件内状态Statetab:number0Stateuri:stringStatename:stringStatecols:number3Staterows:number3// ... 更多状态privatestartAnalysis(uri:string,c:number,r:number,n:string):void{this.uriurithis.colscthis.rowsrthis.namenthis.val0this.onfalsethis.listfalsethis.rebuildAnalysis()this.tab1// 切换到分析 Tab}startAnalysis方法做三件事设置分析数据uri、cols、rows、name重置 UI 状态val0、onfalse、listfalse切换到分析 Tab不需要路由跳转不需要参数序列化/反序列化所有数据都在同一个组件里。rebuildAnalysis从路由参数到直接调用privaterebuildAnalysis():void{constparts:PartInfo[]segmentImage(this.cols,this.rows,360,360)this.countparts.lengththis.pnpartsToNames(parts)this.pxpartsToGridX(parts)this.pypartsToGridY(parts)this.pdpartsToDepths(parts)// ... 构建网格数据和部件卡片}旧版的rebuild在aboutToAppear中调用依赖路由参数。新版的rebuildAnalysis在startAnalysis中调用直接使用组件内的State变量。首页 Tab场景选择的保留HomeTab 保留了之前的所有功能——问候语、Hero Card、统计卡片、场景预设、三步流程。唯一的区别是点击开始分析时不再跳转页面// 旧版.onClick((){this.push(this.cols(),this.rows(),)})// 新版.onClick((){this.startAnalysis(,this.colsH(),this.rowsH(),recommendGrid(this.colsH(),this.rowsH()))})startAnalysis接收四个参数图片 URI、列数、行数、物品名称。首页没有拍照功能所以 URI 传空字符串。分析 Tab从独立页面到 Tab 内容AnalyzeTab 的布局和之前的 AnalysisPage 几乎一样——头部、工作区、滑块、网格选择、部件清单。区别在于不需要aboutToAppear获取路由参数——数据已经在startAnalysis中设置好了不需要router.back()——切换回首页只需this.tab 0状态变量直接在组件内——不需要跨页面传递工作区高度固定.width(100%).height(320).margin({left:16,right:16,bottom:8})旧版的工作区用.layoutWeight(1)占满剩余空间。新版固定高度 320px——因为 Tab 切换时内容区高度不变用固定高度更可控。部件清单的紧凑化// 旧版.height(170).padding(14).borderRadius({topLeft:18,topRight:18})// 新版.height(140).padding(12).borderRadius({topLeft:16,topRight:16})部件清单的高度、内边距、圆角都缩小了。在 Tab 布局中垂直空间更宝贵——底部导航栏占了 68px内容区需要更紧凑。历史 Tab占位设计BuilderHistoryTab(){Column(){Text(分析历史).fontSize(20).fontWeight(FontWeight.Bold).fontColor(T1).width(100%).padding({left:18,top:14}).margin({bottom:12})Column(){Text().fontSize(48).opacity(0.2).margin({bottom:12})Text(暂无分析记录).fontSize(15).fontWeight(FontWeight.Medium).fontColor(T2)Text(切换到首页选择场景开始拆解).fontSize(12).fontColor(T3).margin({top:4})}.width(100%).layoutWeight(1).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}空状态设计标题分析历史图标48px20% 透明度主文案暂无分析记录副文案切换到首页选择场景开始拆解副文案引导用户去首页操作而不是让用户猜测这个页面是干什么的。保留 AnalysisPage 的原因新版 Index 已经包含了分析功能但AnalysisPage.ets没有删除。原因向后兼容如果有其他页面通过router.pushUrl跳转到 AnalysisPage它仍然能工作独立使用如果后续需要把分析功能单独抽出来比如做成一个可复用的组件AnalysisPage 可以作为参考渐进式迁移先在 Index 中实现新架构验证没问题后再删除旧页面踩坑记录1. Tab 切换时的状态保留if(this.tab0){this.HomeTab()}elseif(this.tab1){this.AnalyzeTab()}ArkUI 的if/else条件渲染会在条件变化时销毁旧组件、创建新组件。这意味着切换 Tab 时每个 Tab 的内部状态会丢失。如果需要保留 Tab 状态比如分析页的滑块位置有两个方案用Visibility控制显示/隐藏组件不销毁只是不可见把需要保留的状态提升到父组件当前方案——val、on等状态在 Index 层管理2. Blank().height 的高度计算Blank().height(90)这个高度需要 ≥ 导航栏高度68px 安全区域。设 90px 留了 22px 的余量。如果设太小最后一行内容会被导航栏遮挡。3. Scroll 的 edgeEffect 在 Tab 切换时Scroll(){...}.edgeEffect(EdgeEffect.Spring)Tab 切换时 Scroll 会重置滚动位置。如果需要记住每个 Tab 的滚动位置需要在切换时保存和恢复scrollOffset。4. SymbolGlyph 的选中态图标不是所有sys.symbol.*都有_fill版本。使用前最好在 DevEco Studio 的预览里确认。如果没有_fill就用颜色区分选中/未选中。写在最后单页多 Tab 架构的核心优势是状态共享——首页选的场景、分析页的滑块位置、部件清单的展开状态都在同一个组件里切换 Tab 不会丢失。代价是代码量增加了——Index.ets 现在包含了三个 Tab 的所有代码文件变长了。如果后续每个 Tab 的功能越来越复杂可以考虑把每个 Tab 拆成独立组件在 Index 中组合使用build(){Stack({alignContent:Alignment.Bottom}){Column(){if(this.tab0){HomeTab({preset:$preset})}elseif(this.tab1){AnalyzeTab({uri:$uri,...})}else{HistoryTab()}}this.BottomNav()}}这样每个 Tab 的代码独立维护Index 只负责 Tab 切换和状态管理。

相关新闻

【2026年下】中小学教师资格考试《综合素质》(中学)历年真题和答案

【2026年下】中小学教师资格考试《综合素质》(中学)历年真题和答案

2026/7/8 2:17:20

2026年下半年中小学教师资格考试考试 2026年下半年中小学教师资格考试笔试定于2026年9月12日举行。为助力广大考生高效备考,我们现正式发布中学学段《综合素质》(科目一)历年真题及配套资料合集。 资料内容详情 本合集为PDF电子版&#xf…

【单片机毕业设计】基于 STM32/51 单片机的 8 路病床无线呼叫对讲系统设计,基于 NRF24L01 的病房智能呼叫与输液监测装置开发(020301)

【单片机毕业设计】基于 STM32/51 单片机的 8 路病床无线呼叫对讲系统设计,基于 NRF24L01 的病房智能呼叫与输液监测装置开发(020301)

2026/7/8 2:17:20

文章目录20 个相关毕业设计备选题目项目研究背景摘要总体方案硬件设备选型、作用与架构说明整体硬件架构核心功能一、基础硬件交互功能二、无线通信采集核心功能三、优先级调度医护交互功能四、输液监测辅助功能五、语音对讲特色功能技术路线项目演示关于我们项目案例源码获取博…

简历审查Agent工程化收尾:模型坑位、线程安全、超时兜底与RAG预告

简历审查Agent工程化收尾:模型坑位、线程安全、超时兜底与RAG预告

2026/7/8 2:17:20

0. 上下文衔接 Day 6 完成了简历审查Agent的API层骨架:上传返回202、后台create_task+GC保护、轮询查询、图编排。但代码跑通和能上线之间还有一段距离,今天收尾处理一批工程化问题: DeepSeek V4模型的思考模式坑:换模型后结构化输出全部报错 图实例的线程安全:全局单例图…

DDrawCompat:终极DirectDraw兼容性解决方案,让经典游戏在Windows 10/11上完美运行

DDrawCompat:终极DirectDraw兼容性解决方案,让经典游戏在Windows 10/11上完美运行

2026/7/8 7:17:46

DDrawCompat:终极DirectDraw兼容性解决方案,让经典游戏在Windows 10/11上完美运行 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: htt…

GTA5线上小助手:一站式免费开源游戏增强工具集

GTA5线上小助手:一站式免费开源游戏增强工具集

2026/7/8 7:17:46

GTA5线上小助手:一站式免费开源游戏增强工具集 【免费下载链接】GTA5OnlineTools GTA5线上小助手 项目地址: https://gitcode.com/gh_mirrors/gt/GTA5OnlineTools 还在为GTA5线上模式的复杂操作而烦恼吗?想要更轻松地定制角色、优化载具性能、快速…

如何选择合适的锡膏存储方案?

如何选择合适的锡膏存储方案?

2026/7/8 7:17:46

选型核心原则在选择合适的锡膏存储方案时,应重点关注其是否能够实现全流程的自动化管理、精准的温控能力、数据追溯以及系统集成等关键维度。本文旨在提供一个全面的选型方法论,而非推荐具体产品或品牌。通用选型标准1. 全流程自动化管理理想的智能锡膏存…

不会写代码怎么选量化软件:回测提醒和仓位记录要清楚

不会写代码怎么选量化软件:回测提醒和仓位记录要清楚

2026/7/8 7:17:46

不会写代码的人选量化软件,先别追复杂框架。更实用的检查项是:回测能不能看懂,提醒有没有原因,仓位和止损有没有记录。牛股王股票这类面向普通投资者的量化辅助软件,适合把低门槛规则、最长 5 年历史回测、智能盯盘、调…

基于WebView2与健康度引擎的Cloudflare友好型数据采集方案

基于WebView2与健康度引擎的Cloudflare友好型数据采集方案

2026/7/8 7:17:46

摘要:本文介绍了一种使用 WebView2 真实浏览器配合 Session 健康度引擎,实现任意 IP 稳定通过 Cloudflare 验证的低成本数据采集方案。通过实时评估 Cloudflare 反馈动态调整请求间隔,结合基于 OpenCV 的系统级自动点击,让采集行为…

DDrawCompat:3步解决Windows老游戏兼容性难题的终极方案

DDrawCompat:3步解决Windows老游戏兼容性难题的终极方案

2026/7/8 7:07:46

DDrawCompat:3步解决Windows老游戏兼容性难题的终极方案 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirrors/dd/DDra…

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

2026/7/8 0:44:47

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gi…

6个月转型AI工程师:实战路径与核心技能

6个月转型AI工程师:实战路径与核心技能

2026/7/8 6:29:42

1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公…

YOLOv5模型剪枝与量化实战:边缘设备部署优化

YOLOv5模型剪枝与量化实战:边缘设备部署优化

2026/7/7 13:20:59

1. 项目背景与核心价值在计算机视觉领域,YOLOv5因其出色的实时检测性能成为工业界宠儿。但当我们尝试将其部署到边缘设备(如树莓派、Jetson Nano或手机终端)时,立刻会遇到两个致命问题:模型体积庞大(原始YO…

Qwen Code+Obsidian构建可执行的AI时代认知操作系统

Qwen Code+Obsidian构建可执行的AI时代认知操作系统

2026/7/8 0:07:15

1. 项目概述:这不是又一个笔记软件教程,而是一套可复用的“认知操作系统”搭建逻辑你有没有试过,在读完Andrej Karpathy那篇著名的《Software 2.0》之后,满脑子都是“神经网络即代码”的震撼,但合上网页,打…

校园服饰细分赛道测算程序,学生平价国风,机能穿搭市场规模预估。

校园服饰细分赛道测算程序,学生平价国风,机能穿搭市场规模预估。

2026/7/8 0:07:15

校园服饰细分赛道测算程序(Python)——学生平价国风 & 机能穿搭市场规模预估(TAM / SAM / SOM)一、实际应用场景描述(真实业务抽象)在《时尚产业与品牌创新》课程中,细分市场切入&#xff0…

Visual C++运行库完整解决方案:告别软件兼容性问题

Visual C++运行库完整解决方案:告别软件兼容性问题

2026/7/8 0:07:15

Visual C运行库完整解决方案:告别软件兼容性问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾为打开游戏时弹出的"DLL缺失"错误…