1. 核心概念

标签页(Tabs)是一种常见的多视图切换方案:用户通过点击不同的页签(TabBar)来切换对应内容区(TabContent)。ArkUI 通过 Tabs + TabContent 组件对这一场景进行了封装:

  • **Tabs**:外层容器,负责布局与状态管理;
  • **TabContent**:子组件,只能在 Tabs 内出现,每个实例对应一个页签及其视图;

2. 快速上手

下面示例展示了一个最简版的上下排列标签页:

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

  build() {
    Tabs({
      barPosition: BarPosition.Start,  // 页签在顶部
      controller: this.controller
    }) {
      // — 第一个标签页 —
      TabContent() {
        Column({ alignItems: HorizontalAlign.Center, justifyContent: FlexAlign.Center }) {
          Text("首页内容").fontSize(24);
        }
      }
      .tabBar("首页")

      // — 第二个标签页 —
      TabContent() {
        Column({ alignItems: HorizontalAlign.Center, justifyContent: FlexAlign.Center }) {
          Text("设置内容").fontSize(24);
        }
      }
      .tabBar("设置")
    }
    .width("100%")
    .height("100%");
  }
}
  • barPosition: BarPosition.Start:顶部水平排列;
  • controller:可以在外部通过 controller.changeIndex() 动态切换;
  • .tabBar("文本"):为每个 TabContent 指定页签标题。

3. Tabs 常用属性

方法 说明
.vertical(true/false) 是否左右排列页签(true 左右,false 上下)
.scrollable(true/false) 是否允许手势滑动切换内容(默认 true
.barMode(BarMode.Fixed) 页签宽度分配,Fixed 平均分配 / Scrollable 根据内容自适应
.barWidth(length) 竖排时页签栏宽度
.barHeight(length) 横排时页签栏高度
.animationDuration(ms) 切换动画时长,单位毫秒
.onChange((idx) => {...}) 页签切换回调,idx 当前激活页签下标

4. 布局示例

4.1 横向固定平均分配

Tabs({ barPosition: BarPosition.End })      // 底部水平排列
  .barMode(BarMode.Fixed)
  .barHeight(50)
  .onChange((idx) => console.log("当前页签:", idx))

4.2 纵向可滑动自适应

Tabs({ barPosition: BarPosition.Start })
  .vertical(true)                          // 左侧竖排
  .scrollable(true)
  .barMode(BarMode.Scrollable)
  .barWidth(80)

5. 自定义 TabContent 标签

除了简单的文本或图标,你还可以传入一个自定义的构建器:

@Entry @Component
struct CustomTabsDemo {
  private ctrl = new TabsController();
  @State idx = 0;

  @Builder tabItem(label: string, icon: string, selected: boolean) {
    Column({ alignItems: HorizontalAlign.Center, justifyContent: FlexAlign.Center }) {
      Image(selected ? $r("app.media."+icon+"_sel") : $r("app.media."+icon))
        .size({ width: 24, height: 24 });
      Text(label).fontSize(14)
        .fontColor(selected ? "#007AFF" : "#666");
    }
    .width(100.percent)
    .height(100.percent)
    .onClick(() => {
      this.idx = label === "消息" ? 0 : 1;
      this.ctrl.changeIndex(this.idx);
    });
  }

  build() {
    Tabs({ controller: this.ctrl })
      .barMode(BarMode.Fixed)
      .onChange(index => this.idx = index) {
      TabContent()
        .tabBar(() => this.tabItem("消息", "icon_msg", this.idx === 0)) {
        /* ...内容... */
      }
      TabContent()
        .tabBar(() => this.tabItem("好友", "icon_friends", this.idx === 1)) {
        /* ...内容... */
      }
    }
  }
}

6. 完整示例

@Entry @Component
struct FullTabsExample {
  private controller = new TabsController();
  @State activeIndex = 0;

  build() {
    Column({ space: 0 }) {
      // — 标签页容器 —
      Tabs({
        barPosition: BarPosition.Start,
        controller: this.controller
      })
      .barMode(BarMode.Scrollable)
      .barHeight(48)
      .animationDuration(300)
      .onChange(idx => this.activeIndex = idx) {
        ["消息", "联系人", "动态"].map((label, i) =>
          TabContent()
            .tabBar(label)
        )
      }

      // — 底部内容展示 —
      Box({ flex: 1, backgroundColor: ["#aabbcc","#bbccaa","#ccaabb"][this.activeIndex] }) {
        Text(`当前: ${["消息","联系人","动态"][this.activeIndex]}`)
          .fontSize(20)
          .textAlign(TextAlign.Center)
          .padding(20);
      }
    }
    .width("100%")
    .height("100%");
  }
}

7. 小贴士

  1. 性能优化

    • 当页签数量较多时,开启 .scrollable(true) 并设置合理 barWidth,避免全部均匀分配导致过小。
  2. 动画体验

    • animationDuration 可调节切换动画时长,配合 TabsController.changeIndex() 可实现编程式切换。
  3. 可访问性

    • 为自定义标签添加无障碍描述(accessibilityLabel),确保屏幕阅读器友好。

通过以上用法,你可以在 ArkUI 中灵活配置“上下”/“左右”、可滑动/不可滑动、平均分配/自适应等任意组合,快速搭建符合业务需求的多视图切换组件。
祝你编码愉快!

Logo

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

更多推荐