The ArkUI framework in HarmonyOS provides a versatile Tabs component for creating tabbed user interfaces. This component allows for organized presentation of content, with features such as active state indication, custom tab content, and performance optimization through lazy loading of inactive panels.
Basic Layout
The fundamental structure of the Tabs component involves enclosing individual TabContent elements within the Tabs declaration. Each TabContent corresponds to a distinct tab bar item.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs() {
TabContent() {
Text('Home Content').fontSize(30)
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
Navigation Bar Positioning
The Tabs component supports flexible positioning of the navigation bar. #### Bottom Navigation
To position the tab bar at the bottom, set the barPosition property to BarPosition.End.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Text('Home Content').fontSize(30)
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
Top Navigation
To top navigation, set barPosition to BarPosition.Start.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Text('Home Content').fontSize(30)
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
Side Navigation
To implement side navigation, set the vertical property of the Tabs component to true. When vertical is false, the tab bar defaults to filling the screen width; in this case, you might need to explicitly set barWidth. When vertical is true, the tab bar height defaults to the actual content height; consider setting barHeight appropriately.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Text('Home Content').fontSize(30)
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
.vertical(true)
.barWidth(100)
.barHeight(200)
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
Navigation Effects
Disabling Tab Bar Swiping
In scenarios with nested tab bars (e.g., a botttom tab bar containing another set of tabs), you might need to disable the swipe-to-switch gesture for one of the tab bars to prevent conflicts and ensure a better user experience. This is achieved by setting the scrollable property to false on the Tabs component whose swipe behavior should be restricted.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Column() {
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Text('Home Content').fontSize(30)
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
.vertical(true)
.barWidth(100)
.barHeight(200)
}
.backgroundColor('#ff08a8f1')
.width('100%')
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
.scrollable(false) // Disable swipe for the outer tabs
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
Fixed Navigation Bar
The barMode property controls the scrolling behavior of the navigation bar. By default, it is set to BarMode.Fixed, meaning the tab bar remains stationary.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Column() {
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Text('Home Content').fontSize(30)
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
.vertical(true)
.barWidth(100)
.barHeight(200)
}
.backgroundColor('#ff08a8f1')
.width('100%')
}
.tabBar('Home')
TabContent() {
Text('Recommendations Content').fontSize(30)
}
.tabBar('Recommendations')
TabContent() {
Text('Discover Content').fontSize(30)
}
.tabBar('Discover')
TabContent() {
Text('My Content').fontSize(30)
}
.tabBar("My")
}
.scrollable(false)
.barMode(BarMode.Fixed) // Explicitly set to Fixed
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}
Scrolable Navigation Bar
To enable a scrollable navigation bar, set the barMode property to BarMode.Scrollable. This is particularly useful when you have a large number of tabs that might not fit within the visible screen area.
@Entry
@Component
struct TabbedInterfaceExample {
build() {
Column() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Column() {
Tabs({ barPosition: BarPosition.Start }) {
TabContent() { Text('Home Content').fontSize(30) }.tabBar('Home')
TabContent() { Text('Recommendations Content').fontSize(30) }.tabBar('Recommendations')
TabContent() { Text('Discover Content').fontSize(30) }.tabBar('Discover')
TabContent() { Text('My Content').fontSize(30) }.tabBar("My")
}
.vertical(true)
.barWidth(100)
.barHeight(200)
}
.backgroundColor('#ff08a8f1')
.width('100%')
}
.tabBar('Home')
// Add multiple TabContent items to demonstrate scrolling
TabContent() { Text('Content 1').fontSize(30) }.tabBar('Tab 1')
TabContent() { Text('Content 2').fontSize(30) }.tabBar('Tab 2')
TabContent() { Text('Content 3').fontSize(30) }.tabBar('Tab 3')
TabContent() { Text('Content 4').fontSize(30) }.tabBar('Tab 4')
TabContent() { Text('Content 5').fontSize(30) }.tabBar('Tab 5')
TabContent() { Text('Content 6').fontSize(30) }.tabBar('Tab 6')
TabContent() { Text('Content 7').fontSize(30) }.tabBar('Tab 7')
TabContent() { Text('Content 8').fontSize(30) }.tabBar('Tab 8')
TabContent() { Text('Content 9').fontSize(30) }.tabBar('Tab 9')
TabContent() { Text('Content 10').fontSize(30) }.tabBar('Tab 10')
TabContent() { Text('Content 11').fontSize(30) }.tabBar('Tab 11')
TabContent() { Text('Content 12').fontSize(30) }.tabBar('Tab 12')
TabContent() { Text('Content 13').fontSize(30) }.tabBar('Tab 13')
TabContent() { Text('Content 14').fontSize(30) }.tabBar('Tab 14')
TabContent() { Text('Content 15').fontSize(30) }.tabBar('Tab 15')
TabContent() { Text('Content 16').fontSize(30) }.tabBar('Tab 16')
TabContent() { Text('Content 17').fontSize(30) }.tabBar('Tab 17')
TabContent() { Text('Content 18').fontSize(30) }.tabBar('Tab 18')
TabContent() { Text('Content 19').fontSize(30) }.tabBar('Tab 19')
TabContent() { Text('Content 20').fontSize(30) }.tabBar('Tab 20')
}
.scrollable(false) // Keep this false if outer tabs should not scroll
.barMode(BarMode.Scrollable) // Enable scrolling for the outer tabs
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5')
}
}