 作者简介,愚公搬代码 《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,51CTO博客专家等。 《近期荣誉》:2023年华为云十佳博主,2022年CSDN博客之星TOP2,2022年华为云十佳博主等。 《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。 欢迎 点赞✍评论⭐收藏

文章目录

一、Tabs1.基本布局2.导航位置曆2.1 底部导航曆2.2 顶部导航曆2.3 侧边导航

3.导航效果曆3.1 限制导航栏的滑动切换曆3.2 固定导航栏曆3.3 滚动导航栏

4.自定义导航栏5.切换至指定页签6.滑动切换导航栏

感谢:给读者的一封信

一、Tabs

Tabs组件是一种常见的用户界面(UI)组件,它是一个可以容纳多个选项卡的容器组件。每个选项卡通常包含一个面板和一个标签,用户可以通过点击标签来切换面板。Tabs组件通常用于展示多个相关但又不需要同时展示的数据集合或功能集合,以提高页面的可维护性和可用性。

Tabs组件的主要功能包括:

切换选项卡:用户可以通过点击标签来切换显示面板。激活状态:当前选中的标签会呈现激活状态,以便用户清楚地知道他们当前所在的选项卡。自定义选项卡内容:用户可以通过自定义选项卡内容(例如图片、文本、图标等)来增强页面的可读性和可用性。加载延迟:如果页面需要加载大量数据或内容,Tabs组件可以通过延迟加载未激活的面板来提升页面性能。

1.基本布局

