Flutter三方库适配OpenHarmony【harmony_ui】导航类控件实战:标题栏、子页签、底部页签与轮播
前言
harmony_ui是 Material/Cupertino 风格的 Flutter 组件库,完整实现了HarmonyOS 设计语言,覆盖官方「控件概览」的 6 大类 42 个控件,并额外实现了沉浸光感材质与 UI Design Kit 增强能力。本系列按官方控件类别逐类实战,本篇是第 1 篇:导航类。
导航类是应用骨架的第一层:标题栏(OhosAppBar)定义页面头部,子页签(OhosTabBar)做页面内切换,底部页签(OhosNavigationBar)做全局导航,轮播(OhosSwiper)与导航点(OhosPageIndicator)承载首屏内容流。5 个控件全部对齐官方规范,且是沉浸光感落点最集中的类别——标题栏、底部页签的光感材质、动态模糊、光池效果都在这里。
本系列全部代码都在OpenHarmony 模拟器上直接运行验证(Flutter3.47.7-ohos-1.0.1+ DevEco Studio26.0.0 Release,截图环境:API 26,1280×2832)。环境搭建、依赖引入与构建步骤见文首「环境与版本」「安装与引入 harmony_ui」以及第九节;仓库地址:AtomGit / GitHub。
环境与版本
本文的示例与截图基于以下环境组合(2026-10 实测):
| 组件 | 版本 | 说明 |
|---|---|---|
| Flutter SDK(OH 适配版) | 3.47.7-ohos-1.0.1 | oh-flutter/flutter_flutter,oh-3.47-dev分支 |
| DevEco Studio | 26.0.0 Release | 提供 hvigor / ohpm / hdc / JBR 等工具链 |
| OpenHarmony SDK / API | API 26(26.0.0) | 模拟器与 SDK 均为 API 26 |
| 运行设备 | OpenHarmony 模拟器 | API 26,1280×2832 |
环境搭建(分叉获取、DevEco Studio 与 SDK 配置、模拟器创建)请按官方指导操作:OpenHarmony-flutter 环境搭建指导。
harmony_ui是纯 Dart/Flutter 组件库,不依赖 ohos 平台通道;在官方 Flutter SDK 上也能运行(用于跨平台预览)。只有跑example/ohos工程、构建 HAP 时才需要上面的 OH 适配版 SDK。
安装与引入 harmony_ui
harmony_ui已发布到 pub.dev,当前最新版本是0.3.0。在应用工程的pubspec.yaml中声明:
dependencies:flutter:sdk:flutterharmony_ui:^0.3.0然后拉取依赖:
fvm flutter pub get如果团队需要固定到仓库的某个提交(例如使用尚未发版的修复),改用 git 依赖:
dependencies:harmony_ui:git:url:https://atomgit.com/oh-flutter/harmony_ui.gitref:v0.3.0# 固定 tag;写 main 则跟随最新提交fvm flutter pub getpub.dev 与 git 两种方式二选一,不要同时声明。CI 中建议固定 tag(如
v0.3.0)而不是main,避免构建结果随上游漂移。harmony_ui目前只依赖qr一个三方包,ohos_icons是可选配套图标包,不引入也不影响组件使用。
一、导航类总览
官方「导航类」共 5 个控件,harmony_ui实现如下:
| 官方控件 | 实现 | 关键特性 |
|---|---|---|
| 标题栏 | OhosAppBar | 沉浸光感、动态模糊滚动效果、自动返回键 |
| 子页签 | OhosTabBar | 下划线 24×3vp / 胶囊两种形态、分割线跟手 |
| 底部页签 | OhosNavigationBar | 平铺 48vp / 悬浮 56vp、光池跟随、角标 |
| 导航点 | OhosPageIndicator | 轮播指示点,支持自定义颜色尺寸 |
| 轮播 | OhosSwiper | 自动播放、循环、内置指示点 |
使用导航类组件前,先用OhosTheme包一层应用根节点,所有颜色走主题 Token:
import'package:flutter/material.dart';import'package:harmony_ui/harmony_ui.dart';voidmain()=>runApp(constMyApp());classMyAppextendsStatelessWidget{constMyApp({super.key});@overrideWidgetbuild(BuildContextcontext){returnMaterialApp(home:OhosTheme(data:OhosThemeData.light(),// 或 OhosThemeData.dark()child:constHomePage(),),);}}二、标题栏 OhosAppBar
2.1 基础结构
OhosAppBar是PreferredSizeWidget,可直接传给OhosScaffold.appBar。高度默认56vp,title/leading/actions三区结构:
OhosScaffold(appBar:OhosAppBar(title:constText('设置'),actions:[OhosIconButton(icon:constIcon(Icons.search),onPressed:_onSearch),OhosIconButton(icon:constIcon(Icons.more_horiz),onPressed:_onMore),],),body:constMyBody(),)title:任意 Widget,通常用OhosText(标题字阶);leading:左侧区域,不传且页面可pop时自动插入返回键(automaticallyImplyLeading,默认 true);actions:右侧图标按钮列表,推荐 2-3 个,图标 24×24vp;elevation默认 0,鸿蒙风格标题栏不做投影分层,层次交给光感材质。
2.2 自定义高度与背景
height/backgroundColor/scrolledBackgroundColor都开放。沉浸式页面(内容延伸到标题栏后面)把背景设为透明:
OhosAppBar(height:64,backgroundColor:Colors.transparent,title:constOhosText('首页',level:OhosTextLevel.headlineMedium),)注意:
OhosScaffold内部把OhosAppBar与body按 Column 布局(v0.1.0 之前是 Stack 叠加导致内容被遮挡,已修复)。要做"内容穿透标题栏"的沉浸式效果,用scrollEffect动态模糊(见 3.2 节),而不是自己改 Scaffold 布局。
三、沉浸光感标题栏
3.1 光感材质 lightMaterial
打开lightMaterial: true,标题栏背景由不透明色替换为ULTRA_THIN 光感材质(8vp sigma 模糊 + 表面填充 + 顶部渐变淡出),悬浮在内容之上的"薄纱"效果:
OhosAppBar(lightMaterial:true,// 默认档位 ultraThinlightLevel:OhosLightMaterialLevel.ultraThin,// 可显式指定五档之一title:constText('首页'),actions:const[OhosIconButton(icon:Icon(Icons.more_horiz),onPressed:null),],)3.2 动态模糊 scrollEffect
scrollEffect是 UI Design Kit「动态模糊标题栏」能力的实现:内容穿透标题栏滚动,滚动位移进入blurEffectiveStartOffset ~ blurEffectiveEndOffset区间后,模糊背板按进度淡入。三种效果类型:
OhosAppBar(backgroundColor:Colors.transparent,title:constText('首页'),scrollController:_scroller,scrollEffect:constOhosAppBarScrollEffectOptions(effect:OhosAppBarScrollEffectType.commonBlur,blurEffectiveStartOffset:0,// 开始产生模糊的偏移blurEffectiveEndOffset:60,// 模糊达到满值的偏移blurSigma:10,// 模糊强度),scrolledBackgroundColor:Colors.white,)| 效果类型 | 行为 | 适用场景 |
|---|---|---|
commonBlur | 进入区间后常显模糊背板 | 常规内容流页面 |
transitionBlur | 模糊随滚动进度连续变化 | 沉浸式首屏 |
gradientBlur | 模糊 + 渐变蒙层叠加 | 大图头部页面 |
动态模糊标题栏在模拟器上的实机效果(滚动后背板淡入):
动态模糊标题栏:内容穿透滚动,进入阈值区间后commonBlur背板淡入
四、子页签 OhosTabBar
4.1 下划线式
OhosTabBar与 Flutter 的TabBar一样需要配合TabController/DefaultTabController使用,tabs传List<Widget>。下划线式(默认)的指示条严格对齐官方规范:24×3vp 品牌色:
DefaultTabController(length:3,child:Scaffold(body:NestedScrollView(headerSliverBuilder:(_,__)=>[SliverToBoxAdapter(child:OhosTabBar(tabs:const[Text('推荐'),Text('热榜'),Text('关注')],type:OhosTabBarType.underline,// 默认值,可省略),),],body:constTabBarView(children:[Center(child:Text('推荐页')),Center(child:Text('热榜页')),Center(child:Text('关注页'))],),),),)- 页签可滚动:
isScrollable: true(页签数量多时不换行、横向滑动); - 指示条颜色:
indicatorColor默认取主题品牌色#0A59F7。
4.2 胶囊式
胶囊式(capsule)激活项品牌色实底、未激活项comp_background_gray灰底,对齐官方子页签规范:
OhosTabBar(tabs:const[Text('日'),Text('周'),Text('月')],type:OhosTabBarType.capsule,height:40,)多选/筛选场景用OhosChipGroup(胶囊组合),间距默认 8vp(官方建议"不宜过大"):
OhosChipGroup(items:const<OhosChipItem>[OhosChipItem(label:Text('全部')),OhosChipItem(label:Text('进行中')),OhosChipItem(label:Text('已完成')),],multiple:true,// 多选模式selectedIndexes:_selected,// 已选索引集合onSelectionChanged:(Set<int>v)=>setState(()=>_selected=v),)导航类组件整体效果(沉浸光感标题栏 + 子页签 + ChipGroup + 底部页签):
导航类:顶部沉浸光感标题栏,中部下划线 + 胶囊子页签与 ChipGroup,底部平铺/悬浮页签
胶囊子页签 + ChipGroup 多选实机效果:
胶囊式子页签:激活项品牌色实底、未激活灰底;ChipGroup 多选筛选
五、子页签分割线(divider 三模式)
OhosTabBar通过divider(OhosTabBarDividerOptions)控制页签栏下方的分割线,三种模式:
| 模式 | 行为 |
|---|---|
OhosTabBarDividerMode.visible | 常显 |
OhosTabBarDividerMode.none | 常隐 |
OhosTabBarDividerMode.followScroll | 跟手:内容下滑淡入、回顶淡出 |
OhosTabBar(tabs:const[Text('推荐'),Text('热榜'),Text('关注')],divider:constOhosTabBarDividerOptions(mode:OhosTabBarDividerMode.followScroll,followStartOffset:0,// 开始淡入的滚动偏移followEndOffset:20,// 淡入完成的滚动偏移strokeWidth:1,),scrollController:_scroller,// followScroll 模式必须提供)分割线实机效果(visible常显模式):
子页签分割线:常显 / 常隐 / 跟手三种模式
提示:分割线颜色默认取主题
font_fourth(20% 黑),可用divider.color覆盖;startMargin/endMargin可让分割线两端缩进,与内容边距对齐。
六、底部页签 OhosNavigationBar
6.1 平铺式与悬浮式
OhosNavigationBar对齐官方底部页签规范:平铺式高48vp通栏,悬浮式高56vp圆角悬浮条;激活项用 20% 品牌色(comp_emphasize_secondary)填充,图标 24×24vp,页签数量建议3-5 个:
| 形态 | 默认高度 | 外观 | 典型场景 |
|---|---|---|---|
tile(平铺,默认) | 48vp | 通栏,无投影 | 标准应用 |
float(悬浮) | 56vp | 圆角悬浮条 + 投影 | 配合沉浸光感 |
// 平铺式OhosNavigationBar(currentIndex:_index,onDestinationSelected:(int i)=>setState(()=>_index=i),destinations:const[OhosNavigationDestination(icon:Icon(Icons.home_outlined),label:'首页'),OhosNavigationDestination(icon:Icon(Icons.square_grid_2x2),label:'组件'),OhosNavigationDestination(icon:Icon(Icons.person_outline),label:'我的'),],)6.2 双图标与角标
每个页签可以配置selectedIcon(选中态图标,不传则用icon)与badge(图标角标,OhosBadge数字或红点):
OhosNavigationDestination(icon:constIcon(Icons.person_outline),selectedIcon:constIcon(Icons.person_filled),label:'我的',badge:constOhosBadge(count:5),// 数字角标;不传 count 为红点)七、光感底部页签与光池
悬浮式 +lightMaterial: true是导航类的光感重头戏:THIN 材质(16vp sigma)悬浮条,彩色光池跟随选中项移动,按压时指尖出现光晕:
OhosNavigationBar(type:OhosNavigationBarType.float,lightMaterial:true,lightLevel:OhosLightMaterialLevel.thin,// 悬浮式默认档位glow:true,// 光池跟随选中项enablePressGlow:true,// 按压触发指尖光斑currentIndex:_index,onDestinationSelected:(int i)=>setState(()=>_index=i),destinations:destinations,)- 光池移动带动画过渡,切换页签时光晕平滑滑动而非瞬移;
- 按压光斑抬手后自动淡出,与
OhosGeometry.spring(90ms)曲线一致; - 光池配色来自
OhosLightPalette.glowColors,明暗主题自动适配。
平铺式与悬浮式底部页签实机对比:
底部页签:上为平铺式(48vp 通栏),下为悬浮式(56vp 圆角悬浮条 + 光感材质)
八、轮播 OhosSwiper 与导航点
8.1 OhosSwiper
OhosSwiper封装了PageView,内置自动播放、循环与指示点,是首屏 Banner 的主力:
OhosSwiper(height:180,autoPlay:true,autoPlayInterval:constDuration(seconds:4),loop:true,// 无限循环indicator:true,// 内置导航点(默认开启)clipRadius:BorderRadius.circular(16),onPageChanged:(int i)=>setState(()=>_page=i),children:[OhosImage(image:NetworkImage('https://example.com/a.png'),width:double.infinity),OhosImage(image:NetworkImage('https://example.com/b.png'),width:double.infinity),OhosImage(image:NetworkImage('https://example.com/c.png'),width:double.infinity),],)8.2 OhosPageIndicator
需要自定义指示点位置(如放在图片外)时,OhosSwiper(indicator: false)关掉内置点,用OhosPageIndicator单独渲染:
Column(children:[SizedBox(height:180,child:OhosSwiper(indicator:false,children:bannerImages),),constSizedBox(height:12),OhosPageIndicator(count:3,currentIndex:_page,dotSize:8,spacing:6,),],)activeColor/inactiveColor默认取主题色(品牌色 / 20% 黑);- 导航点尺寸默认 8vp、间距 6vp,与官方规范一致。
8.3 导航类常见坑
OhosTabBar不传 controller:既没有TabController也没有DefaultTabController祖先时会取不到控制器而报错,页签页务必用DefaultTabController(length:)包裹;- 轮播图片不圆角:
OhosImage自带圆角但OhosSwiper翻页切换时会露出直角边缘,给OhosSwiper(clipRadius:)传同样的圆角; - 悬浮页签被内容遮挡:
OhosNavigationBar(type: float)悬浮在内容之上,页面底部要留 56vp + 安全区的 padding,否则最后一行列表会被盖住; - 动态模糊不生效:
scrollEffect必须同时传scrollController且滚动容器真实使用它;backgroundColor设为不透明色时模糊被背景挡住,需设透明。
九、在鸿蒙模拟器上运行
导航类的所有效果(光感标题栏、动态模糊、光池)都在 gallery 示例应用的「导航」分类页可交互运行。最短运行路径:
安装3.47.7-ohos-1.0.1的 OH 适配版 SDK。该版本在仓库里是 git tag,按 tag 浅克隆到 fvm 版本目录后在工程内切换:
gitclone--depth1--branch3.47.7-ohos-1.0.1\https://atomgit.com/oh-flutter/flutter_flutter.git\~/fvm/versions/ohos/oh-3.47.7-releasecd<harmony_ui 仓库根目录>fvm use ohos/oh-3.47.7-release fvm flutter--version# 应输出 Flutter 3.47.7-ohos-1.0.1fvm 的
fvm install <alias>/<ref>只识别分支名,3.47.7-ohos-1.0.1是 tag,不能直接 install;按上面的方式 clone 到版本目录后fvm use即可。source env.sh加载 DevEco Studio26.0.0 Release的工具链(node / ohpm / hvigor / SDK toolchains);如果命令不可用,按文首的环境搭建指导检查DEVECO_SDK_HOME、JAVA_HOME与hdc;进入
example/:fvm flutter pub get && fvm flutter create --platforms ohos .;构建并安装到模拟器:
fvm flutter build hap--debug--no-codesign hdc list targets hdcinstall-rbuild/ohos/hap/entry-default-unsigned.hap hdc shell aa start-aEntryAbility-bcom.example.ohos_ui_example光感效果依赖
BackdropFilter,模拟器与真机渲染一致;若真机上模糊边缘有毛刺,优先检查设备 GPU 驱动,而非组件参数。
十、最佳实践
- 层级唯一:一个页面只有一个标题栏,
actions最多 3 个按钮,更多操作收进"更多"菜单; - 页签数量:底部页签 3-5 个,子页签 2-5 个,超出说明信息架构该拆页了;
- 光感节制:标题栏 + 悬浮底部页签同时开光感即可,弹层再叠加光感时注意同屏模糊层数量(≥3 层时低端机会掉帧);
- 动态模糊阈值:
blurEffectiveEndOffset建议 40-80vp,太小模糊感突兀,太大几乎看不到; - 选中态图标:底部页签务必配
selectedIcon(线性→面性切换),是官方视觉的重要组成部分; - 宽屏适配:≥840vp 窗口建议底部页签改侧边页签(
OhosSideBar,见系列第 7 篇增强类); - 导航与反馈联动:页签切换失败时配合
showOhosToast提示,切换成功保持静默——导航层"成功不打扰、失败有交代"。
十一、常见问题 FAQ
11.1flutter pub get找不到 harmony_ui?
先确认版本口径:pub.dev 上最新为0.3.0,pubspec.yaml写harmony_ui: ^0.3.0;若使用 git 依赖,检查url/ref是否可达,并确认没有同时声明 pub.dev 与 git 两份依赖。改完后执行fvm flutter clean && fvm flutter pub get;如果仍解析到旧版本,删除pubspec.lock与.dart_tool/后重试,不要手改pubspec.lock。
11.2 组件能编译,但运行时颜色/字阶与截图不一致?
通常是主题没有注入。OhosTheme要放在MaterialApp.home(或builder)里包住页面根节点,所有Ohos*组件都通过OhosTheme.of(context)读取 Token:
MaterialApp(home:OhosTheme(data:OhosThemeData.light(),// 或 OhosThemeData.dark()child:constHomePage(),),);只import 'package:harmony_ui/harmony_ui.dart'不会自动注入主题;未包OhosTheme时组件会回退到默认亮色 Token。
11.3 光感、动态模糊不生效?
按顺序检查:
OhosAppBar(scrollEffect: ...)是否同时传了scrollController,且滚动容器真的使用了这个 controller;backgroundColor是否被设成了不透明色——不透明背景会挡住BackdropFilter,需要透明或半透明;- 同一屏的模糊层是否过多(标题栏 + 悬浮页签 + 弹层同时开启)。层数越多开销越大,减少层数通常比调参数更有效。
11.4 真机上模糊边缘有毛刺、光感发灰?
模拟器与真机的光感效果基本一致;真机出现边缘毛刺时,优先排查设备 GPU 驱动与系统版本,而不是组件参数。可以在真机上把scatterScale调低、glowScale略降后再对比;深色模式如果过曝,glowScale建议保持在 0.8–0.9。
11.5 页签报No TabController,轮播图片露出直角?
这是组件约定,不是 bug:OhosTabBar需要有TabController或DefaultTabController祖先,页签页用DefaultTabController(length: ...)包住即可;OhosSwiper翻页时会裁切子组件的圆角,需要给OhosSwiper(clipRadius:)传与OhosImage相同的圆角。更多导航类细节见 8.3 节。
11.6 构建时报npm not found、hvigor不存在或DEVECO_SDK_HOME错误?
说明 DevEco 工具链没有进入 PATH。在仓库根目录执行source env.sh(按 DevEco Studio 26.0.0 Release 的默认安装路径配置),确认node、ohpm、hvigor、hdc都可执行;DEVECO_SDK_HOME必须指向.../Contents/sdk,而不是 DevEco 的安装根目录。首次构建前可用fvm flutter doctor -v检查 OHOS 设备识别情况。
11.7 模拟器安装失败,或提示签名错误?
OpenHarmony 模拟器接受未签名 debug HAP:
fvm flutter build hap--debug--no-codesign hdcinstall-rbuild/ohos/hap/entry-default-unsigned.hap如果要用flutter run热重载 / 断点调试,则需要签名配置:在 DevEco Studio 中打开example/ohos,勾选自动签名,或参考 oh-flutter 的自动签名方案。真机安装必须使用调试证书签名的 HAP。
11.8 能在官方 Flutter(Android / iOS / Web)上使用吗?
可以。harmony_ui是纯 Dart/Flutter 组件库,不依赖平台通道;差异主要在视觉:HarmonyOS 字体在非鸿蒙平台会回退到系统字体,光感与模糊的最终效果也取决于平台 GPU。跨平台预览用官方 Flutter 即可,鸿蒙模拟器/真机验证使用 3.47.7-ohos-1.0.1。
11.9 该用 pub.dev 的 0.3.0,还是仓库 main?
以 pub.dev 的0.3.0为准,它对应仓库 tagv0.3.0;main可能包含尚未发版的改动。生产项目固定版本号或 tag,尝鲜再跟main。升级前查看 CHANGELOG,确认是否有 API 变更。
总结
导航类 5 个控件是harmony_ui与官方规范对齐度最高的一组:标题栏 56vp、下划线指示条 24×3vp、平铺 48vp / 悬浮 56vp 底部页签,数字都来自官方文档,不是拍脑袋调的。加上沉浸光感标题栏、动态模糊与光池跟随,导航层就能达到"以假乱真"的鸿蒙质感。
下一篇进入展示类:文本字阶、图片、进度条、徽标、索引条、二维码等 13 个控件逐个拆解。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- harmony_ui 仓库(AtomGit):https://atomgit.com/oh-flutter/harmony_ui
- harmony_ui 仓库(GitHub):https://github.com/shaohushuo/harmony_ui
- harmony_ui pub.dev 发布页:https://pub.dev/packages/harmony_ui
- Flutter OH 适配版(3.47.7-ohos-1.0.1):https://atomgit.com/oh-flutter/flutter_flutter
- Flutter OH 环境搭建指导:https://atomgit.com/oh-flutter/flutter_samples/blob/master/ohos/docs/03_environment/OpenHarmony-flutter%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%AF%BC.md
- DevEco Studio 官方页面(本文使用 26.0.0 Release):https://developer.huawei.com/consumer/cn/deveco-studio/
- 配套图标包 ohos_icons:https://pub.dev/packages/ohos_icons
- 官方底部页签规范:https://developer.huawei.com/consumer/cn/doc/doccenter-ux-design/bottomtab-0000001956787789
- 官方子页签规范:https://developer.huawei.com/consumer/cn/doc/doccenter-ux-design/chipsgroup-0000001929788350
- 官方沉浸光感规范:https://developer.huawei.com/consumer/cn/doc/doccenter-ux-design/immersivelight-0000002612101053
- fvm 多版本管理:https://fvm.app