Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Multi-Level Navigation in HarmonyOS with Navbar and TabBar

Tech 1

In HarmonyOS application development, routing and view switching are typically managed through state-decorated propertise and lifecycle-aware components. The following example demonstrates how to implement a tab-based interface using TabBar while isolating route state.

@Entry
@Component
struct MainRouter {
  @State activeTabIndex: number = 0;

  build() {
    Column() {
      TabBar({
        selectedIndex: this.activeTabIndex,
        onTabChanged: (index: number) => {
          this.activeTabIndex = index;
        }
      }) {
        TabItem({ label: 'Dashboard', icon: ResourceStr('icons/home') })
        TabItem({ label: 'Configuration', icon: ResourceStr('icons/cog') })
      }

      // Dynamic View Rendering
      if (this.activeTabIndex === 0) {
        DashboardPanel();
      } else if (this.activeTabIndex === 1) {
        SettingsPanel();
      }
    }
    .width('100%')
    .height('100%')
  }
}

Individual views are structured as autonomous components. Layout hierarchy utilizes nested containers to distribute content proportionally across the screen dimensions.

struct DashboardPanel {
  build() {
    Row() {
      Column() {
        Text('System Overview')
          .fontSize(48)
          .fontWeight(FontWeight.Medium)
          .padding(16)
      }
      .alignItems(HorizontalAlign.Start)
    }
    .layoutWeight(1)
    .backgroundColor('#F5F7FA')
  }
}

struct SettingsPanel {
  build() {
    Row() {
      Column() {
        Text('User Preferences')
          .fontSize(48)
          .fontWeight(FontWeight.Medium)
          .padding(16)
      }
      .alignItems(HorizontalAlign.End)
    }
    .layoutWeight(1)
    .backgroundColor('#FFFFFF')
  }
}

Advanced interfaces often require simultaneous top and bottom navigation controls. By decoupling their respective state variables, developers can manage independent interaction flows without triggering unnecessary UI rebuilds.

@Entry
@Component
struct DualNavLayout {
  @State topNavSelection: number = 0;
  @State bottomTabSelection: number = 0;

  build() {
    Column() {
      // Upper Control Layer
      Navbar({
        title: 'Platform Console',
        leading: Icon(Icons.menu),
        trailing: Icon(Icons.search),
        onLeadingTap: () => this.handleMenuAction(),
        onTrailingTap: () => this.handleSearchAction()
      })

      // Content Area Conditionally Rendered
      if (this.topNavSelection === 0) {
        HomeView();
      } else if (this.topNavSelection === 1) {
        AnalyticsView();
      }

      // Lower Control Layer
      TabBar({
        selectedIndex: this.bottomTabSelection,
        onTabChanged: (idx: number) => {
          this.bottomTabSelection = idx;
        }
      }) {
        TabItem({ label: 'Main' })
        TabItem({ label: 'Tools' })
      }
    }
    .width('100%')
    .height('100%')
  }

  private handleMenuAction(): void { /* Drawer toggle logic */ }
  private handleSearchAction(): void { /* Query modal logic */ }
}

The underlying panel definitions follow a standardized structural pattern. Each component encapsulates its own layout geometry and styling parameters, promoting modular reuse across different routing contexts.

struct HomeView {
  build() {
    Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Nowrap }) {
      Column() {
        Text('Active Workspace')
          .style({ fontSize: 52, fontWeight: FontWeight.Bold })
          .margin(20)
      }
      .layoutFlex(1)
    }
    .backgroundImageStyle(ImageFit.Contain)
  }
}

struct AnalyticsView {
  build() {
    Flex({ direction: FlexDirection.Column }) {
      Row() {
        Text('Metrics Summary')
          .style({ fontSize: 52, fontWeight: FontWeight.Bold })
          .margin(20)
      }
    }
    .justifyContent(FlexAlign.Center)
  }
}

When configuring multi-axis navigation systems, state synchronization becomes the primary concern. Binding selectedIndex to independent decorators ensures that modifying one controller does not invalidate the other's display context. Event handlers route user inputs back to the local scope, allowing precise control over render cycles. This architecture scales efficiently to enterprise-grade dashboards where header actions and footer tabs operate on disjoint data models.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.