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