第20篇|底部导航:地图、拍照、相册、保险箱的产品路径

发布时间:2026/5/30 0:52:26

第20篇|底部导航:地图、拍照、相册、保险箱的产品路径 第20篇底部导航地图、拍照、相册、保险箱的产品路径底部导航看起来只是四个入口但在一个相机类应用里它实际定义了产品路径从「在哪里拍」进入地图从「马上拍」进入相机从「拍完看」进入相册从「私密内容」进入保险箱。导航如果只做成按钮就会漏掉状态、权限和内容边界。本篇对应源码仍然是entry/src/main/ets/pages/Index.ets重点看buildBottomNavigation()、buildNavItem()和buildNavIconMark()。四个入口不是四个普通按钮项目里的底部导航是这样组织的Row() { this.buildNavItem(地图, map) this.buildNavItem(拍照, camera) this.buildNavItem(相册, gallery) this.buildNavItem(保险箱, vault) }每个入口都走同一个buildNavItem(label, tab)这样选中态、字体、边框、光效、点击行为可以统一维护。统一并不等于行为完全一样gallery的点击会走openFullGalleryFromNavigation()其他入口走switchTab(tab)。这是一个很小但重要的产品判断相册不是普通页签它要进入完整浏览路径。为什么导航层要透明命中地图页底部覆盖层代码里有一段容易被忽略Column({ space: 14 }) { if (this.getMapPhotoDockMemories().length 0) { this.buildMapPhotoGroupDock() } this.buildBottomNavigation() } .hitTestBehavior(HitTestMode.Transparent)它的意思是容器空白区域不吃掉手势真正的卡片和按钮才响应点击。这样用户在底部附近仍然能拖动地图不会感觉地图「死掉了一块」。这比单纯调zIndex更可靠因为问题不在层级而在命中区域。选中态为什么要同时改图标、边框和光效buildNavIconMark()使用资源命名来区分默认态和选中态Image(this.isActiveTab(tab) ? $r(app.media.nav_camera_active) : $r(app.media.nav_camera))再配合ml_selected_glass、getNavGlowColor(tab)和hdsEffect.HdsEffectBuilder().pointLight(...)选中态会同时体现在图标、背景、边框和光效上。官方 UIDesignKit 文档提供了hdsEffect和HdsEffectBuilder项目里用它做导航玻璃层的光照反馈而不是只把文字变粗。和侧边导航的关系buildBottomNavigation()的第一句是if (this.shouldUseSideNavigation()) { Blank().width(0).height(0) } else { // 构建底部导航 }这说明底部导航只服务手机形态。宽度达到平板/2in1 条件后主入口交给侧边导航。这个判断避免了一个常见问题大屏上同时出现底部导航和侧边导航路径重复空间也浪费。自测建议在地图页拖动底图确认底部透明区域不阻断地图手势。依次点击地图、拍照、相册、保险箱确认选中态和页面内容一致。点击相册入口确认走完整相册路径而不是只切普通 Tab。把窗口宽度调到 600vp 以上确认底部导航消失、侧边导航出现。切深色模式确认ml_nav_glass、ml_selected_glass、文字色和图标仍然可读。导航行为不是一个 switch 就结束底部导航的点击分支看起来很短但背后有清楚的产品语义.onClick(() { if (tab gallery) { this.openFullGalleryFromNavigation(); return; } this.switchTab(tab); })map、camera、vault是主 Tab 切换gallery是完整浏览路径。这样设计是因为相册页不仅展示缩略图还承担大图查看、筛选、回看和返回逻辑。如果相册也只做switchTab(gallery)用户从首页进入后会丢失“完整浏览”的上下文后续文章讲相册详情时就会发现入口不一致。视觉状态的四个来源一个导航项的选中态由四部分组成不是单独靠颜色来源代码位置作用图标资源buildNavIconMark(tab)默认态和_active成对切换玻璃背景ml_selected_glass让当前入口有稳定承托面边框和阴影getNavGlowColor(tab)区分不同业务入口的强调色光照效果hdsEffect.HdsEffectBuilder()让玻璃层有系统级质感官方hdsEffect文档提供的是效果能力项目里没有把它当成装饰堆叠而是只在导航容器和选中项上使用。这样做的好处是光效有明确语义它只强调“你现在在哪个路径里”。代码验证 1底部导航只在手机形态出现buildBottomNavigation()开头直接判断侧边导航if (this.shouldUseSideNavigation()) { Blank() .width(0) .height(0) } else { // 构建底部导航 }这段代码可以用窗口宽度验证。把预览器或真机窗口拖到 600vp 以上底部导航应该消失再缩回手机宽度它应该重新出现。这个判断比在 CSS 或样式里隐藏某个容器更可靠因为它从构建阶段就不再输出底部导航避免大屏上出现两个主入口。代码验证 2资源成对存在第 20 篇用到的导航资源必须成对存在否则选中态会断。可以在项目根目录运行Get-ChildItem entry/src/main/resources/base/media -File | Where-Object { $_.Name -like nav_* } | Sort-Object Name应该能看到nav_map.png和nav_map_active.png、nav_camera.png和nav_camera_active.png、nav_gallery.png和nav_gallery_active.png、nav_vault.png和nav_vault_active.png。这就是官方资源访问文档里“通过资源文件管理媒体资源”的落地方式代码只写$r(app.media.nav_camera)真正替换视觉时改资源文件不改导航逻辑。可复用检查清单如果你也在做相机、地图或工具类应用可以按下面顺序检查底部导航先确认每个入口是否代表不同任务而不是仅仅分页面。再确认特殊路径是否单独处理例如本文的相册入口。然后检查命中区域容器空白不要吞掉地图或内容手势。最后检查大屏降级底部导航和侧边导航不要同时存在。这套顺序比先画 UI 更稳因为它先确定“入口要完成什么任务”再决定“入口长什么样”。小结一个高质量导航不只是能点。它要表达当前所在位置要把不同业务路径分开还要在地图这种强交互背景上处理好命中区域。这里的实现把「路径统一」和「行为差异」放在同一层UI 统一由buildNavItem()承担特殊路径由点击分支承担设备差异由shouldUseSideNavigation()承担。参考依据华为开发者文档《hdsEffect》https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ui-design-hdseffect华为开发者文档《资源分类与访问》https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access项目源码entry/src/main/ets/pages/Index.ets

相关新闻