鸿蒙学习实战之路-Tabs标签页组件全攻略
默认的 TabBar 只有文字,不够美观。咱们可以自定义 TabBar,添加图标、调整样式,让它更符合咱们的设计需求~ 🎨咱们可以使用@Builder装饰器来创建自定义的 TabBar 组件,这样就能添加图片、调整布局了。TabBar 的 tabBar 属性支持两种类型:string 和 CustomBuilder。当我们需要自定义复杂的 TabBar 时,可以使用 CustomBuilder:
鸿蒙学习实战之路-Tabs 标签页组件全攻略 🥦
最近好多朋友问我:“鸿蒙里的页面切换怎么弄?就像微信底部那几个标签栏一样的效果”,别慌!今天咱们就来聊聊鸿蒙里的 Tabs 组件,这个组件可是实现页面分类切换的神器~ 😊
一、Tabs 组件是什么?
Tabs 组件是鸿蒙里的一个容器组件,当页面内容比较多时,可以用它来分类展示。比如咱们手机里常见的:
- 微信底部的"微信"“通讯录”“发现”“我”
- 淘宝首页的各种分类标签
- 新闻 App 顶部的"推荐"“热点”"财经"等
这些效果,用 Tabs 组件都能轻松实现!

二、Tabs 组件基础用法
咱们先从最简单的 Tabs 用法开始,就像学炒菜先学会开火一样~ 🔥
1. 核心结构
Tabs 组件的核心结构非常简单,主要由两部分组成:
Tabs():外层容器,包裹所有标签页TabContent():每个标签页的内容,需要配合.tabBar()设置标签文字
基础代码示例:
@Entry
@Component
struct TabsBasicDemo {
build() {
Tabs() { // 外层容器
TabContent() { // 第一个标签页
Text('首页内容')
.fontSize(30)
.textAlign(TextAlign.Center)
}
.tabBar('首页') // 设置标签文字
TabContent() { // 第二个标签页
Text('推荐内容')
.fontSize(30)
.textAlign(TextAlign.Center)
}
.tabBar('推荐')
TabContent() { // 第三个标签页
Text('发现内容')
.fontSize(30)
.textAlign(TextAlign.Center)
}
.tabBar('发现')
TabContent() { // 第四个标签页
Text('我的内容')
.fontSize(30)
.textAlign(TextAlign.Center)
}
.tabBar('我的')
}
}
}
运行这段代码,你就能看到一个简单的标签页切换效果啦!是不是超简单?
效果预览:

三、Tabs 组件常用属性
默认的 Tabs 已经能用了,但咱们还可以通过一些属性来调整它的外观和行为,就像给菜调味一样~ 😋
通过这些属性,我们可以实现各种不同的导航效果:

1. 垂直导航 & 导航位置
默认的 Tabs 是水平导航栏在顶部,咱们可以调整:
vertical:设置导航方向为水平或垂直barPosition:设置导航栏位置(开头/结尾)
代码示例:
@Entry
@Component
struct TabsAttributeDemo {
build() {
Tabs() {
TabContent() {
Text('首页内容')
.fontSize(30)
}
.tabBar('首页')
TabContent() {
Text('推荐内容')
.fontSize(30)
}
.tabBar('推荐')
TabContent() {
Text('发现内容')
.fontSize(30)
}
.tabBar('发现')
TabContent() {
Text('我的内容')
.fontSize(30)
}
.tabBar('我的')
}
.vertical(true) // 设置为垂直导航
.barPosition(BarPosition.End) // 导航栏在末尾
.scrollable(false) // 禁用滑动切换
.animationDuration(500) // 切换动画时长
}
}
2. 滚动导航栏
当标签太多,屏幕放不下时,咱们可以把导航栏设置为滚动的,这样就能容纳更多标签了~ 👇
效果预览:

代码示例:
@Entry
@Component
struct ScrollableTabsDemo {
// 定义多个标签标题
titles: string[] = ['首页', '关注', '热门', '军事', '体育', '八卦', '数码', '财经', '美食', '旅行']
build() {
Tabs() {
// 使用ForEach循环生成多个TabContent
ForEach(this.titles, (title: string) => {
TabContent() {
Text(title + '的内容')
.fontSize(30)
.textAlign(TextAlign.Center)
}
.tabBar(title)
})
}
.barMode(BarMode.Scrollable) // 设置为滚动导航栏
}
}
四、自定义 TabBar(重点!)
默认的 TabBar 只有文字,不够美观。咱们可以自定义 TabBar,添加图标、调整样式,让它更符合咱们的设计需求~ 🎨
1. 自定义 TabBar 外观
咱们可以使用@Builder装饰器来创建自定义的 TabBar 组件,这样就能添加图片、调整布局了。
TabBar 的 tabBar 属性支持两种类型:string 和 CustomBuilder。当我们需要自定义复杂的 TabBar 时,可以使用 CustomBuilder:

