鸿蒙开发之多样化底部导航栏01——默认导航栏
·
一、前言:
在移动APP开发中,底部导航栏是一种常见的用户界面设计元素,主要用于提供快速访问应用核心功能的入口,绝大部分APP都会设计底部导航栏,只有少数APP没有或没必要用到。它的作用和设计要点如下:
1、核心作用
快速导航
- 允许用户一键切换应用的主要模块(如首页、发布和个人中心等),避免频繁返回上级页面。
-
适合功能复杂、模块划分清晰的应用(如社交、电商、工具类APP)。
明确核心功能
-
通过图标和文字标签突出展示最重要的3-5个功能入口,降低用户学习成本。
保持操作一致性
-
固定显示在屏幕底部,符合用户习惯,减少误操作。
-
HarmonyOS在“一次开发,多端部署”的特性下,建议大屏时把导航栏放在左侧,这样右侧可用面积更好。
提升用户体验
-
避免用户迷失在多层页面中,随时可返回核心页面。
2、设计规范
数量控制:
-
通常放置3-5个常用核心标签,过多会显得拥挤。
视觉反馈:
-
选中态(高亮颜色、图标变化)明确当前所在模块。
图标+文字:
-
纯图标易歧义,需搭配简短标签(如“首页”“我的”);个别页签可以不用加文字说明(如“发布”),而且这个按钮可以更加丰富界面。
二、正题:
前言说完,也该进入我们今天的正题了。这一节,我们将从默认样式讲起,这也是大部分有底部导航栏的APP使用的样式。新建项目后,我们只需要在entry/src/main/ets/pages/Index.ets或MainPage.ets 里面加相关代码便可实现导航栏功能
预览效果:
1、核心组件:
- Tabs
2、核心代码:
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) { TabContent() { ... }.tabBar(...) ... }.vertical(false)
1)Tabs里面的属性barPosition需要选择:BarPosition.End并且vertical选择false,这样该样式才会置于底部并且是横向的。
2)一个Tabs里面可以包含多个TabContent(),但是最好不超过5个。
代码解析:
// 选择的页签下标
@State selectedIndex: number = 0;
// 当前页签下标
@State currentIndex: number = 0;
// 页签控制器
private controller: TabsController = new TabsController();
// 自定义函数,方便.tabBar()函数复用
@Builder
tabBuilder(title: string, targetIndex: number, selectImg: ResourceStr, unselectImg: ResourceStr) {
Column() {
Image(this.selectedIndex === targetIndex ? selectImg : unselectImg)
.width(24)
.height(24)
.margin({ bottom: 4 })
.objectFit(ImageFit.Contain)
Text(title).fontColor(this.selectedIndex === targetIndex ? '#1296db' : '#707070')
}.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
}
// onChange()当点击页签时,获取并改变下标值
Tabs() {
...
}
.onChange((index: number) => {
this.currentIndex = index;
this.selectedIndex = index;
})
三、完整代码:
@Entry
@Component
struct Index {
@State selectedIndex: number = 0;
@State currentIndex: number = 0;
private controller: TabsController = new TabsController();
@Builder
tabBuilder(title: string, targetIndex: number, selectImg: ResourceStr, unselectImg: ResourceStr) {
Column() {
Image(this.selectedIndex === targetIndex ? selectImg : unselectImg)
.width(24)
.height(24)
.margin({ bottom: 4 })
.objectFit(ImageFit.Contain)
Text(title).fontColor(this.selectedIndex === targetIndex ? '#1296db' : '#707070')
}.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
}
build() {
Column() {
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) {
TabContent() {
Column() {
Text('首页的内容')
.fontSize(30)
}
.width('100%')
.height('100%')
.backgroundColor('#00CB87')
.justifyContent(FlexAlign.Center)
}.tabBar(this.tabBuilder('首页', 0, $r('app.media.ic_tabbar_home_on'), $r('app.media.ic_tabbar_home_off')))
TabContent() {
Column() {
Text('发布的内容')
.fontSize(30)
}
.width('100%')
.height('100%')
.backgroundColor('#007DFF')
.justifyContent(FlexAlign.Center)
}
.tabBar(this.tabBuilder('发布', 1, $r('app.media.ic_tabbar_publish_on'), $r('app.media.ic_tabbar_publish_off')))
TabContent() {
Column() {
Text('我的内容')
.fontSize(30)
}
.width('100%')
.height('100%')
.backgroundColor('#E67C92')
.justifyContent(FlexAlign.Center)
}
.tabBar(this.tabBuilder('我的', 2, $r('app.media.ic_tabbar_my_on'), $r('app.media.ic_tabbar_my_off')))
}
.barWidth(360)
.barHeight(60)
.vertical(false)
.barMode(BarMode.Fixed)
.animationDuration(0)
.backgroundColor('#F1F3F5')
.onChange((index: number) => {
this.currentIndex = index;
this.selectedIndex = index;
})
}
.width('100%')
.height('100%')
}
}
更多推荐
所有评论(0)