在多标签页场景下,ArkUI 提供了 TabsTabContent 两个组件,帮助你快速实现不同内容区的切换展示。每个标签对应一个 TabContent 子组件,Tabs 负责整体容器的布局与交互。


一、基础用法

@Entry @Component
struct SimpleTabsDemo {
  private controller: TabsController = new TabsController();

  build() {
    Column({ space: 0 }) {
      // 1. 定义 Tabs 容器,barPosition 决定标签栏方向
      Tabs({
        barPosition: BarPosition.Start,   // 标签栏顶端
        controller: this.controller,      // 控制器,用于编程式切换
        index: 0                          // 默认激活第一个标签
      })
      .size({ width: "100%", height: "100%" })
      .vertical(false)                   // 上下排列(默认)
      {
        // 2. 每个 TabContent 对应一个内容视图
        TabContent()
          .tabBar("消息")                 // 文本标签
        {
          Column({ alignItems: HorizontalAlign.Center }) {
            Text("这里是消息页面")
              .fontSize(24)
              .padding(20)
          }
        }

        TabContent()
          .tabBar({ icon: "icon_contacts", text: "联系人" })  // 图文标签
        {
          Column({ alignItems: HorizontalAlign.Center }) {
            Text("这里是联系人页面")
              .fontSize(24)
              .padding(20)
          }
        }

        TabContent()
          .tabBar("动态")
        {
          Column({ alignItems: HorizontalAlign.Center }) {
            Text("这里是动态页面")
              .fontSize(24)
              .padding(20)
          }
        }
      }
    }
  }
}
  • barPosition: BarPosition.Start:标签在上方;
  • vertical(false):上下排列标签页;
  • 每个 TabContent().tabBar(...) { ... } 定义一个标签与对应内容。

二、左右布局与底部布局

  • 左右排列vertical(true)
    标签栏在左右侧,适合复杂侧边导航。

  • 底部排列barPosition: BarPosition.End + vertical(false)
    标签栏在底部,典型的移动端导航结构。

Tabs({ barPosition: BarPosition.End, controller: this.controller })
  .vertical(false)      // 底部标签
  .barHeight(60)        // 指定高度
  .barMode(BarMode.Fixed) // 标签均分
  .onChange(idx => { /* 切换回调 */ })

三、常用属性

方法 说明
vertical(bool) 是否左右布局,true 左右,false 上下(默认)
barPosition(BarPosition) 标签栏位置:Start(上/左)、End(下/右)
scrollable(bool) 标签栏是否可滑动,超出宽度时横向滚动(默认 true
barMode(BarMode) Fixed(均分宽度)、Scrollable(实际宽度)
barWidth(length) 标签栏宽度(左右布局时生效)
barHeight(length) 标签栏高度(上下布局时生效)
animationDuration(ms) 切换内容的动画时长,毫秒单位,默认 200
onChange((index)⇒void) 用户切换标签的回调,返回当前标签索引

四、编程式切换

通过传入统一的 TabsController,可以在外部调用切换:

// 切换到第二个标签
this.controller.changeIndex(1);

也可在自定义标签中直接触发:

TabContent()
  .tabBar(customBuilder)
  .onClick(() => {
    this.controller.changeIndex(2);
  })

五、自定义标签样式

TabContent.tabBar(...) 支持以下形式:

  1. 纯文本.tabBar("标签名称")
  2. 图文对象.tabBar({ icon: "资源ID", text: "名称" })
  3. 自定义 Builder:提供 JSX/DSL 构建函数,完全自定义渲染。

例如,结合 @Builder 构造圆形图标加文字的标签:

@Builder tabItem(iconRes: string, label: string, active: boolean) {
  Column({ alignItems: HorizontalAlign.Center, space: 4 }) {
    Image(iconRes)
      .size({ width: 24, height: 24 })
      .opacity(active ? 1 : 0.6);
    Text(label)
      .fontSize(14)
      .fontColor(active ? "#2a58d0" : "#888");
  }
  .onClick(() => this.controller.changeIndex( indexOf(label) ));
}

六、完整示例

@Entry @Component
struct TabsFullDemo {
  @State currentIndex: number = 0;
  private ctrl: TabsController = new TabsController();

  build() {
    Column() {
      Tabs({
        barPosition: BarPosition.End,
        controller: this.ctrl,
        index: this.currentIndex
      })
      .barHeight(56)
      .barMode(BarMode.Scrollable)
      .onChange(idx => this.currentIndex = idx)
      .vertical(false)
      {
        TabContent()
          .tabBar(this.tabBuilder("消息", 0)) {
          Text("消息页内容").fontSize(20).padding(16);
        }

        TabContent()
          .tabBar(this.tabBuilder("联系人", 1)) {
          Text("联系人页内容").fontSize(20).padding(16);
        }

        TabContent()
          .tabBar(this.tabBuilder("动态", 2)) {
          Text("动态页内容").fontSize(20).padding(16);
        }
      }
    }
  }

  @Builder
  private tabBuilder(label: string, idx: number) {
    let active = (idx === this.currentIndex);
    Column({ alignItems: HorizontalAlign.Center, space: 4 }) {
      Image(active ? "icon_sel" : "icon_nor")
        .size({ width: 20, height: 20 });
      Text(label)
        .fontSize(14)
        .fontColor(active ? "#2a58d0" : "#666");
    }
    .onClick(() => {
      this.currentIndex = idx;
      this.ctrl.changeIndex(idx);
    })
  }
}

这样,你便拥有了一个功能齐全、可编程、易于自定义的多标签切换组件。无论是移动端底栏导航,还是桌面端侧边标签页,都能一行代码完成布局与交互。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