• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Tabs
2
3
4When there is a large amount of page information, to enable the user to focus on the currently displayed content, the page content needs to be classified to improve the page space utilization. The [\<Tabs>](../reference/arkui-ts/ts-container-tabs.md) component can quickly switch between views on a page, improving information search efficiency and reducing the amount of information that users can obtain at a time.
5
6
7## Basic Layout
8
9  The **\<Tabs>** component consists of two parts: **\<TabContent>** and **\<TabBar>**. **\<TabContent>** is the content page, and **\<TabBar>** is the navigation tab bar. The following figure shows the page structure. The layout varies according to the navigation type. In bottom navigation, top navigation, and side navigation, the navigation tab bar is located at the bottom, top, and edge, respectively.
10  **Figure 1** \<Tabs> component layout
11
12![tabs-layout](figures/tabs-layout.png)
13
14
15>**NOTE**
16>
17> - The **\<TabContent>** component does not support setting of the common width attribute. By default, its width is the same as that of the parent **\<Tabs>** component.
18>
19> - The **\<TabContent>** component does not support setting of the common height attribute. Its height is determined by the height of the parent **\<Tabs>** component and the **\<TabBar>** component.
20
21
22**\<Tabs>** use braces to enclose the tab content, as shown in Figure 2.
23
24
25  **Figure 2** Using \<Tabs> and \<TabContent>
26
27![tabs-tabscontent](figures/tabs-tabscontent.png)
28
29
30Each **\<TabContent>** component should be mapped to a tab page, which can be configured through the **tabBar** attribute. The following is an example.
31
32
33
34```ts
35 TabContent() {
36   Text('Content of the Home tab').fontSize(30)
37 }
38.tabBar ('Home')
39```
40
41
42When setting multiple **\<TabContent>** components, place them in sequence in the **\<Tabs>** component.
43
44```ts
45Tabs() {
46  TabContent() {
47    Text('Content of the Home tab').fontSize(30)
48  }
49  .tabBar ('Home')
50
51  TabContent() {
52    Text('Content of the Recommended tab').fontSize(30)
53  }
54  .tabBar ('Recommended')
55
56  TabContent() {
57    Text ('Content of the Discover tab').fontSize (30)
58  }
59  .tabBar ('Discover')
60
61  TabContent() {
62    Text ('Content of the Me tab').fontSize (30)
63  }
64  .tabBar ("Me")
65}
66```
67
68
69## Bottom Navigation
70
71Bottom navigation is the most common navigation mode in applications. The bottom navigation bar is located at the bottom of the level-1 page of the application. It enables the user to quickly have a picture of the feature categories the moment they open the application. In addition, it facilitates one-hand operations of the user. Bottom navigation generally exists as a main navigation form of an application, in that it provides convenient access to primary destinations anywhere in the application.
72
73
74  **Figure 3** Bottom navigation bar
75
76![bottom-navigation](figures/bottom-navigation.gif)
77
78
79You set the position of the navigation bar through the **barPosition** parameter of the **\<Tabs>** component. The default value of this parameter is **Start**, which means that the navigation bar is located on the top. To set the navigation bar to the bottom, set **barPosition** to **End**.
80
81
82```ts
83Tabs({ barPosition: BarPosition.End }) {
84  // TabContent: Home, Discover, Recommended, and Me
85  ...
86}
87```
88
89
90## Top Navigation
91
92Top navigation comes in handy when there are many content categories and users need to frequently switch between them. It is usually a further subdivision of the categories in the bottom navigation bar. For example, a theme application may provide a top navigation bar that classifies themes into image, video, and font.
93
94  **Figure 4** Top navigation bar
95
96![top-navigation](figures/top-navigation.gif)
97
98The default barPosition parameter of the Tabs component is Start, indicating the top navigation mode.
99
100
101```ts
102Tabs({ barPosition: BarPosition.Start }) {
103  // TabContent: Following, Video, Game, Digital, Technology, Sports, Movie
104  ...
105}
106```
107
108
109## Side Navigation
110
111Side navigation is seldom used in applications. It is more applicable to landscape screens and is used to perform navigation operations on applications. Because the natural eye movement pattern is from left to right, the side navigation bar is located on the left side by default.
112
113
114  **Figure 5** Side navigation bar
115
116![side-navigation](figures/side-navigation.png)
117
118
119To implement the side navigation bar, set the **vertical** attribute of the **\<Tabs>** component to **true**. In the bottom navigation and top navigation implementations, the default value **false** of the **vertical** attribute is used, indicating that the content page and navigation bar are aligned vertically.
120
121
122
123```ts
124Tabs({ barPosition: BarPosition.Start }) {
125  // TabContent: Home, Discover, Recommended, and Me
126  ...
127}
128.vertical(true)
129.barWidth(100)
130.barHeight(200)
131```
132
133
134>**NOTE**
135>
136> - When the **vertical** attribute is set to **true**, the tab bar takes up the whole screen width by default. You need to set **barWidth** to a proper value.
137>
138> - When the **vertical** attribute is set to **true**, the tab bar takes up the actual content height by default. You need to set **barWidth** to a proper value.
139
140
141## Restricting the Scrolling of the Navigation Bar
142
143By default, the navigation bar is scrollable. On some pages that require multi-level classification of content, for example, when both bottom navigation and top navigation are used, the scroll effect of the bottom navigation bar may conflict with that of the top navigation bar. In this case, the scrolling of the bottom navigation bar needs to be restricted to improve user experience.
144
145  **Figure 6** Restricting the scrolling of the bottom navigation bar
146
147![restricted-navigation](figures/restricted-navigation.gif)
148
149
150The attribute that enables or disables the scrolling is **scrollable**. Its default value is **true**, indicating that scrolling is enabled. To disable the scrolling, set the attribute to **false**.
151
152
153
154```ts
155Tabs({ barPosition: BarPosition.End }) {
156  TabContent(){
157    Column(){
158      Tabs(){
159        // Content on the top navigation bar
160        ...
161      }
162    }
163    .backgroundColor('#ff08a8f1')
164    .width('100%')
165  }
166  .tabBar ('Home')
167
168  // Other TabContent content: Discover, Recommended, and Me
169  ...
170}
171.scrollable(false)
172```
173
174
175## Fixed Navigation Bar
176
177When the content categories are relatively fixed and not scalable, a fixed navigation bar can be used. For example, it can be used for the bottom navigation bar, which generally contains 3 to 5 categories. The fixed navigation bar cannot be scrolled or dragged. The tab bar width is evenly distributed among the categories.
178
179
180  **Figure 7** Fixed navigation bar
181
182![fixed-navigation](figures/fixed-navigation.gif)
183
184
185To use a fixed navigation bar, set the **barMode** attribute of the **\<Tabs>** component to **Fixed** (default).
186
187
188
189```ts
190Tabs({ barPosition: BarPosition.End }) {
191  // TabContent: Home, Discover, Recommended, and Me
192  ...
193}
194.barMode(BarMode.Fixed)
195```
196
197
198## Scrollable Navigation Bar
199
200The top navigation bar or side navigation bar can be set to be scrollable if the screen width cannot fully accommodate all the tabs. With a scrollable navigation bar, users can reveal tabs beyond the visible area by touching or swiping on the navigation bar.
201
202
203  **Figure 8** Scrollable navigation bar
204
205![scrollable-navigation](figures/scrollable-navigation.gif)
206
207
208To use a scrollable navigation bar, set the **barMode** attribute of the **\<Tabs>** component to **Scrollable**.
209
210
211
212```ts
213Tabs({ barPosition: BarPosition.Start }) {
214  // TabContent: follow, video, game, digital, technology, sports, movie, humanities, art, nature, and military
215  ...
216}
217.barMode(BarMode.Scrollable)
218```
219
220
221## Customizing the Navigation Bar
222
223The bottom navigation bar is generally used on the home page of an application. To deliver a more vibrant experience, you can customize the style of the navigation bar, combining use of text and icons to signify the tab content.
224
225
226  **Figure 9** Custom navigation bar
227
228![custom-navigation-bar](figures/custom-navigation-bar.png)
229
230
231By default, the system uses an underscore (_) to indicate the active tab. For a custom navigation bar, you need to implement the corresponding style to distinguish active tabs from inactive tabs.
232
233
234To customize the navigation bar, use the **tabBar** parameter and pass in to it custom function component styles in **CustomBuilder** mode. In this example, a custom function component **TabBuilder** is declared, and the input parameters include **title** (tab title), **targetIndex** (target index of the tab), **selectedImg** (image for the selected state), and **normalImg** (image for the unselected state). The UI display style is determined based on whether the value of **currentIndex** (index of the active tab) matches that of **targetIndex** (target index of the tab).
235
236
237
238```ts
239@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
240  Column() {
241    Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
242      .size({ width: 25, height: 25 })
243    Text(title)
244      .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
245  }
246  .width('100%')
247  .height(50)
248  .justifyContent(FlexAlign.Center)
249}
250```
251
252
253Pass the custom function component to the **tabBar** attribute corresponding to the tab content and transfer the corresponding parameters.
254
255
256
257```ts
258TabContent() {
259  Column(){
260    Text('Content of the Me tab')
261  }
262  .width('100%')
263  .height('100%')
264  .backgroundColor('#007DFF')
265}
266.tabBar(this.TabBuilder('Me', 0, $r('app.media.mine_selected'), $r('app.media.mine_normal')))
267```
268
269
270## Switching to a Specified Tab
271
272Non-custom navigation bars follow the default system switching logic. If you are using a custom navigation bar, you must manually implement the logic for switching tabs so that when the user touches a tab, the application displays the corresponding tab page.
273
274
275  **Figure 10** Switching to a specified tab in a custom navigation bar
276
277![switching-to-a-specified-tab](figures/switching-to-a-specified-tab.gif)
278
279
280To switch to a specified tab page, use **TabsController**, which is the controller of the **\<Tabs>** component. By using the **changeIndex** API of **TabsController**, you can set your application to display the tab content corresponding to the specified index.
281
282
283
284```ts
285private tabsController : TabsController = new TabsController()
286@State currentIndex:number = 0;
287
288@Builder TabBuilder(title: string, targetIndex: number) {
289  Column() {
290    Text(title)
291      .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
292  }
293  ...
294  .onClick(() => {
295    this.currentIndex = targetIndex;
296    this.tabsController.changeIndex(this.currentIndex);
297  })
298}
299```
300
301
302When using a custom navigation bar, pass the corresponding \@Builder in the **tabBar** attribute and transfer the corresponding parameters.
303
304
305
306```ts
307Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
308  TabContent(){
309    ...
310  }.tabBar (this.TabBuilder ('Home', 0))
311
312  TabContent(){
313    ...
314  }.tabBar (this.TabBuilder ('Discover', 1))
315
316  TabContent(){
317    ...
318  }.tabBar (this.TabBuilder ('Recommended', 2))
319
320  TabContent(){
321    ...
322  }
323  .tabBar (this.TabBuilder ('Me',3))
324}
325```
326
327
328## Swiping to Switch Between Tabs
329
330For non-custom navigation bars, tabs and tab content are linked by default. For custom navigation bars, however, tabs and tab content are linked when tab switching is initiated by **TabsController**, but not when tab switching is initiated by a swipe gesture. This means that, when the user swipes on the screen to switch between tab content, the tabs do not switch automatically. In this case, manual switching is required.
331
332
333  **Figure 11** Lack of linkage between tabs and tab content
334
335![lack-of-linkage](figures /lack-of-linkage.gif)
336
337
338To manually switch between the tabs, use the **onChange** API provided by the **\<Tabs>** component to listen for the index change and pass the index of the active tab to **currentIndex**.
339
340
341
342
343```ts
344Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
345  TabContent() {
346    ...
347  }.tabBar (this.TabBuilder ('Home', 0))
348
349  TabContent() {
350    ...
351  }.tabBar (this.TabBuilder ('Found', 1))
352
353  TabContent() {
354    ...
355  }.tabBar (this.TabBuilder ('Recommended', 2))
356
357  TabContent() {
358    ...
359  }
360  .tabBar (this.TabBuilder ('Me', 3))
361}.onChange((index) => {
362  this.currentIndex = index
363})
364```
365
366
367  **Figure 12** Linkage between tabs and tab content
368
369![final-effect](figures/final-effect.gif)
370