Per-Tab Immersive Status Bar and Programmatic TabBar Hiding with ArkUI Tabs

Published: (March 15, 2026 at 09:35 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

Requirement Description

Q1: When building pages with Tabs, how can a specific TabContent enable an immersive (edge‑to‑edge) top status bar effect?

Q2: When using Tabs, how can the TabBar be hidden programmatically?

Background Knowledge

ConceptDescriptionDocs
expandSafeAreaControls how a component extends into system safe areas (e.g., status / navigation bars).
barHeight / barWidth (on Tabs)Controls the size of the TabBar. Setting the value to 0 effectively hides the bar.

Implementation Steps

Q1 – Immersive status bar only for the target TabContent

  1. Page / Tabs root – Allow content to extend into system safe areas:

    expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  2. Target TabContent – Disable clipping so its children can draw into the expanded area:

    .clip(false)
  3. Inside that TabContent – Apply expandSafeArea to the container that should render edge‑to‑edge.

Q2 – Hide the TabBar programmatically

  1. Bind a boolean state (e.g., isTabBarVisible) to the Tabs component.

  2. Toggle the size properties:

    .barHeight(isTabBarVisible ? -1 : 0)
    .barWidth(isTabBarVisible ? -1 : 0)
    • 0 → hide the bar.
    • -1 → use the default size.
  3. (Optional) Add a short animation for a smoother transition:

    .animationDuration(400)   // duration in ms

Code Snippets

Q1 – Per‑Tab Immersive Status Bar

@Entry
@Component
struct TabsExample {
  build() {
    Tabs({ barPosition: BarPosition.End }) {
      // ----- First Tab (immersive) -----
      TabContent() {
        Column() {
          Text('Homepage Content')
            .fontSize(30)
            .width('100%')
            .height('100%')
            .backgroundColor('#0A59F7')
            .textAlign(TextAlign.Center)
            // Immersive effect for this tab's content
            .expandSafeArea([SafeAreaType.SYSTEM],
                            [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
        }
        .height('100%')
        .width('100%')
      }
      .clip(false)                     // allow drawing beyond bounds
      .tabBar('Home')

      // ----- Second Tab (normal) -----
      TabContent() {
        Row() {
          Text('Recommended content')
            .fontSize(30)
            .width('100%')
            .height('100%')
            .backgroundColor('#F1F3F5')
            .textAlign(TextAlign.Center)
        }
        .height('100%')
      }
      .tabBar('Recommendation')
    }
    .expandSafeArea([SafeAreaType.SYSTEM],
                    [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
    .width('100%')
    .height('100%')
  }
}

Tip: Use the Enter fullscreen mode / Exit fullscreen mode buttons in the IDE preview to verify the immersive effect.

Q2 – Programmatically Hide/Show the TabBar

@Entry
@Component
struct TabsExample {
  @State isTabBarVisible: boolean = true;
  @State fontColor: string = '#182431';
  @State selectedFontColor: string = '#007DFF';
  @State currentIndex: number = 1;
  private controller: TabsController = new TabsController();

  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.currentIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 });
      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.currentIndex === index ? 1 : 0);
    }
    .width('100%');
  }

  build() {
    Column() {
      Blank().height('5%');

      // ---- Controls to toggle TabBar visibility ----
      Row() {
        Text('Hide')
          .height('3%')
          .onClick(() => this.isTabBarVisible = false);
        Blank().width('25%');
        Text('Display')
          .height('3%')
          .onClick(() => this.isTabBarVisible = true);
      }
      .height('15%');

      // ---- Tabs ----
      Tabs({
        barPosition: BarPosition.End,
        index: this.currentIndex,
        controller: this.controller
      }) {
        TabContent() { Column().width('100%').height('100%').backgroundColor('#00CB87') }
          .tabBar(this.tabBuilder(0, 'green'));

        TabContent() { Column().width('100%').height('100%').backgroundColor('#007DFF') }
          .tabBar(this.tabBuilder(1, 'blue'));

        TabContent() { Column().width('100%').height('100%').backgroundColor('#FFBF00') }
          .tabBar(this.tabBuilder(2, 'yellow'));
      }
      .vertical(false)
      .barMode(BarMode.Fixed)
      .barWidth(this.isTabBarVisible ? -1 : 0)
      .barHeight(this.isTabBarVisible ? -1 : 0)
      .animationDuration(400)
      .onChange((index: number) => this.currentIndex = index)
      .width('100%')
      .height('64%')
      .backgroundColor('#F1F3F5');
    }
    .width('100%');
  }
}

Tip: Use the Enter fullscreen mode / Exit fullscreen mode buttons in the preview to see the TabBar hide and show smoothly.

Test Results

  • Immersive rendering – Verified that only the first TabContent renders edge‑to‑edge; the second tab retains the normal layout.
  • TabBar visibility – Confirmed that toggling isTabBarVisible hides/shows the TabBar instantly with the defined animation, while tab selection and page navigation continue to work correctly.

Test GIF

Example illustration

Limitations or Considerations

  • barHeight: 'auto' only applies in horizontal mode; hiding uses 0 explicitly.
  • Immersive content must manage its own contrast/readability against status‑bar overlays (consider background color or top padding as needed).
  • Round wearable screens: confirm corners/radii aren’t clipped; ensure touch targets are ≥ 44 vp.
  • expandSafeArea
  • barHeight

Written by Bunyamin Eymen Alagoz

0 views
Back to Blog

Related posts

Read more »