#星光不负 码向未来# 鸿蒙6.0开发进阶:告别朴素导航栏,用 HdsNavigation 打造高级视觉体验 原创

锦绣河山醉清风
发布于 2025-10-22 15:27
浏览
0收藏

引言

各位小伙伴,在鸿蒙应用开发中,导航栏作为用户交互的重要入口,其设计直接影响整体视觉质感。原生 Navigation 组件虽能满足基础需求,但在动态视觉效果和精细化样式控制上难免显得单薄。
#星光不负 码向未来#  鸿蒙6.0开发进阶:告别朴素导航栏,用 HdsNavigation 打造高级视觉体验-鸿蒙开发者社区
如果你正想为应用导航栏添加滚动渐变、毛玻璃模糊等高级效果,那么 @kit.UIDesignKit 中的 HdsNavigation 组件或许正是你需要的解决方案。来,跟着我一步一步实现它吧!
坐稳喽,开始发车!

第一站:“装修队”入场 (Import)

#星光不负 码向未来#  鸿蒙6.0开发进阶:告别朴素导航栏,用 HdsNavigation 打造高级视觉体验-鸿蒙开发者社区

首先,咱们不能用“游击队”了,得请“正规军”。HdsNavigation 不在标准 ArkUI 里,它在官方提供的“精品 UI 套件” @kit.UIDesignKit (HarmonyOS Design System, Hds) 里。

所以,第一步,先 import 把它请进来!

import { HdsNavigation, HdsNavigationAttribute, ScrollEffectType, HdsNavigationTitleMode } from '@kit.UIDesignKit';
import { LengthMetrics } from '@kit.ArkUI';

const  TITLE_BAR_HEIGHT_FREE: number = 138;

(P.S. 那个 TITLE_BAR_HEIGHT_FREE 是个常量,后面有用,先记住它。)

第二站:准备“遥控器”和“状态”

#星光不负 码向未来#  鸿蒙6.0开发进阶:告别朴素导航栏,用 HdsNavigation 打造高级视觉体验-鸿蒙开发者社区
老规矩,@Entry@Component 开局。

这次我们的“状态” @State 比较有意思:

  1. @Provide('pageInfos'): 这个是给 HdsNavigation 用的“导航地图”,NavPathStack 专门管页面跳转,@Provide 意思是“我把它共享出去了,导航栏你自己来拿着用”。
  2. scroller: 这是一个 Scroll(滚动条)的“遥控器”,HdsNavigation 需要知道你滚了多少,才能实现特效。
  3. blankHeight: 这是个重点! 我们用 @State 存了一个“空白高度”。
  4. titleMode: 标题栏的模式。我们用的是 FREE 模式,意思是标题栏会“浮”在内容的上层
  5. subTitle: 副标题,纯粹是为了好看。
@Entry
@Component
struct Index {
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack();
  scroller: Scroller = new Scroller();
  @State blankHeight: number = TITLE_BAR_HEIGHT_FREE;
  @State isHideBackButton: boolean = false;
  @State titleMode: HdsNavigationTitleMode = HdsNavigationTitleMode.FREE;
  @State subTitle: string = '江山美如画,人生苦无涯'

第三站:搭骨架 (HdsNavigation + Scroll)

build 函数来了。

  1. 最外层,我们不用 Navigation,而是用“豪华版” HdsNavigation,并把“导航地图” pageInfos 交给它。
  2. 里面放一个 Scroll,并把“遥控器” scroller 装上。
  3. Scroll 里面放 ColumnColumn 里面……先别急着放图片!
  build() {
    HdsNavigation(this.pageInfos) {
      Column() {
        Stack() {
          Scroll(this.scroller) {
            Column() {

第四站:核心技巧——“隐形占位符” (Blank)

还记得 FREE 模式吗?标题栏是“浮”在上面的。如果我们直接放图片,图片就会顶到屏幕最顶上,被大标题栏(138vp)盖住一大截!

[Image showing content hidden under a large title bar]

怎么办?

很简单,在图片前面,先放一个**“隐形占位符” Blank()**,它的高度(this.blankHeight)正好等于那个大标题栏的高度(138vp)。

这就像在列表开头加了个 padding-top,把图片“挤”下来,正好显示在大标题栏的下方。这就是那个 TITLE_BAR_HEIGHT_FREE 常量的意义所在!

              Blank().height(this.blankHeight)
              Image($r('app.media.moxian')).width('100%')

              Blank().height(this.blankHeight)
              Image($r('app.media.taihangshan')).width('100%')

              Blank().height(this.blankHeight)
              Image($r('app.media.yunnan')).width('100%')
            }
          }.edgeEffect(EdgeEffect.Spring).scrollBar(BarState.Off)
        }
      }
    }

第五站:“豪华装修订单” (.titleBar)

HdsNavigation 最牛的地方来了,它不像原生 Navigation 那样只能改改标题。它提供了一个超——长——的 .titleBar 配置项,就像一份“装修订单”,你想要啥样,直接“勾选”!

    .titleBar({
      padding: {
        start: LengthMetrics.vp(2),
        end: LengthMetrics.vp(2)
      },

第六站:点亮“毛玻璃”特效! (scrollEffectOpts)

在“装修订单”里,我们最关心的就是 style 里的 scrollEffectOpts(滚动特效选项)。

  • enableScrollEffect: true: “老板,我要特效!”
  • scrollEffectType: ScrollEffectType.COMMON_BLUR: “我要那种最经典的**‘毛玻璃’模糊特效**!”
  • blurEffectiveStartOffset: 从哪里开始模糊。
  • blurEffectiveEndOffset: 滚到哪里时模糊效果拉满。
      style: {
        scrollEffectOpts: {
          enableScrollEffect: true,
          scrollEffectType: ScrollEffectType.COMMON_BLUR,
          blurEffectiveStartOffset: LengthMetrics.vp(0),
          blurEffectiveEndOffset: LengthMetrics.vp(20)
        },

第七站:“装修订单”的其他配置

后面就是一堆“精装修”配置了,我(小白)的理解是:

  • originalStyle: 滚动之前(原始状态)的样式。
  • scrollEffectStyle: 滚动之后的样式。
  • content: 标题栏里到底放啥。
    • title: 主标题和副标题(副标题用了我们的 @State 变量)。
    • menu: 右上角的菜单按钮,它是一个数组,你可以放N个图标!
    • backIcon: 返回按钮(虽然我们后面又把它关了)。

这一大坨代码,你不需要全背下来,直接从官方文档“复制粘贴”再改改就行,主打一个“拿来主义”!

        originalStyle: {
          backgroundStyle: {
            backgroundColor: $r('sys.color.ohos_id_color_background'),
          },
          contentStyle: {
            titleStyle: { mainTitleColor: $r('sys.color.font_primary'), subTitleColor: $r('sys.color.font_secondary') },
            menuStyle: { backgroundColor: $r('sys.color.comp_background_tertiary'), iconColor: $r('sys.color.icon_primary') },
            backIconStyle: { backgroundColor: $r('sys.color.comp_background_tertiary'), iconColor: $r('sys.color.icon_primary') }
          }
        }, scrollEffectStyle: {
          backgroundStyle: {
            backgroundColor: $r('sys.color.ohos_id_color_background_transparent'),
          },
          contentStyle: {
            titleStyle: { mainTitleColor: $r('sys.color.font_primary'), subTitleColor: $r('sys.color.font_secondary') },
            menuStyle: { backgroundColor: $r('sys.color.comp_background_tertiary'), iconColor: $r('sys.color.icon_primary') },
            backIconStyle: { backgroundColor: $r('sys.color.comp_background_tertiary'), iconColor: $r('sys.color.icon_primary') }
          }
        }
      },
      content: {
        title: {
          mainTitle: '我的图片',
          subTitle: this.subTitle
        },
        menu: {
          value: [{
            content: {
              label: 'menu1',
              icon: $r('sys.symbol.ohos_wifi'),
              isEnabled: true,
              action: () => {
                console.info("HdsNavigation menu1");
              }
            }
          }, {
            content: {
              label: 'menu2',
              icon: $r('sys.symbol.plus'),
              isEnabled: true,
            }
          }, {
            content: {
              label: 'menu3',
              icon: $r('sys.symbol.lock'),
            }
          }, {
            content: {
              label: 'menu4',
              icon: $r('sys.symbol.trunk'),
            }
          }]
        },
        backIcon: {
          label: 'backButton',
          icon: $r('sys.symbol.trunk'),
          isEnabled: true,
        }
      }
    })

第八站:“老板,再帮我调一下!”

“装修订单” (.titleBar) 提交后,我们还可以再补几句:

  • .systemBarStyle(...): 连最顶上的“状态栏”(显示时间、电量那个)也帮我管管!
  • .titleMode(this.titleMode): 最终决定,用 FREE 模式!
  • .hideBackButton(this.isHideBackButton): 啊,我这个是首页,还是把返回按钮藏起来吧。
  • .hideTitleBar(false): 标题栏?当然不能隐藏!

收工!

    .systemBarStyle({ statusBarContentColor: '#0A59F7' }, { statusBarContentColor: '#C7C7CD' })
    .titleMode(this.titleMode)
    .hideBackButton(this.isHideBackButton)
    .hideTitleBar(false)
  }
}

实战总结

通过 HdsNavigation 组件的实践,我们不仅实现了比原生导航栏更丰富的视觉效果,还掌握了几个关键开发技巧:

  1. 组件选型:借助官方 @kit.UIDesignKit 套件,无需从零构建动态导航效果,降低开发成本。
  2. 动态特效实现:通过 scrollEffectOpts 配置,轻松启用滚动时的毛玻璃模糊效果,提升界面层次感。
  3. 布局适配方案:利用 FREE 模式配合 Blank 占位组件,完美解决浮动导航栏遮挡内容的问题,确保界面元素展示合理。

掌握这些技巧后,你可以根据实际需求进一步调整 HdsNavigation 的样式参数,让导航栏既能满足功能需求,又能成为提升应用质感的亮点。

怎么样,老司机开车还稳当不,稳稳的教你学会了吧,快自己动手敲一敲,体验“豪华导航”带来的视觉升级吧!

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