智能客服
你问我答,随时在线为你解决问题

























为了提升用户体验和界面功能性,开发者往往会在TabBar页签栏中添加其他组件(如按钮、图标、通知角标等),以下是在TabBar两侧添加其他组件的常见写法:
本文将基于上述场景,逐一阐述其具体实现方式。
实现方案 | 方案描述 | 适用场景 |
|---|---|---|
方案一 | TabBar叠加overlay浮层效果。 | 实现简单,无需自定义TabBar;且使用overlay可以实现动态显示而不必重新渲染整个TabBar。 |
方案二 | 利用Stack组件,在自定义TabBar上堆叠其他组件。 | 当需要在TabBar的特定位置添加固定的功能按钮或图标时,Stack组件可以方便地实现这一需求,而不会影响TabBar的其他部分。 |
方案三 | 使用Row组件自定义行内布局。 | 当需要完全自定义TabBar的布局时,Row组件可以提供更大的灵活性。 |
在当前Tabs组件上,可以叠加按钮或图标作为TabBar的浮层,达到页签栏添加其他组件的效果,原理如下图:

实现步骤如下:
实现代码如下:
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct TabBarOverlay {
tabArr: string[] = ['首页', '商城', '账号'];
@State currentIndex: number = 0;
@Builder
tabBuilder(index: number, name: string) {
Column() {
Text(name)
.width('74vp')
.height('36vp')
.textAlign(TextAlign.Center)
.textVerticalAlign(TextVerticalAlign.CENTER)
.fontColor(this.currentIndex === index ? '#e6000000' : '#99000000')
.fontSize(14)
.fontWeight(this.currentIndex === index ? 500 : 400)
.lineHeight(40)
.backgroundColor(this.currentIndex === index ? Color.White : '#00000000')
.borderRadius('50vp');
}
.backgroundColor('#0d000000')
.borderRadius({
topLeft: index === 0 ? 50 : 0,
bottomLeft: index === 0 ? 50 : 0,
topRight: index === 2 ? 50 : 0,
bottomRight: index === 2 ? 50 : 0
})
.margin({ top: 5 })
.padding(2);
}
// 设置浮层
@Builder
tabOverlay() {
Flex({
justifyContent: FlexAlign.SpaceBetween,
direction: FlexDirection.Row,
alignItems: ItemAlign.Center
}) {
Image($r('sys.media.ohos_ic_public_arrow_left')) // 开发者可根据需求更换其它图片资源
.width(30)
.height(30)
.onClick(() => {
try {
this.getUIContext().getPromptAction().showToast({
message: '触发开发者自定义事件',
duration: 2000,
showMode: promptAction.ToastShowMode.TOP_MOST,
bottom: 85
});
} catch (error) {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`showToast args error code is ${code}, message is ${message}`);
}
});
Image($r('sys.media.ohos_ic_public_more')) // 开发者可根据需求更换其它图片资源
.width(30)
.height(30)
.onClick(() => {
try {
this.getUIContext().getPromptAction().showToast({
message: '触发开发者自定义事件',
duration: 2000,
showMode: promptAction.ToastShowMode.TOP_MOST,
bottom: 85
});
} catch (error) {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`showToast args error code is ${code}, message is ${message}.`);
}
});
}
.padding({ left: 20, right: 20 })
.width('100%')
.height(56)
.hitTestBehavior(HitTestMode.Transparent); // 配置浮层不阻塞交互
}
build() {
Column() {
Tabs() {
ForEach(this.tabArr, (item: string, index: number) => {
TabContent() {
Column()
.width('100%')
.height('100%');
}
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
.backgroundColor('#FFFFFF')
.tabBar(this.tabBuilder(index, item));
});
}
.width('100%')
.height('100%')
.barMode(BarMode.Scrollable)
.barWidth(250)
.overlay(this.tabOverlay(), { align: Alignment.Top })
.onChange((index: number) => {
this.currentIndex = index;
});
};
}
} 实现效果如下:

利用堆叠容器,在原本的TabBar基础上放置其他组件,原理如下图:

