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) => 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) => 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 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 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 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 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 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 698