让咱们实现一个包含图标和文字的自定义 TabBar:
代码示例:
@Entry
@Component
struct CustomTabBarDemo {
build() {
Tabs() {
TabContent() {
Text('首页')
.fontSize(30)
}
// 使用自定义TabBar
.tabBar(this.tabBarBuilder($r('app.media.ic_tabbar_icon_0'), '首页'))
TabContent() {
Text('我的')
.fontSize(30)
}
.tabBar(this.tabBarBuilder($r('app.media.ic_tabbar_icon_3'), '我的'))
}
.barPosition(BarPosition.End) // 导航栏在底部
}
// 自定义TabBar的Builder函数
@Builder
tabBarBuilder(img: ResourceStr, text: string) {
Column() { // 垂直布局
Image(img) // 图标
.width(30)
.height(30)
Text(text) // 文字
.fontSize(12)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
2. 实现 TabBar 高亮效果
自定义 TabBar 后,默认的高亮效果就没有了,咱们需要自己实现。这时候就需要用到 Tabs 的事件和状态管理了~ ✨
效果预览:

核心思路:
- 用
@State变量保存当前选中的索引 - 在
onChange和onTabBarClick事件中更新索引 - 在自定义 TabBar 中根据索引切换高亮样式
代码示例:
@Entry
@Component
struct HighlightTabBarDemo {
// 保存当前选中的索引
@State selectedIndex: number = 0
build() {
Column() {
Tabs() {
TabContent() {
Text('首页内容')
.fontSize(30)
}
// 传递默认图标、高亮图标、文字和索引
.tabBar(this.tabBarBuilder($r('app.media.ic_tabbar_icon_0'), $r('app.media.ic_tabbar_icon_0_selected'), '首页', 0))
TabContent() {
Text('我的内容')
.fontSize(30)
}
.tabBar(this.tabBarBuilder($r('app.media.ic_tabbar_icon_3'), $r('app.media.ic_tabbar_icon_3_selected'), '我的', 1))
}
.layoutWeight(1)
.barPosition(BarPosition.End)
// 滑动切换时触发
.onChange((index) => {
this.selectedIndex = index
})
// 点击TabBar时触发
.onTabBarClick((index) => {
this.selectedIndex = index
})
}
}
// 自定义TabBar的Builder函数
@Builder
tabBarBuilder(img: ResourceStr, selectedImg: ResourceStr, text: string, index: number) {
Column() {
// 根据选中状态切换图片
Image(this.selectedIndex == index ? selectedImg : img)
.width(30)
.height(30)
// 根据选中状态切换文字颜色
Text(text)
.fontSize(12)
.fontColor(this.selectedIndex == index ? '#efc07e' : Color.Black)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
3. 优化 TabBar 参数(使用接口)
当自定义 TabBar 的参数越来越多时,直接传递多个参数容易出错。咱们可以使用接口来优化参数传递~ 📝
代码示例:
// 定义TabBar参数的接口
interface TabBarParams {
img: ResourceStr // 默认图标
selectedImg: ResourceStr // 高亮图标
text: string // 标签文字
index: number // 标签索引
}
@Entry
@Component
struct OptimizedTabBarDemo {
@State selectedIndex: number = 0
build() {
Column() {
Tabs() {
TabContent() {
Text('首页内容')
.fontSize(30)
}
// 使用对象传递参数
.tabBar(this.tabBarBuilder({
img: $r('app.media.ic_tabbar_icon_0'),
selectedImg: $r('app.media.ic_tabbar_icon_0_selected'),
text: '首页',
index: 0
}))
TabContent() {
Text('我的内容')
.fontSize(30)
}
.tabBar(this.tabBarBuilder({
img: $r('app.media.ic_tabbar_icon_3'),
selectedImg: $r('app.media.ic_tabbar_icon_3_selected'),
text: '我的',
index: 1
}))
}
.layoutWeight(1)
.barPosition(BarPosition.End)
.onChange((index) => {
this.selectedIndex = index
})
.onTabBarClick((index) => {
this.selectedIndex = index
})
}
}
// 使用接口类型的参数
@Builder
tabBarBuilder(params: TabBarParams) {
Column() {
Image(this.selectedIndex == params.index ? params.selectedImg : params.img)
.width(30)
.height(30)
Text(params.text)
.fontSize(12)
.fontColor(this.selectedIndex == params.index ? '#efc07e' : Color.Black)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
五、实战案例:小米有品底部导航
咱们来做一个实战案例,模仿小米有品的底部导航效果,这个效果在很多 App 里都很常见哦~ 🛒
效果预览:

切换效果:

需求分析
- 底部有 5 个标签:首页、分类、中间特殊按钮、购物车、我的
- 中间按钮是特殊样式(突出显示)
- 选中时图标和文字会高亮
代码实现
// 定义TabBar参数接口
interface XMTabBarParams {
img: ResourceStr
selectedImg: ResourceStr
text: string
index: number
}
@Entry
@Component
struct XiaomiYoupinDemo {
// 保存当前选中的索引
@State selectedIndex: number = 0
build() {
Column() {
Tabs() {
// 首页
TabContent() {
Image($r('app.media.ic_xiaomi_content_00'))
.width('100%')
.height('100%')
}
.tabBar(this.tabBarBuilder({
img: $r('app.media.ic_tabbar_icon_0'),
selectedImg: $r('app.media.ic_tabbar_icon_0_selected'),
text: '首页',
index: 0
}))
// 分类
TabContent() {
Image($r('app.media.ic_xiaomi_content_01'))
.width('100%')
.height('100%')
}
.tabBar(this.tabBarBuilder({
img: $r('app.media.ic_tabbar_icon_1'),
selectedImg: $r('app.media.ic_tabbar_icon_1_selected'),
text: '分类',
index: 1
}))
// 中间特殊按钮
TabContent() {
Image($r('app.media.ic_xiaomi_content_02'))
.width('100%')
.height('100%')
}
.tabBar(this.centerTabBarBuilder()) // 使用特殊的TabBar
// 购物车
TabContent() {
Image($r('app.media.ic_xiaomi_content_03'))
.width('100%')
.height('100%')
}
.tabBar(this.tabBarBuilder({
img: $r('app.media.ic_tabbar_icon_2'),
selectedImg: $r('app.media.ic_tabbar_icon_2_selected'),
text: '购物车',
index: 3 // 注意这里的索引是3,因为中间按钮占用了索引2
}))
// 我的
TabContent() {
Image($r('app.media.ic_xiaomi_content_04'))
.width('100%')
.height('100%')
}
.tabBar(this.tabBarBuilder({
img: $r('app.media.ic_tabbar_icon_3'),
selectedImg: $r('app.media.ic_tabbar_icon_3_selected'),
text: '我的',
index: 4
}))
}
.layoutWeight(1)
.barPosition(BarPosition.End)
.onChange((index) => {
this.selectedIndex = index
})
.onTabBarClick((index) => {
this.selectedIndex = index
})
}
}
// 普通TabBar的Builder
@Builder
tabBarBuilder(params: XMTabBarParams) {
Column({ space: 5 }) {
Image(this.selectedIndex == params.index ? params.selectedImg : params.img)
.width(30)
.height(30)
Text(params.text)
.fontSize(12)
.fontColor(this.selectedIndex == params.index ? '#efc07e' : Color.Black)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
// 中间特殊TabBar的Builder
@Builder
centerTabBarBuilder() {
Image($r('app.media.ic_xiaomi_center_tabBar'))
.width(60)
.height(60)
.borderRadius(30)
}
}
六、Tabs 组件的事件
Tabs 组件提供了两个常用事件,咱们可以用来监听标签切换:
| 事件名 | 功能描述 |
|---|---|
onChange(index: number) |
标签切换后触发(滑动或点击都触发) |
onTabBarClick(index: number) |
点击标签栏时触发 |
代码示例:
@Entry
@Component
struct TabsEventsDemo {
build() {
Tabs() {
TabContent() {
Text('首页')
.fontSize(30)
}
.tabBar('首页')
TabContent() {
Text('推荐')
.fontSize(30)
}
.tabBar('推荐')
}
.onChange((index) => {
console.log('标签切换到了:' + index)
})
.onTabBarClick((index) => {
console.log('点击了标签:' + index)
})
}
}
🥦 西兰花小贴士
- TabContent 的子组件:每个 TabContent 只能有一个直接子组件,如果需要多个子组件,要使用容器组件(如 Column、Row)包裹
- 导航栏位置:设置
barPosition(BarPosition.End)可以让导航栏在底部,适合做 App 的主导航 - 滑动切换:可以通过
scrollable(false)禁用滑动切换,只能通过点击标签切换 - 动画时长:使用
animationDuration()可以调整标签切换的动画时长 - 自定义 TabBar:自定义 TabBar 后,需要自己实现高亮效果,记得同时监听
onChange和onTabBarClick事件
📚 官方文档
如果想了解更多关于 Tabs 组件的内容,可以查看官方文档:
鸿蒙 Tabs 组件官方文档
总结
今天咱们学习了 Tabs 组件的全部用法,从基础用法到自定义 TabBar,再到实战案例,是不是感觉已经掌握了这个组件的精髓?
Tabs 组件就像一个分类收纳盒,把不同的内容整理得井井有条,让用户能快速找到自己想要的内容。在实际开发中,它可是咱们的得力助手~ 🛠️
我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦
更多推荐



所有评论(0)