实现步骤如下:
实现代码如下:
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct TabBarStack {
@State selectedIndex: number = 0;
private controller: TabsController = new TabsController();
@Builder
tabBuilder(index: number, name: string) {
Column() {
Text(name)
.width('80vp')
.height('36vp')
.textAlign(TextAlign.Center)
.textVerticalAlign(TextVerticalAlign.CENTER)
.fontColor(this.selectedIndex === index ? '#e6000000' : '#99000000')
.fontSize(14)
.fontWeight(this.selectedIndex === index ? 500 : 400)
.lineHeight(40)
.backgroundColor(this.selectedIndex === index ? Color.White : '#00000000')
.borderRadius('50vp');
}
.backgroundColor('#0d000000')
.borderRadius({
topLeft: index === 0 ? 50 : 0,
bottomLeft: index === 0 ? 50 : 0,
topRight: index === 2 ? 50 : 0,
bottomRight: index === 2 ? 50 : 0
})
.margin({ top: 5 })
.padding(2)
.onClick(() => {
this.controller.changeIndex(index);
this.selectedIndex = index;
});
}
build() {
Stack({ alignContent: Alignment.TopStart }) {
Image($r('sys.media.ohos_ic_public_arrow_left')) // 开发者自定义图片资源
.width(32)
.height(32)
.offset({ top: 15, left: 16 })
.zIndex(1)
.onClick(() => {
try {
this.getUIContext().getPromptAction().showToast({
message: '触发开发者自定义事件',
duration: 2000,
showMode: promptAction.ToastShowMode.TOP_MOST,
bottom: 85
});
} catch (error) {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`showToast args error code is ${code}, message is ${message}`);
}
});
Tabs({ controller: this.controller }) {
TabContent() {
Column()
.width('100%')
.height('100%');
}.tabBar(this.tabBuilder(0, '首页'))
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
.backgroundColor('#FFFFFF');
TabContent() {
Column()
.width('100%')
.height('100%');
}
.tabBar(this.tabBuilder(1, '商城'))
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
.backgroundColor('#FFFFFF');
TabContent() {
Column()
.width('100%')
.height('100%');
}
.tabBar(this.tabBuilder(2, '我的'))
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
.backgroundColor('#FFFFFF');
}
.barWidth(250)
.onAnimationStart((index: number, targetIndex: number) => {
if (index === targetIndex) {
return;
}
this.selectedIndex = targetIndex;
})
// 设置Tabs层级小于Image组件
.zIndex(-1);
}.width('100%').height('100%');
}
} 实现效果如下:

更丰富的实现效果请参考:可滚动Tabs页签栏+更多按钮。
通过Row组件,自行设置TabBar行内组件的组成效果,原理如下图:

实现步骤如下:
实现代码如下:
import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct TabBarRow {
tabName: Array<string> = ['首页', '商城', '详情'];
fontColor: string = '#000000';
@State selectedIndex: number = 0;
private controller: TabsController = new TabsController();
@Builder
tabBuilder(index: number, name: string) {
Column() {
Column() {
Text(name)
.width('80vp')
.height('36vp')
.textAlign(TextAlign.Center)
.textVerticalAlign(TextVerticalAlign.CENTER)
.fontColor(this.selectedIndex === index ? '#e6000000' : '#99000000')
.fontSize(14)
.fontWeight(this.selectedIndex === index ? 500 : 400)
.lineHeight(40)
.backgroundColor(this.selectedIndex === index ? Color.White : '#00000000')
.borderRadius('50vp');
}
.backgroundColor('#0d000000')
.borderRadius({
topLeft: index === 0 ? 50 : 0,
bottomLeft: index === 0 ? 50 : 0,
topRight: index === 2 ? 50 : 0,
bottomRight: index === 2 ? 50 : 0
})
.padding({
top: 2,
bottom: 2,
left: 2,
right: 2
});
}
.onClick(() => {
this.controller.changeIndex(index);
this.selectedIndex = index;
});
}
build() {
Column() {
Row({ space: 10 }) {
Scroll() {
Row() {
ForEach(this.tabName, (item: string, index: number) => {
this.tabBuilder(index, item);
});
}
.justifyContent(FlexAlign.Start);
}
.layoutWeight(1)
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off);
Image($r('sys.media.ohos_ic_public_more')) // 开发者可根据需求更换其它图片资源
.width(32)
.height(32)
.onClick(() => {
try {
this.getUIContext().getPromptAction().showToast({
message: '触发开发者自定义事件',
duration: 2000,
showMode: promptAction.ToastShowMode.TOP_MOST,
bottom: 85
});
} catch (error) {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`showToast args error code is ${code}, message is ${message}.`);
}
});
}
.margin({ top: 16 })
.padding({ left: 10, right: 10 })
.alignItems(VerticalAlign.Center)
.width('100%')
.height(40);
Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
ForEach(this.tabName, () => {
TabContent() {
Column()
.width('100%')
.height('100%');
};
});
}
.margin({ top: 2 })
.width('100%')
.barHeight(0)
.animationDuration(100)
.onChange((index: number) => {
this.selectedIndex = index;
});
}
.height('100%');
}
} 实现效果如下:

智能客服
你问我答,随时在线为你解决问题
合作咨询
我们的专家服务团队将竭诚为您提供专业的合作咨询服务
解决方案
精准高效的一站式服务支持,助力开发者商业成功