Tabs使用花括号包裹TabContent,每一个TabContent对应一个tabBar

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs() {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

2.导航位置

曆2.1 底部导航

BarPosition.End设置底部导航

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs({ barPosition: BarPosition.End }) {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

曆2.2 顶部导航

BarPosition.Start设置顶部导航

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs({ barPosition: BarPosition.Start }) {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

曆2.3 侧边导航

实现侧边导航栏需要设置Tabs的属性vertical为true

vertical为false时,tabbar宽度会默认撑满屏幕的宽度,需要设置barWidth为合适值。 vertical为true时,tabbar的高度会默认实际内容高度,需要设置barHeight为合适值。

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs({ barPosition: BarPosition.Start }) {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}.vertical(true)

.barWidth(100)

.barHeight(200)

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

3.导航效果

曆3.1 限制导航栏的滑动切换

在某些需要进行多级分类的页面上,如同时存在底部导航栏和顶部导航栏时,因为默认情况下导航栏都支持滑动切换,所以当底部导航栏的滑动效果与顶部导航栏出现冲突时,需要限制底部导航栏的滑动,以避免给用户带来不好的体验。

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs({ barPosition: BarPosition.End }) {

TabContent(){

Column(){

Tabs({ barPosition: BarPosition.Start }) {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}.vertical(true)

.barWidth(100)

.barHeight(200)

}

.backgroundColor('#ff08a8f1')

.width('100%')

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}

.scrollable(false)

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

曆3.2 固定导航栏

Tabs的属性barMode是控制导航栏是否可以滚动,默认值为Fixed

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs({ barPosition: BarPosition.End }) {

TabContent(){

Column(){

Tabs({ barPosition: BarPosition.Start }) {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}.vertical(true)

.barWidth(100)

.barHeight(200)

}

.backgroundColor('#ff08a8f1')

.width('100%')

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}

.scrollable(false)

.barMode(BarMode.Fixed)

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

曆3.3 滚动导航栏

滚动导航栏需要设置Tabs组件的barMode属性,默认情况下其值为Fixed,表示为固定导航栏,设置为Scrollable即可设置为可滚动导航栏

@Entry

@Component

struct NavigationExample {

private arr: number[] = [1, 2, 3];

build() {

Column() {

Tabs({ barPosition: BarPosition.End }) {

TabContent(){

Column(){

Tabs({ barPosition: BarPosition.Start }) {

TabContent() {

Text('首页的内容').fontSize(30)

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}.vertical(true)

.barWidth(100)

.barHeight(200)

}

.backgroundColor('#ff08a8f1')

.width('100%')

}

.tabBar('首页')

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

TabContent() {

Text('推荐的内容').fontSize(30)

}

.tabBar('推荐')

TabContent() {

Text('发现的内容').fontSize(30)

}

.tabBar('发现')

TabContent() {

Text('我的内容').fontSize(30)

}

.tabBar("我的")

}

.scrollable(false)

.barMode(BarMode.Scrollable)

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

4.自定义导航栏

自定义导航栏是指在应用开发中,开发者使用自己定制的视图代替系统自带的导航栏,以实现更加自由、灵活和符合应用风格的导航栏。自定义导航栏可以包括各种 UI 元素,例如按钮、文本、图片、标签等,以满足不同应用的需求。自定义导航栏可以帮助应用创建独特的风格和品牌形象,提高用户体验和应用的可用性。

@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {

Column() {

Image(this.currentIndex === targetIndex ? selectedImg : normalImg)

.size({ width: 25, height: 25 })

Text(title)

.fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')

}

.width('100%')

.height(50)

.justifyContent(FlexAlign.Center)

}

TabContent() {

Column(){

Text('我的内容')

}

.width('100%')

.height('100%')

.backgroundColor('#007DFF')

}

.tabBar(this.TabBuilder('我的', 0, $r('app.media.mine_selected'), $r('app.media.mine_normal')))

5.切换至指定页签

要想切换特定的标签页,需要使用TabsController。TabsController是Tabs组件的控制器,它用于控制Tabs组件进行标签页的切换。使用TabsController的changeIndex方法,可以实现跳转到指定索引值对应的标签页内容。

@Entry

@Component

struct NavigationExample {

private tabsController : TabsController = new TabsController()

@State currentIndex:number = 0;

@Builder TabBuilder(title: string, targetIndex: number) {

Column() {

Text(title)

.fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')

}

.onClick(() => {

this.currentIndex = targetIndex;

this.tabsController.changeIndex(this.currentIndex);

})

}

build() {

Column() {

Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {

TabContent(){

Text('首页')

}.tabBar(this.TabBuilder('首页',0)).backgroundColor(Color.Black)

TabContent(){

Text('发现')

}.tabBar(this.TabBuilder('发现',1)).backgroundColor(Color.Blue)

TabContent(){

Text('推荐')

}.tabBar(this.TabBuilder('推荐',2)).backgroundColor(Color.Red)

TabContent(){

Text('我的')

}

.tabBar(this.TabBuilder('我的',3)).backgroundColor(Color.Pink)

}

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

6.滑动切换导航栏

在不使用自定义导航栏的情况下,Tabs组件会默认实现tabBar与TabContent的切换联动。然而,一旦使用了自定义导航栏,就需要使用TabsController来实现点击页签与页面内容的联动。但使用TabsController无法实现滑动页面时,页面内容对应页签的联动。也就是说,当用户滑动屏幕切换页面内容时,页签栏无法同步切换至对应的页签,这可能会影响用户的体验。

@Entry

@Component

struct NavigationExample {

private tabsController : TabsController = new TabsController()

@State currentIndex:number = 0;

@Builder TabBuilder(title: string, targetIndex: number) {

Column() {

Text(title)

.fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')

}

.onClick(() => {

this.currentIndex = targetIndex;

this.tabsController.changeIndex(this.currentIndex);

})

}

build() {

Column() {

Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {

TabContent(){

Text('首页')

}.tabBar(this.TabBuilder('首页',0)).backgroundColor(Color.Black)

TabContent(){

Text('发现')

}.tabBar(this.TabBuilder('发现',1)).backgroundColor(Color.Blue)

TabContent(){

Text('推荐')

}.tabBar(this.TabBuilder('推荐',2)).backgroundColor(Color.Red)

TabContent(){

Text('我的')

}

.tabBar(this.TabBuilder('我的',3)).backgroundColor(Color.Pink)

}.onChange((index) => {

this.currentIndex = index

})

}

.height('100%')

.width('100%')

.backgroundColor('#F1F3F5')

}

}

感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: