• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Tabs
2
3The **\<Tabs>** component is a container component that allows users to switch between content views through tabs. Each tab page corresponds to a content view.
4
5>  **NOTE**
6>
7>  This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## Child Components
11
12Only the [\<TabContent>](ts-container-tabcontent.md) child component is supported.
13
14
15## APIs
16
17Tabs(value?: {barPosition?: BarPosition, index?: number, controller?: [TabsController](#tabscontroller)})
18
19**Parameters**
20
21| Name        | Type                             | Mandatory  | Description                                    |
22| ----------- | --------------------------------- | ---- | ---------------------------------------- |
23| barPosition | [BarPosition](#barposition)| No   | Position of the **\<Tabs>** component.<br>Default value: **BarPosition.Start**  |
24| index       | number                            | No   | Initial tab index.<br>Default value: **0**<br>**NOTE**<br>A value less than 0 evaluates to the default value.<br>The value ranges from 0 to the number of **\<TabContent>** subnodes minus 1.<br>When this parameter is set to different values, the slide animation for tab switching is enabled by default. To disable the animation, set **animationDuration** to **0**.<br>Since API version 10, this parameter supports [$$](../../quick-start/arkts-two-way-sync.md) for two-way binding of variables. |
25| controller  | [TabsController](#tabscontroller) | No   | Tab controller.                              |
26
27## BarPosition
28
29| Name   | Description                                      |
30| ----- | ---------------------------------------- |
31| Start | If the **vertical** attribute is set to **true**, the tab is on the left of the container. If the **vertical** attribute is set to **false**, the tab is on the top of the container.|
32| End   | If the **vertical** attribute is set to **true**, the tab is on the right of the container. If the **vertical** attribute is set to **false**, the tab is at the bottom of the container.|
33
34
35## Attributes
36
37In addition to the [universal attributes](ts-universal-attributes-size.md), the following attributes are supported.
38
39| Name                              | Type                                    | Description                                      |
40| -------------------------------- | ---------------------------------------- | ---------------------------------------- |
41| vertical                         | boolean                                  | Whether to use vertical tabs. The value **true** means to use vertical tabs, and **false** means to use horizontal tabs.<br>Default value: **false**|
42| scrollable                       | boolean                                  | Whether the tabs are scrollable. The value **true** means that the tabs are scrollable, and **false** means the opposite.<br>Default value: **true**|
43| barMode                          | [BarMode](#barmode),[ScrollableBarModeOptions](#scrollablebarmodeoptions10) | Tab bar layout mode. **BarMode** is mandatory, and **ScrollableBarModeOptions** is optional. For details, see **BarMode** and **ScrollableBarModeOptions**. Since API version 10, the optional **ScrollableBarModeOptions** parameter is supported. It is effective only when the tab bar is in scrollable mode.<br>Default value: **BarMode.Fixed**|
44| barWidth                         | number \| Length<sup>8+</sup>  | Width of the tab bar.<br>The default value varies.<br>If the tab bar has the **vertical** attribute set to **false** and does not have a style specified, the default value is the width of the **\<Tabs>** component.<br>If the tab bar has the **vertical** attribute set to **true** and does not have a style specified, the default value is **56vp**.<br>If the tab bar has the **vertical** attribute set to **false** and **SubTabbarStyle** specified, the default value is the width of the **\<Tabs>** component.<br>If the tab bar has the **vertical** attribute set to **true** and **SubTabbarStyle** specified, the default value is **56vp**.<br>If the tab bar has the **vertical** attribute set to **true** and **BottomTabbarStyle** specified, the default value is **96vp**.<br>If the tab bar has the **vertical** attribute set to **false** and **BottomTabbarStyle** specified, the default value is the width of the **\<Tabs>** component.<br>**NOTE**<br>A value less than 0 or greater than the width of the **\<Tabs>** component evaluates to the default value. |
45| barHeight                        | number \| Length<sup>8+</sup>  | Height of the tab bar.<br>The default value varies.<br>If the tab bar has the **vertical** attribute set to **false** and does not have a style specified, the default value is **56vp**.<br>If the tab bar has the **vertical** attribute set to **true** and does not have a style specified, the default value is the height of the **\<Tabs>** component.<br>If the tab bar has the **vertical** attribute set to **false** and **SubTabbarStyle** specified, the default value is **56vp**.<br>If the tab bar has the **vertical** attribute set to **true** and **SubTabbarStyle** specified, the default value is the height of the **\<Tabs>** component.<br>If the tab bar has the **vertical** attribute set to **true** and **BottomTabbarStyle** specified, the default value is the height of the **\<Tabs>** component.<br>If the tab bar has the **vertical** attribute set to **false** and **BottomTabbarStyle** specified, the default value is **56vp**.<br>**NOTE**<br>A value less than 0 or greater than the height of the **\<Tabs>** component evaluates to the default value. |
46| animationDuration                | number                                   | Duration of the slide animation for tab switching. If this parameter is set, the tab switching animation is played when the user switches between tabs by sliding or clicking. If this parameter is not set, the tab switching animation is played only when the user switches between tabs by sliding.<br>Default value: **300**<br>**NOTE**<br>A value less than 0 or in percentage evaluates to the default value. |
47| divider<sup>10+</sup>            | [DividerStyle](#dividerstyle10) \| null | Whether the divider is displayed for the **\<TabBar>** and **\<TabContent>** components and the divider style. By default, the divider is not displayed.<br> **DividerStyle**: divider style.<br> **null**: The divider is not displayed.|
48| fadingEdge<sup>10+</sup>         | boolean                                  | Whether the tab fades out when it exceeds the container width.<br>Default value: **true**        |
49| barOverlap<sup>10+</sup>         | boolean                                  | Whether the tab bar is superimposed on the **\<TabContent>** component after having its background blurred.<br>Default value: **false**|
50| barBackgroundColor<sup>10+</sup> | [ResourceColor](ts-types.md#resourcecolor) | Background color of the tab bar.<br>Default value: transparent              |
51| barGridAlign<sup>10+</sup> | [BarGridColumnOptions](#bargridcolumnoptions10) | Visible area of the tab bar in grid mode. For details, see **BarGridColumnOptions**. This attribute is effective only in horizontal mode. It is not applicable to [XS, XL, and XXL devices](../../ui/arkts-layout-development-grid-layout.md#grid-breakpoints).             |
52
53## DividerStyle<sup>10+</sup>
54
55| Name         | Type                                    | Mandatory  | Description                                      |
56| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
57| strokeWidth | [Length](ts-types.md#length)             | Yes   | Width of the divider. It cannot be set in percentage.                       |
58| color       | [ResourceColor](ts-types.md#resourcecolor) | No   | Color of the divider.<br>Default value: **#33182431**               |
59| startMargin | [Length](ts-types.md#length)             | No   | Distance between the divider and the top of the sidebar. It cannot be set in percentage.<br>Default value: **0.0**<br>Unit: vp|
60| endMargin   | [Length](ts-types.md#length)             | No   | Distance between the divider and the bottom of the sidebar. It cannot be set in percentage.<br>Default value: **0.0**<br>Unit: vp|
61
62## BarGridColumnOptions<sup>10+</sup>
63
64| Name         | Type                                    | Mandatory  | Description                                      |
65| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
66| margin | [Dimension](ts-types.md#dimension10)             | No   | Column margin in grid mode. It cannot be set in percentage.<br>Default value: **24.0**<br>Unit: vp                       |
67| gutter      | [Dimension](ts-types.md#dimension10) | No   | Column gutter (that is, gap between columns) in grid mode. It cannot be set in percentage.<br>Default value: **24.0**<br>Unit: vp                    |
68| sm | number            | No   | Number of columns occupied by a tab on a screen whose width is greater than or equal to 320 vp but less than 600 vp.<br>The value must be a non-negative even number. The default value is **-1**, indicating that the tab takes up the entire width of the tab bar.|
69| md   | number          | No   | Number of columns occupied by a tab on a screen whose width is greater than or equal to 600 vp but less than 800 vp.<br>The value must be a non-negative even number. The default value is **-1**, indicating that the tab takes up the entire width of the tab bar.|
70| lg   | number           | No   | Number of columns occupied by a tab on a screen whose width is greater than or equal to 840 vp but less than 1024 vp.<br>The value must be a non-negative even number. The default value is **-1**, indicating that the tab takes up the entire width of the tab bar.|
71
72## ScrollableBarModeOptions<sup>10+</sup>
73
74| Name         | Type                                    | Mandatory  | Description                                      |
75| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
76| margin | [Dimension](ts-types.md#dimension10)          | No   | Left and right margin of the tab bar in scrollable mode. It cannot be set in percentage.<br>Default value: **0.0**<br>Unit: vp                   |
77| nonScrollableLayoutStyle      | [LayoutStyle](#layoutstyle10) | No   | Tab layout mode of the tab bar when not scrolling in scrollable mode.<br>Default value: **LayoutStyle.ALWAYS_CENTER**          |
78
79## BarMode
80
81| Name        | Description                                      |
82| ---------- | ---------------------------------------- |
83| Scrollable | The width of each tab is determined by the actual layout. The tabs are scrollable in the following case: In horizontal layout, the total width exceeds the tab bar width; in horizontal layout, the total height exceeds the tab bar height.|
84| Fixed      | The width of each tab is determined by equally dividing the number of tabs by the bar width (or bar height in the vertical layout).|
85
86## LayoutStyle<sup>10+</sup>
87
88| Name        | Description                                      |
89| ---------- | ---------------------------------------- |
90| ALWAYS_CENTER | When the tab content exceeds the tab bar width, the tabs are scrollable.<br>Otherwise, the tabs are compactly centered and not scrollable.|
91| ALWAYS_AVERAGE_SPLITE      | When the tab content exceeds the tab bar width, the tabs are scrollable.<br>Otherwise, the tabs are not scrollable, and the tab bar width is distributed evenly between all tabs.<br>This option is valid only in horizontal mode, and is equivalent to **LayoutStyle.ALWAYS_CENTER** otherwise.|
92| SPACE_BETWEEN_OR_CENTER      | When the tab content exceeds the tab bar width, the tabs are scrollable.<br>When the tab content exceeds half of the tab bar width but still within the tab bar width, the tabs are compactly centered and not scrollable.<br>When the tab content does not exceed half of the tab bar width, the tabs are centered within half of the tab bar width, with even spacing between, and not scrollable.|
93
94## Events
95
96In addition to the [universal events](ts-universal-events-click.md), the following events are supported.
97
98| Name                                      | Description                                    |
99| ---------------------------------------- | ---------------------------------------- |
100| onChange(event: (index: number) =&gt; void) | Triggered when a tab is switched.<br>- **index**: index of the active tab. The index starts from 0.<br>This event is triggered when any of the following conditions is met:<br>1. The **\<TabContent>** component supports sliding, and the user slides on the tab bar.<br>2. The [Controller](#tabscontroller) API is called.<br>3. The attribute value is updated using a [state variable](../../quick-start/arkts-state.md).<br>4. A tab is clicked.|
101| onTabBarClick(event: (index: number) =&gt; void)<sup>10+</sup> | Triggered when a tab is clicked.<br>- **index**: index of the clicked tab. The index starts from 0.|
102
103## TabsController
104
105Defines a tab controller, which is used to control switching of tabs. One **TabsController** cannot control multiple **\<Tabs>** components.
106
107### Objects to Import
108
109```ts
110let controller: TabsController = new TabsController()
111```
112
113### changeIndex
114
115changeIndex(value: number): void
116
117Switches to the specified tab.
118
119**Parameters**
120
121| Name  | Type  | Mandatory  | Description                                    |
122| ----- | ------ | ---- | ---------------------------------------- |
123| value | number | Yes   | Index of the tab. The value starts from 0.<br>**NOTE**<br>If this parameter is set to a value less than 0 or greater than the maximum number, the event will be invalid.|
124
125
126## Example
127
128### Example 1
129
130```ts
131// xxx.ets
132@Entry
133@Component
134struct TabsExample {
135  @State fontColor: string = '#182431'
136  @State selectedFontColor: string = '#007DFF'
137  @State currentIndex: number = 0
138  private controller: TabsController = new TabsController()
139
140  @Builder TabBuilder(index: number, name: string) {
141    Column() {
142      Text(name)
143        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
144        .fontSize(16)
145        .fontWeight(this.currentIndex === index ? 500 : 400)
146        .lineHeight(22)
147        .margin({ top: 17, bottom: 7 })
148      Divider()
149        .strokeWidth(2)
150        .color('#007DFF')
151        .opacity(this.currentIndex === index ? 1 : 0)
152    }.width('100%')
153  }
154
155  build() {
156    Column() {
157      Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
158        TabContent() {
159          Column().width('100%').height('100%').backgroundColor('#00CB87')
160        }.tabBar(this.TabBuilder(0, 'green'))
161
162        TabContent() {
163          Column().width('100%').height('100%').backgroundColor('#007DFF')
164        }.tabBar(this.TabBuilder(1, 'blue'))
165
166        TabContent() {
167          Column().width('100%').height('100%').backgroundColor('#FFBF00')
168        }.tabBar(this.TabBuilder(2, 'yellow'))
169
170        TabContent() {
171          Column().width('100%').height('100%').backgroundColor('#E67C92')
172        }.tabBar(this.TabBuilder(3, 'pink'))
173      }
174      .vertical(false)
175      .barMode(BarMode.Fixed)
176      .barWidth(360)
177      .barHeight(56)
178      .animationDuration(400)
179      .onChange((index: number) => {
180        this.currentIndex = index
181      })
182      .width(360)
183      .height(296)
184      .margin({ top: 52 })
185      .backgroundColor('#F1F3F5')
186    }.width('100%')
187  }
188}
189```
190
191![tabs2](figures/tabs2.gif)
192
193### Example 2
194
195```ts
196// xxx.ets
197@Entry
198@Component
199struct TabsDivider1 {
200  private controller1: TabsController = new TabsController()
201  @State dividerColor: string = 'red'
202  @State strokeWidth: number = 2
203  @State startMargin: number = 0
204  @State endMargin: number = 0
205  @State nullFlag: boolean = false
206
207  build() {
208    Column() {
209      Tabs({ controller: this.controller1 }) {
210        TabContent() {
211          Column().width('100%').height('100%').backgroundColor(Color.Pink)
212        }.tabBar('pink')
213
214        TabContent() {
215          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
216        }.tabBar('yellow')
217
218        TabContent() {
219          Column().width('100%').height('100%').backgroundColor(Color.Blue)
220        }.tabBar('blue')
221
222        TabContent() {
223          Column().width('100%').height('100%').backgroundColor(Color.Green)
224        }.tabBar('green')
225
226        TabContent() {
227          Column().width('100%').height('100%').backgroundColor(Color.Red)
228        }.tabBar('red')
229      }
230      .vertical(true)
231      .scrollable(true)
232      .barMode(BarMode.Fixed)
233      .barWidth(70)
234      .barHeight(200)
235      .animationDuration(400)
236      .onChange((index: number) => {
237        console.info(index.toString())
238      })
239      .height('200vp')
240      .margin({ bottom: '12vp' })
241      .divider(this.nullFlag ? null : {
242        strokeWidth: this.strokeWidth,
243        color: this.dividerColor,
244        startMargin: this.startMargin,
245        endMargin: this.endMargin
246      })
247
248      Button ('Regular Divider').width('100%').margin({ bottom: '12vp'})
249        .onClick(() => {
250          this.nullFlag = false;
251          this.strokeWidth = 2;
252          this.dividerColor = 'red';
253          this.startMargin = 0;
254          this.endMargin = 0;
255        })
256      Button('Empty Divider').width('100%').margin({ bottom: '12vp' })
257        .onClick(() => {
258          this.nullFlag = true
259        })
260      Button('Change to Blue').width('100%').margin({ bottom: '12vp'})
261        .onClick(() => {
262          this.dividerColor = 'blue'
263        })
264      Button('Increase Width').width('100%').margin({ bottom: '12vp' })
265        .onClick(() => {
266          this.strokeWidth += 2
267        })
268      Button('Decrease Width').width('100%').margin({ bottom: '12vp'})
269        .onClick(() => {
270          if (this.strokeWidth > 2) {
271            this.strokeWidth -= 2
272          }
273        })
274      Button ('Increase Top Margin').width ('100%').margin ({ bottom:'12vp'})
275        .onClick(() => {
276          this.startMargin += 2
277        })
278      Button ('Decrease Top Margin').width ('100%').margin ({ bottom:'12vp' })
279        .onClick(() => {
280          if (this.startMargin > 2) {
281            this.startMargin -= 2
282          }
283        })
284      Button ('Increase Bottom Margin').width ('100%').margin ({ bottom:'12vp'})
285        .onClick(() => {
286          this.endMargin += 2
287        })
288      Button ('Decrease Bottom Margin').width ('100%').margin ({ bottom:'12vp' })
289        .onClick(() => {
290          if (this.endMargin > 2) {
291            this.endMargin -= 2
292          }
293        })
294    }.padding({ top: '24vp', left: '24vp', right: '24vp' })
295  }
296}
297```
298
299![tabs3](figures/tabs3.gif)
300
301### Example 3
302
303```ts
304// xxx.ets
305@Entry
306@Component
307struct TabsOpaque {
308  @State message: string = 'Hello World'
309  private controller: TabsController = new TabsController()
310  private controller1: TabsController = new TabsController()
311  @State selfFadingFade: boolean = true;
312
313  build() {
314    Column() {
315      Button (Set Tab to Fade').width ('100%').margin ({bottom: '12vp'})
316        .onClick((event?: ClickEvent) => {
317          this.selfFadingFade = true;
318        })
319      Button (Set Tab Not to Fade').width ('100%').margin ({bottom: '12vp'})
320        .onClick((event?: ClickEvent) => {
321          this.selfFadingFade = false;
322        })
323      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
324        TabContent() {
325          Column().width('100%').height('100%').backgroundColor(Color.Pink)
326        }.tabBar('pink')
327
328        TabContent() {
329          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
330        }.tabBar('yellow')
331
332        TabContent() {
333          Column().width('100%').height('100%').backgroundColor(Color.Blue)
334        }.tabBar('blue')
335
336        TabContent() {
337          Column().width('100%').height('100%').backgroundColor(Color.Green)
338        }.tabBar('green')
339
340        TabContent() {
341          Column().width('100%').height('100%').backgroundColor(Color.Green)
342        }.tabBar('green')
343
344        TabContent() {
345          Column().width('100%').height('100%').backgroundColor(Color.Green)
346        }.tabBar('green')
347
348        TabContent() {
349          Column().width('100%').height('100%').backgroundColor(Color.Green)
350        }.tabBar('green')
351
352        TabContent() {
353          Column().width('100%').height('100%').backgroundColor(Color.Green)
354        }.tabBar('green')
355      }
356      .vertical(false)
357      .scrollable(true)
358      .barMode(BarMode.Scrollable)
359      .barHeight(80)
360      .animationDuration(400)
361      .onChange((index: number) => {
362        console.info(index.toString())
363      })
364      .fadingEdge(this.selfFadingFade)
365      .height('30%')
366      .width('100%')
367
368      Tabs({ barPosition: BarPosition.Start, controller: this.controller1 }) {
369        TabContent() {
370          Column().width('100%').height('100%').backgroundColor(Color.Pink)
371        }.tabBar('pink')
372
373        TabContent() {
374          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
375        }.tabBar('yellow')
376
377        TabContent() {
378          Column().width('100%').height('100%').backgroundColor(Color.Blue)
379        }.tabBar('blue')
380
381        TabContent() {
382          Column().width('100%').height('100%').backgroundColor(Color.Green)
383        }.tabBar('green')
384
385        TabContent() {
386          Column().width('100%').height('100%').backgroundColor(Color.Green)
387        }.tabBar('green')
388
389        TabContent() {
390          Column().width('100%').height('100%').backgroundColor(Color.Green)
391        }.tabBar('green')
392      }
393      .vertical(true)
394      .scrollable(true)
395      .barMode(BarMode.Scrollable)
396      .barHeight(200)
397      .barWidth(80)
398      .animationDuration(400)
399      .onChange((index: number) => {
400        console.info(index.toString())
401      })
402      .fadingEdge(this.selfFadingFade)
403      .height('30%')
404      .width('100%')
405    }
406    .padding({ top: '24vp', left: '24vp', right: '24vp' })
407  }
408}
409```
410
411![tabs4](figures/tabs4.gif)
412
413### Example 4
414
415```ts
416// xxx.ets
417@Entry
418@Component
419struct barBackgroundColorTest {
420  private controller: TabsController = new TabsController()
421  @State barOverlap: boolean = true;
422  @State barBackgroundColor: string = '#88888888';
423
424  build() {
425    Column() {
426      Button ("Change barOverlap").width ('100%').margin ({ bottom:'12vp'})
427        .onClick((event?: ClickEvent) => {
428          if (this.barOverlap) {
429            this.barOverlap = false;
430          } else {
431            this.barOverlap = true;
432          }
433        })
434
435      Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.controller }) {
436        TabContent() {
437          Column() {
438            Text(`barOverlap ${this.barOverlap}`).fontSize(16).margin({ top: this.barOverlap ? '56vp' : 0 })
439            Text(`barBackgroundColor ${this.barBackgroundColor}`).fontSize(16)
440          }.width('100%').width('100%').height('100%')
441          .backgroundColor(Color.Pink)
442        }
443        .tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), "1"))
444
445        TabContent() {
446          Column() {
447            Text(`barOverlap ${this.barOverlap}`).fontSize(16).margin({ top: this.barOverlap ? '56vp' : 0 })
448            Text(`barBackgroundColor ${this.barBackgroundColor}`).fontSize(16)
449          }.width('100%').width('100%').height('100%')
450          .backgroundColor(Color.Yellow)
451        }
452        .tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), "2"))
453
454        TabContent() {
455          Column() {
456            Text(`barOverlap ${this.barOverlap}`).fontSize(16).margin({ top: this.barOverlap ? '56vp' : 0 })
457            Text(`barBackgroundColor ${this.barBackgroundColor}`).fontSize(16)
458          }.width('100%').width('100%').height('100%')
459          .backgroundColor(Color.Green)
460        }
461        .tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), "3"))
462      }
463      .vertical(false)
464      .barMode(BarMode.Fixed)
465      .height('60%')
466      .barOverlap(this.barOverlap)
467      .scrollable(true)
468      .animationDuration(10)
469      .barBackgroundColor(this.barBackgroundColor)
470    }
471    .height(500)
472    .padding({ top: '24vp', left: '24vp', right: '24vp' })
473  }
474}
475```
476
477![tabs5](figures/tabs5.gif)
478
479
480### Example 5
481
482```ts
483// xxx.ets
484@Entry
485@Component
486struct TabsExample5 {
487  private controller: TabsController = new TabsController()
488  @State gridMargin: number = 10
489  @State gridGutter: number = 10
490  @State sm: number = -2
491  @State clickedContent: string = "";
492
493  build() {
494    Column() {
495      Row() {
496        Button("gridMargin+10 " + this.gridMargin)
497          .width('47%')
498          .height(50)
499          .margin({ top: 5 })
500          .onClick((event?: ClickEvent) => {
501            this.gridMargin += 10
502          })
503          .margin({ right: '6%', bottom: '12vp' })
504        Button("gridMargin-10 " + this.gridMargin)
505          .width('47%')
506          .height(50)
507          .margin({ top: 5 })
508          .onClick((event?: ClickEvent) => {
509            this.gridMargin -= 10
510          })
511          .margin({ bottom: '12vp' })
512      }
513
514      Row() {
515        Button("gridGutter+10 " + this.gridGutter)
516          .width('47%')
517          .height(50)
518          .margin({ top: 5 })
519          .onClick((event?: ClickEvent) => {
520            this.gridGutter += 10
521          })
522          .margin({ right: '6%', bottom: '12vp' })
523        Button("gridGutter-10 " + this.gridGutter)
524          .width('47%')
525          .height(50)
526          .margin({ top: 5 })
527          .onClick((event?: ClickEvent) => {
528            this.gridGutter -= 10
529          })
530          .margin({ bottom: '12vp' })
531      }
532
533      Row() {
534        Button("sm+2 " + this.sm)
535          .width('47%')
536          .height(50)
537          .margin({ top: 5 })
538          .onClick((event?: ClickEvent) => {
539            this.sm += 2
540          })
541          .margin({ right: '6%' })
542        Button("sm-2 " + this.sm).width('47%').height(50).margin({ top: 5 })
543          .onClick((event?: ClickEvent) => {
544            this.sm -= 2
545          })
546      }
547
548      Text ("Tab clicks: "+ this.clickedContent).width ('100%').height (200).margin ({ top: 5 })
549
550
551      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
552        TabContent() {
553          Column().width('100%').height('100%').backgroundColor(Color.Pink)
554        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "1"))
555
556        TabContent() {
557          Column().width('100%').height('100%').backgroundColor(Color.Green)
558        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "2"))
559
560        TabContent() {
561          Column().width('100%').height('100%').backgroundColor(Color.Blue)
562        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "3"))
563      }
564      .width('350vp')
565      .animationDuration(300)
566      .height('60%')
567      .barGridAlign({ sm: this.sm, margin: this.gridMargin, gutter: this.gridGutter })
568      .backgroundColor(0xf1f3f5)
569      .onTabBarClick((index: number) => {
570        this.clickedContent += "index " + index + " was clicked\n";
571      })
572    }
573    .width('100%')
574    .height(500)
575    .margin({ top: 5 })
576    .padding('10vp')
577  }
578}
579```
580
581![tabs5](figures/tabs6.gif)
582
583### Example 6
584
585```ts
586// xxx.ets
587@Entry
588@Component
589struct TabsExample6 {
590  private controller: TabsController = new TabsController()
591  @State scrollMargin: number = 0
592  @State layoutStyle: LayoutStyle = LayoutStyle.ALWAYS_CENTER
593  @State text: string = "Text"
594
595  build() {
596    Column() {
597      Row() {
598        Button("scrollMargin+10 " + this.scrollMargin)
599          .width('47%')
600          .height(50)
601          .margin({ top: 5 })
602          .onClick((event?: ClickEvent) => {
603            this.scrollMargin += 10
604          })
605          .margin({ right: '6%', bottom: '12vp' })
606        Button("scrollMargin-10 " + this.scrollMargin)
607          .width('47%')
608          .height(50)
609          .margin({ top: 5 })
610          .onClick((event?: ClickEvent) => {
611            this.scrollMargin -= 10
612          })
613          .margin({ bottom: '12vp' })
614      }
615
616      Row() {
617        Button ("Add Text")
618          .width('47%')
619          .height(50)
620          .margin({ top: 5 })
621          .onClick((event?: ClickEvent) => {
622            this.text += 'Add Text'
623          })
624          .margin({ right: '6%', bottom: '12vp' })
625        Button ("Reset Text")
626          .width('47%')
627          .height(50)
628          .margin({ top: 5 })
629          .onClick((event?: ClickEvent) => {
630            this.text = "Text"
631          })
632          .margin({ bottom: '12vp' })
633      }
634
635      Row() {
636        Button("layoutStyle.ALWAYS_CENTER")
637          .width('100%')
638          .height(50)
639          .margin({ top: 5 })
640          .fontSize(15)
641          .onClick((event?: ClickEvent) => {
642            this.layoutStyle = LayoutStyle.ALWAYS_CENTER;
643          })
644          .margin({ bottom: '12vp' })
645      }
646
647      Row() {
648        Button("layoutStyle.ALWAYS_AVERAGE_SPLIT")
649          .width('100%')
650          .height(50)
651          .margin({ top: 5 })
652          .fontSize(15)
653          .onClick((event?: ClickEvent) => {
654            this.layoutStyle = LayoutStyle.ALWAYS_AVERAGE_SPLIT;
655          })
656          .margin({ bottom: '12vp' })
657      }
658
659      Row() {
660        Button("layoutStyle.SPACE_BETWEEN_OR_CENTER")
661          .width('100%')
662          .height(50)
663          .margin({ top: 5 })
664          .fontSize(15)
665          .onClick((event?: ClickEvent) => {
666            this.layoutStyle = LayoutStyle.SPACE_BETWEEN_OR_CENTER;
667          })
668          .margin({ bottom: '12vp' })
669      }
670
671      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
672        TabContent() {
673          Column().width('100%').height('100%').backgroundColor(Color.Pink)
674        }.tabBar(SubTabBarStyle.of(this.text))
675
676        TabContent() {
677          Column().width('100%').height('100%').backgroundColor(Color.Green)
678        }.tabBar(SubTabBarStyle.of(this.text))
679
680        TabContent() {
681          Column().width('100%').height('100%').backgroundColor(Color.Blue)
682        }.tabBar(SubTabBarStyle.of(this.text))
683      }
684      .animationDuration(300)
685      .height('60%')
686      .backgroundColor(0xf1f3f5)
687      .barMode(BarMode.Scrollable, { margin: this.scrollMargin, nonScrollableLayoutStyle: this.layoutStyle })
688    }
689    .width('100%')
690    .height(500)
691    .margin({ top: 5 })
692    .padding('24vp')
693  }
694}
695```
696
697![tabs5](figures/tabs7.gif)
698