1# TabContent 2 3The **\<TabContent>** component is used only in the **\<Tabs>** component. It corresponds to the content view of a switched tab page. 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 12This component supports only one child component. 13 14> **NOTE** 15> 16> Built-in components and custom components are allowed, with support for ([if/else](../../quick-start/arkts-rendering-control-ifelse.md), [ForEach](../../quick-start/arkts-rendering-control-foreach.md), and [LazyForEach](../../quick-start/arkts-rendering-control-lazyforeach.md)) rendering control. 17 18 19## APIs 20 21TabContent() 22 23 24## Attributes 25 26In addition to the [universal attributes](ts-universal-attributes-size.md), the following attributes are supported. 27 28| Name| Type| Description| 29| -------- | -------- | -------- | 30| tabBar | string \| [Resource](ts-types.md#resource) \|<br>[CustomBuilder](ts-types.md#custombuilder8)<sup>8+</sup>\| {<br>icon?: string \| [Resource](ts-types.md#resource),<br>text?: string \| [Resource](ts-types.md#resource)<br>} | Content displayed on the tab bar.<br>**CustomBuilder**: builder, to which components can be passed (applicable to API version 8 and later versions).<br>**NOTE**<br>When using an SVG image for the icon, delete the width and height attributes of the image. Otherwise, the icon size will be determined by the width and height attributes of the SVG image.<br>If the content set exceeds the space provided by the tab bar, it will be clipped.| 31| tabBar<sup>9+</sup> | [SubTabBarStyle](#subtabbarstyle9) \| [BottomTabBarStyle](#bottomtabbarstyle9) | Content displayed on the tab bar.<br>**SubTabBarStyle**: subtab style. It takes text as its input parameter.<br>**BottomTabBarStyle**: bottom and side tab style. It takes text and images as its input parameters.<br>**NOTE**<br>The bottom tab style does not include an indicator.<br>When an icon display error occurs, a gray blank block is displayed.| 32 33> **NOTE** 34> 35> - 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. 36> - The **\<TabContent>** component does not support setting of the universal height attribute. Its height is determined by the height of the parent **\<Tabs>** component and the **\<TabBar>** component. 37> - If the **vertical** attribute is **false**, the width and height descriptions are swapped in the preceding two restrictions. 38> - **\<TabContent>** does not support page scrolling. If page scrolling is required, consider nesting a list. 39 40## SubTabBarStyle<sup>9+</sup> 41 42Implements the subtab style. 43 44### constructor 45 46constructor(content: string | Resource) 47 48Constructor used to create a **SubTabBarStyle** instance. 49 50**Parameters** 51 52| Name| Type | Mandatory| Description| 53| -------- | -------- | -------- | -------- | 54| content | string \| [Resource](ts-types.md#resource) | Yes| Text for the tab. Since API version 10, the type of **content** is **ResourceStr**.| 55 56### of<sup>10+</sup> 57 58static of(content: ResourceStr) 59 60Static constructor used to create a **SubTabBarStyle** instance. 61 62**Parameters** 63 64| Name | Type | Mandatory| Description | 65| ------- | ------------------------------------------ | ---- | ------------------ | 66| content | [ResourceStr](ts-types.md#resourcestr) | Yes | Text for the tab.| 67 68### Attributes 69 70The following attributes are supported. 71 72| Name | Type | Description | 73| ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | 74| indicator<sup>10+</sup> | [IndicatorStyle](#indicatorstyle10)| Indicator style of the selected subtab. It is valid only in the horizontal layout.| 75| selectedMode<sup>10+</sup> | [SelectedMode](#selectedmode10) | Display mode of the selected subtab.<br>Default value: **SelectedMode.INDICATOR**| 76| board<sup>10+</sup> | [BoardStyle](#boardstyle10) | Board style of the selected subtab. This attribute applies only | 77| labelStyle<sup>10+</sup> | [LabelStyle](#labelstyle10) | Label text and font of the subtab.| 78| padding<sup>10+</sup> | [Padding](ts-types.md#padding) \| [Dimension](ts-types.md#dimension10) | Padding of the subtab. It cannot be set in percentage. When the parameter is of the Dimension type, the value applies to all sides.<br>Default value: **{left:8.0vp,right:8.0vp,top:17.0vp,bottom:18.0vp}**| 79| id<sup>11+</sup> | string | [ID](ts-universal-attributes-component-id.md#attributes) of the subtab.| 80 81## IndicatorStyle<sup>10+</sup> 82 83| Name| Type| Mandatory| Description| 84| -------- | -------- | -------- | -------------------------------- | 85| color | [ResourceColor](ts-types.md#resourcecolor) | No| Color of the indicator and board.<br>Default value: **#FF007DFF**| 86| height | [Length](ts-types.md#length) | No| Height of the indicator. It cannot be set in percentage.<br>Default value: **2.0**<br>Unit: vp| 87| width | [Length](ts-types.md#length) | No| Width of the indicator. It cannot be set in percentage.<br>Default value: **0.0**<br>Unit: vp<br>**NOTE**<br>If this parameter is set to **0**, the tab text width will be used instead.| 88| borderRadius | [Length](ts-types.md#length) | No| Rounded corner radius of the indicator. It cannot be set in percentage.<br>Default value: **0.0**<br>Unit: vp| 89| marginTop | [Length](ts-types.md#length) | No| Spacing between the indicator and text. It cannot be set in percentage.<br>Default value: **8.0**<br>Unit: vp| 90 91## SelectedMode<sup>10+</sup> 92| Name | Description | 93| ---------- | ------------------------ | 94| INDICATOR | Indicator mode. | 95| BOARD | Board mode. | 96 97## BoardStyle<sup>10+</sup> 98 99| Name| Type| Mandatory| Description| 100| -------- | -------- | -------- | ------------------------------------ | 101| borderRadius | [Length](ts-types.md#length) | No| Rounded corner radius of the board. It cannot be set in percentage.<br>Default value: **8.0**<br>Unit: vp| 102 103## LabelStyle<sup>10+</sup> 104 105| Name | Type | Mandatory| Description | 106| -------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 107| overflow | [TextOverflow](ts-appendix-enums.md#textoverflow) | No | Display mode when the label text is too long. By default, an ellipsis (...) is used to represent text overflow.| 108| maxLines | number | No | Maximum number of lines in the label text. If this attribute is specified, the text will not exceed the specified number of lines. You can use **textOverflow** to specify how to represent text overflow. Default value: **1**| 109| minFontSize | number \| [ResourceStr](ts-types.md#resourcestr) | No | Minimum font size of the label text. It cannot be set in percentage. For the setting to take effect, this attribute must be used together with **maxFontSize**, **maxLines**, or layout constraint settings. When the adaptive text size is set, **font.size** does not take effect. Default value: **0.0fp**| 110| maxFontSize | number \| [ResourceStr](ts-types.md#resourcestr) | No | Maximum font size of the label text. It cannot be set in percentage. For the setting to take effect, this attribute must be used together with **minFontSize**, **maxLines**, or layout constraint settings. When the adaptive text size is set, **font.size** does not take effect. Default value: **0.0fp**| 111| heightAdaptivePolicy | [TextHeightAdaptivePolicy](ts-appendix-enums.md#textheightadaptivepolicy10) | No | How the adaptive height is determined for the label text. By default, the **maxLines** settings are prioritized. | 112| font | [Font](ts-types.md#font) | No | Font of the label text.<br>When the tab is a subtab, the default font is in 16.0 fp size, 'HarmonyOS Sans' family, and normal font style and weight.<br>When the tab is a bottom tab, the default font is in 10.0 fp size, 'HarmonyOS Sans' family, normal font style, and medium weight. | 113 114## BottomTabBarStyle<sup>9+</sup> 115 116Implements the bottom and side tab style. 117 118### constructor 119 120constructor(icon: string | Resource, text: string | Resource) 121 122A constructor used to create a **BottomTabBarStyle** instance. 123 124**Parameters** 125 126| Name| Type | Mandatory| Description| 127| -------- | -------- | -------- | -------- | 128| icon | string \| [Resource](ts-types.md#resource) | Yes| Image for the tab. Since API version 10, the type of **icon** is **ResourceStr**.| 129| text | string \| [Resource](ts-types.md#resource) | Yes| Text for the tab. Since API version 10, the type of **text** is **ResourceStr**.| 130 131### of<sup>10+</sup> 132 133static of(icon: ResourceStr, text: ResourceStr) 134Static constructor used to create a **BottomTabBarStyle** instance. 135 136**Parameters** 137 138| Name| Type | Mandatory| Description| 139| -------- | -------- | -------- | -------- | 140| icon | [ResourceStr](ts-types.md#resourcestr) | Yes| Image for the tab.| 141| text | [ResourceStr](ts-types.md#resourcestr) | Yes| Text for the tab.| 142 143### Attributes 144 145The following attributes are supported. 146 147| Name | Type | Description | 148| ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | 149| padding<sup>10+</sup> | [Padding](ts-types.md#padding) \| [Dimension](ts-types.md#dimension10) | Padding of the bottom tab. It cannot be set in percentage. When the parameter is of the Dimension type, the value applies to all sides.<br>Default value: **{left:4.0vp,right:4.0vp,top:0.0vp,bottom:0.0vp}**| 150| verticalAlign<sup>10+</sup> | [VerticalAlign](ts-appendix-enums.md#verticalalign) | Vertical alignment mode of the images and text on the bottom tab.<br>Default value: **VerticalAlign.Center**| 151| layoutMode<sup>10+</sup> | [LayoutMode](#layoutmode10) | Layout of the images and text on the bottom tab. For details, see **LayoutMode**.<br>Default value: **LayoutMode.VERTICAL**| 152| symmetricExtensible<sup>10+</sup> | boolean | Whether the images and text on the bottom tab can be symmetrically extended by the minimum value of the available space on the left and right bottom tabs. This parameter is valid only between bottom tabs in fixed horizontal mode.<br>Default value: **false**| 153| labelStyle<sup>10+</sup> | [LabelStyle](#labelstyle10) | Label text and font of the bottom tab.| 154| id<sup>11+</sup> | string | [ID](ts-universal-attributes-component-id.md#attributes) of the bottom tab.| 155 156## LayoutMode<sup>10+</sup> 157 158| Name | Description | 159| ---------- | ---------------------------------------- | 160| AUTO | When the tab width is greater than 104 vp, the tab content is arranged from left to right. Otherwise,the tab content is arranged from top to bottom. This parameter is valid only when the tab bar is in vertical mode or fixed horizontal mode.| 161| VERTICAL | The tab content is arranged from top to bottom.| 162| HORIZONAL | The tab content is arranged from left to right.| 163 164 165## Example 166 167### Example 1 168 169```ts 170// xxx.ets 171@Entry 172@Component 173struct TabContentExample { 174 @State fontColor: string = '#182431' 175 @State selectedFontColor: string = '#007DFF' 176 @State currentIndex: number = 0 177 private controller: TabsController = new TabsController() 178 179 @Builder tabBuilder(index: number) { 180 Column() { 181 Image(this.currentIndex === index ? '/common/public_icon_on.svg' : '/common/public_icon_off.svg') 182 .width(24) 183 .height(24) 184 .margin({ bottom: 4 }) 185 .objectFit(ImageFit.Contain) 186 Text(`Tab${index + 1}`) 187 .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) 188 .fontSize(10) 189 .fontWeight(500) 190 .lineHeight(14) 191 }.width('100%') 192 } 193 194 build() { 195 Column() { 196 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 197 TabContent() { 198 Column() { 199 Text('Tab1') 200 .fontSize(36) 201 .fontColor('#182431') 202 .fontWeight(500) 203 .opacity(0.4) 204 .margin({ top: 30, bottom: 56.5 }) 205 Divider() 206 .strokeWidth(0.5) 207 .color('#182431') 208 .opacity(0.05) 209 }.width('100%') 210 }.tabBar(this.tabBuilder(0)) 211 212 TabContent() { 213 Column() { 214 Text('Tab2') 215 .fontSize(36) 216 .fontColor('#182431') 217 .fontWeight(500) 218 .opacity(0.4) 219 .margin({ top: 30, bottom: 56.5 }) 220 Divider() 221 .strokeWidth(0.5) 222 .color('#182431') 223 .opacity(0.05) 224 }.width('100%') 225 }.tabBar(this.tabBuilder(1)) 226 227 TabContent() { 228 Column() { 229 Text('Tab3') 230 .fontSize(36) 231 .fontColor('#182431') 232 .fontWeight(500) 233 .opacity(0.4) 234 .margin({ top: 30, bottom: 56.5 }) 235 Divider() 236 .strokeWidth(0.5) 237 .color('#182431') 238 .opacity(0.05) 239 }.width('100%') 240 }.tabBar(this.tabBuilder(2)) 241 242 TabContent() { 243 Column() { 244 Text('Tab4') 245 .fontSize(36) 246 .fontColor('#182431') 247 .fontWeight(500) 248 .opacity(0.4) 249 .margin({ top: 30, bottom: 56.5 }) 250 Divider() 251 .strokeWidth(0.5) 252 .color('#182431') 253 .opacity(0.05) 254 }.width('100%') 255 }.tabBar(this.tabBuilder(3)) 256 } 257 .vertical(false) 258 .barHeight(56) 259 .onChange((index: number) => { 260 this.currentIndex = index 261 }) 262 .width(360) 263 .height(190) 264 .backgroundColor('#F1F3F5') 265 .margin({ top: 38 }) 266 }.width('100%') 267 } 268} 269``` 270 271 272 273### Example 2 274 275```ts 276// xxx.ets 277@Entry 278@Component 279struct TabContentExample { 280 @State fontColor: string = '#182431' 281 @State selectedFontColor: string = '#007DFF' 282 @State currentIndex: number = 0 283 private controller: TabsController = new TabsController() 284 285 @Builder tabBuilder(index: number) { 286 Column() { 287 Image(this.currentIndex === index ? '/common/public_icon_on.svg' : '/common/public_icon_off.svg') 288 .width(24) 289 .height(24) 290 .margin({ bottom: 4 }) 291 .objectFit(ImageFit.Contain) 292 Text('Tab') 293 .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor) 294 .fontSize(10) 295 .fontWeight(500) 296 .lineHeight(14) 297 }.width('100%').height('100%').justifyContent(FlexAlign.Center) 298 } 299 300 build() { 301 Column() { 302 Tabs({ barPosition: BarPosition.Start, controller: this.controller }) { 303 TabContent() 304 .tabBar(this.tabBuilder(0)) 305 TabContent() 306 .tabBar(this.tabBuilder(1)) 307 TabContent() 308 .tabBar(this.tabBuilder(2)) 309 TabContent() 310 .tabBar(this.tabBuilder(3)) 311 } 312 .vertical(true) 313 .barWidth(96) 314 .barHeight(414) 315 .onChange((index: number) => { 316 this.currentIndex = index 317 }) 318 .width(96) 319 .height(414) 320 .backgroundColor('#F1F3F5') 321 .margin({ top: 52 }) 322 }.width('100%') 323 } 324} 325``` 326 327 328 329### Example 3 330 331```ts 332// xxx.ets 333@Entry 334@Component 335struct TabBarStyleExample { 336 build() { 337 Column({ space: 5 }) { 338 Text ("Subtab Style") 339 Column() { 340 Tabs({ barPosition: BarPosition.Start }) { 341 TabContent() { 342 Column().width('100%').height('100%').backgroundColor(Color.Pink) 343 }.tabBar(new SubTabBarStyle('Pink')) 344 345 TabContent() { 346 Column().width('100%').height('100%').backgroundColor(Color.Yellow) 347 }.tabBar(new SubTabBarStyle('Yellow')) 348 349 TabContent() { 350 Column().width('100%').height('100%').backgroundColor(Color.Blue) 351 }.tabBar(new SubTabBarStyle('Blue')) 352 353 TabContent() { 354 Column().width('100%').height('100%').backgroundColor(Color.Green) 355 }.tabBar(new SubTabBarStyle('Green')) 356 } 357 .vertical(false) 358 .scrollable(true) 359 .barMode(BarMode.Fixed) 360 .onChange((index: number) => { 361 console.info(index.toString()) 362 }) 363 .width('100%') 364 .backgroundColor(0xF1F3F5) 365 }.width('100%').height(200) 366 Text ("Bottom Tab Style") 367 Column() { 368 Tabs({ barPosition: BarPosition.End }) { 369 TabContent() { 370 Column().width('100%').height('100%').backgroundColor(Color.Pink) 371 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'pink')) 372 373 TabContent() { 374 Column().width('100%').height('100%').backgroundColor(Color.Yellow) 375 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Yellow')) 376 377 TabContent() { 378 Column().width('100%').height('100%').backgroundColor(Color.Blue) 379 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Blue')) 380 381 TabContent() { 382 Column().width('100%').height('100%').backgroundColor(Color.Green) 383 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Green')) 384 } 385 .vertical(false) 386 .scrollable(true) 387 .barMode(BarMode.Fixed) 388 .onChange((index: number) => { 389 console.info(index.toString()) 390 }) 391 .width('100%') 392 .backgroundColor(0xF1F3F5) 393 }.width('100%').height(200) 394 Text ("Side Tab Style") 395 Column() { 396 Tabs({ barPosition: BarPosition.Start }) { 397 TabContent() { 398 Column().width('100%').height('100%').backgroundColor(Color.Pink) 399 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'pink')) 400 401 TabContent() { 402 Column().width('100%').height('100%').backgroundColor(Color.Yellow) 403 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Yellow')) 404 405 TabContent() { 406 Column().width('100%').height('100%').backgroundColor(Color.Blue) 407 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Blue')) 408 409 TabContent() { 410 Column().width('100%').height('100%').backgroundColor(Color.Green) 411 }.tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), 'Green')) 412 } 413 .vertical(true).scrollable(true).barMode(BarMode.Fixed) 414 .onChange((index: number) => { 415 console.info(index.toString()) 416 }) 417 .width('100%') 418 .backgroundColor(0xF1F3F5) 419 }.width('100%').height(400) 420 } 421 } 422} 423``` 424 425 426 427### Example 4 428 429```ts 430// xxx.ets 431@Entry 432@Component 433struct TabsAttr { 434 private controller: TabsController = new TabsController() 435 @State indicatorColor: Color = Color.Blue; 436 @State indicatorWidth: number = 40; 437 @State indicatorHeight: number = 10; 438 @State indicatorBorderRadius: number = 5; 439 @State indicatorSpace: number = 10; 440 @State subTabBorderRadius: number = 20; 441 @State selectedMode: SelectedMode = SelectedMode.INDICATOR; 442 private colorFlag: boolean = true; 443 private widthFlag: boolean = true; 444 private heightFlag: boolean = true; 445 private borderFlag: boolean = true; 446 private spaceFlag: boolean = true; 447 448 build() { 449 Column() { 450 Button ("Change Indicator Color").width ('100%').margin ({ bottom:'12vp' }) 451 .onClick((event?: ClickEvent) => { 452 // Animation configuration for the width and height attributes of the <Button> component 453 if (this.colorFlag) { 454 animateTo({ 455 duration: 1000, // Animation duration. 456 curve: Curve.Linear, // Animation curve. 457 delay: 200, // Animation delay. 458 iterations: 1, // Number of playback times. 459 playMode: PlayMode.Normal, // Animation playback mode. 460 onFinish: () => { 461 console.info('play end') 462 } 463 }, () => { 464 this.indicatorColor = Color.Red 465 }) 466 } else { 467 animateTo({ 468 duration: 1000, // Animation duration. 469 curve: Curve.Linear, // Animation curve. 470 delay: 200, // Animation delay. 471 iterations: 1, // Number of playback times. 472 playMode: PlayMode.Normal, // Animation playback mode. 473 onFinish: () => { 474 console.info('play end') 475 } 476 }, () => { 477 this.indicatorColor = Color.Yellow 478 }) 479 } 480 this.colorFlag = !this.colorFlag 481 }) 482 Button("Change Indicator Height").width('100%').margin({ bottom: '12vp' }) 483 .onClick((event?: ClickEvent) => { 484 // Animation configuration for the width and height attributes of the <Button> component 485 if (this.heightFlag) { 486 animateTo({ 487 duration: 1000, // Animation duration. 488 curve: Curve.Linear, // Animation curve. 489 delay: 200, // Animation delay. 490 iterations: 1, // Number of playback times. 491 playMode: PlayMode.Normal, // Animation playback mode. 492 onFinish: () => { 493 console.info('play end') 494 } 495 }, () => { 496 this.indicatorHeight = 20 497 }) 498 } else { 499 animateTo({ 500 duration: 1000, // Animation duration. 501 curve: Curve.Linear, // Animation curve. 502 delay: 200, // Animation delay. 503 iterations: 1, // Number of playback times. 504 playMode: PlayMode.Normal, // Animation playback mode. 505 onFinish: () => { 506 console.info('play end') 507 } 508 }, () => { 509 this.indicatorHeight = 10 510 }) 511 } 512 this.heightFlag = !this.heightFlag 513 }) 514 Button("Change Indicator Width").width('100%').margin({ bottom: '12vp' }) 515 .onClick((event?: ClickEvent) => { 516 // Animation configuration for the width and height attributes of the <Button> component 517 if (this.widthFlag) { 518 animateTo({ 519 duration: 1000, // Animation duration. 520 curve: Curve.Linear, // Animation curve. 521 delay: 200, // Animation delay. 522 iterations: 1, // Number of playback times. 523 playMode: PlayMode.Normal, // Animation playback mode. 524 onFinish: () => { 525 console.info('play end') 526 } 527 }, () => { 528 this.indicatorWidth = 30 529 }) 530 } else { 531 animateTo({ 532 duration: 1000, // Animation duration. 533 curve: Curve.Linear, // Animation curve. 534 delay: 200, // Animation delay. 535 iterations: 1, // Number of playback times. 536 playMode: PlayMode.Normal, // Animation playback mode. 537 onFinish: () => { 538 console.info('play end') 539 } 540 }, () => { 541 this.indicatorWidth = 50 542 }) 543 } 544 this.widthFlag = !this.widthFlag 545 }) 546 Button ("Change Indicator Corner Radius").width ('100%').margin ({ bottom:'12vp' }) 547 .onClick((event?: ClickEvent) => { 548 // Animation configuration for the width and height attributes of the <Button> component 549 if (this.borderFlag) { 550 animateTo({ 551 duration: 1000, // Animation duration. 552 curve: Curve.Linear, // Animation curve. 553 delay: 200, // Animation delay. 554 iterations: 1, // Number of playback times. 555 playMode: PlayMode.Normal, // Animation playback mode. 556 onFinish: () => { 557 console.info('play end') 558 } 559 }, () => { 560 this.indicatorBorderRadius = 0 561 }) 562 } else { 563 animateTo({ 564 duration: 1000, // Animation duration. 565 curve: Curve.Linear, // Animation curve. 566 delay: 200, // Animation delay. 567 iterations: 1, // Number of playback times. 568 playMode: PlayMode.Normal, // Animation playback mode. 569 onFinish: () => { 570 console.info('play end') 571 } 572 }, () => { 573 this.indicatorBorderRadius = 5 574 }) 575 } 576 this.borderFlag = !this.borderFlag 577 }) 578 Button ("Change Indicator Spacing").width ('100%').margin ({ bottom:'12vp' }) 579 .onClick((event?: ClickEvent) => { 580 // Animation configuration for the width and height attributes of the <Button> component 581 if (this.spaceFlag) { 582 animateTo({ 583 duration: 1000, // Animation duration. 584 curve: Curve.Linear, // Animation curve. 585 delay: 200, // Animation delay. 586 iterations: 1, // Number of playback times. 587 playMode: PlayMode.Normal, // Animation playback mode. 588 onFinish: () => { 589 console.info('play end') 590 } 591 }, () => { 592 this.indicatorSpace = 20 593 }) 594 } else { 595 animateTo({ 596 duration: 1000, // Animation duration. 597 curve: Curve.Linear, // Animation curve. 598 delay: 200, // Animation delay. 599 iterations: 1, // Number of playback times. 600 playMode: PlayMode.Normal, // Animation playback mode. 601 onFinish: () => { 602 console.info('play end') 603 } 604 }, () => { 605 this.indicatorSpace = 10 606 }) 607 } 608 this.spaceFlag = !this.spaceFlag 609 }) 610 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 611 TabContent() { 612 Column().width('100%').height('100%').backgroundColor(Color.Pink).borderRadius('12vp') 613 }.tabBar(SubTabBarStyle.of('pink') 614 .indicator({ 615 color: this.indicatorColor, // Indicator color. 616 height: this.indicatorHeight, // Indicator height. 617 width: this.indicatorWidth, // Indicator width. 618 borderRadius: this.indicatorBorderRadius, // Rounded corner radius of the indicator. 619 marginTop: this.indicatorSpace // Spacing between the indicator and text. 620 }) 621 .selectedMode(this.selectedMode) 622 .board({ borderRadius: this.subTabBorderRadius }) 623 .labelStyle({}) 624 ) 625 626 TabContent() { 627 Column().width('100%').height('100%').backgroundColor(Color.Yellow).borderRadius('12vp') 628 }.tabBar('yellow') 629 630 TabContent() { 631 Column().width('100%').height('100%').backgroundColor(Color.Blue).borderRadius('12vp') 632 }.tabBar('blue') 633 634 TabContent() { 635 Column().width('100%').height('100%').backgroundColor(Color.Green).borderRadius('12vp') 636 }.tabBar('green') 637 638 TabContent() { 639 Column().width('100%').height('100%').backgroundColor(Color.Gray).borderRadius('12vp') 640 }.tabBar('gray') 641 642 TabContent() { 643 Column().width('100%').height('100%').backgroundColor(Color.Orange).borderRadius('12vp') 644 }.tabBar('orange') 645 } 646 .vertical(false) 647 .scrollable(true) 648 .barMode(BarMode.Scrollable) 649 .barHeight(140) 650 .animationDuration(400) 651 .onChange((index: number) => { 652 console.info(index.toString()) 653 }) 654 .backgroundColor(0xF5F5F5) 655 .height(320) 656 }.width('100%').height(250).padding({ top: '24vp', left: '24vp', right: '24vp' }) 657 } 658} 659``` 660 661 662 663### Example 5 664 665```ts 666// xxx.ets 667@Entry 668@Component 669struct TabsTextOverflow { 670 @State message: string = 'Hello World' 671 private controller: TabsController = new TabsController() 672 @State subTabOverflowOpaque: boolean = true; 673 build() { 674 Column() { 675 Tabs({ barPosition: BarPosition.Start, controller: this.controller }) { 676 TabContent() { 677 Column(){ 678 Text('Use an ellipsis').fontSize(30).fontColor(0xFF000000) 679 }.width('100%').height('100%').backgroundColor(Color.Pink) 680 }.tabBar (SubTabBarStyle.of ('Start [Use an ellipsis] End') 681 .labelStyle({ overflow: TextOverflow.Ellipsis, maxLines: 1, minFontSize: 10, heightAdaptivePolicy: TextHeightAdaptivePolicy.MAX_LINES_FIRST, 682 font: { size: 20 } })) 683 TabContent() { 684 Column() 685 { 686 Text('Scale down and then clip').fontSize(30).fontColor(0xFF000000) 687 }.width('100%').height('100%').backgroundColor(Color.Pink) 688 }.tabBar (SubTabBarStyle.of ('Start [Scale down and then clip; Scale down and then clip] End') 689 .labelStyle({ overflow: TextOverflow.Clip, maxLines: 1, minFontSize: 15, maxFontSize: 15, heightAdaptivePolicy: TextHeightAdaptivePolicy.MIN_FONT_SIZE_FIRST, 690 font: { size: 20 } })) 691 TabContent() { 692 Column(){ 693 Text('Scale down, start a new line, and then clip').fontSize(30).fontColor(0xFF000000) 694 }.width('100%').height('100%').backgroundColor(Color.Pink) 695 }.tabBar (SubTabBarStyle.of ('Start [Scale down, start a new line, and then clip; Scale down, start a new line, and then clip] End') 696 .labelStyle({ overflow: TextOverflow.Clip, maxLines: 2, minFontSize: 15, maxFontSize: 15, heightAdaptivePolicy: TextHeightAdaptivePolicy.MIN_FONT_SIZE_FIRST, 697 font: { size: 20 } })) 698 TabContent() { 699 Column() { 700 Text('Start a new line').fontSize(30).fontColor(0xFF000000) 701 } 702 .width('100%').height('100%').backgroundColor(Color.Pink) 703 }.tabBar(SubTabBarStyle.of('Start [Start a new line; Start a new line; Start a new line; Start a new line; Start a new line] End') 704 .labelStyle({ overflow: TextOverflow.Clip, maxLines: 10, minFontSize: 10, heightAdaptivePolicy: TextHeightAdaptivePolicy.MAX_LINES_FIRST, 705 font: { size: 20 } })) 706 } 707 .vertical(true).scrollable(true) 708 .barMode(BarMode.Fixed) 709 .barHeight(720) 710 .barWidth(200).animationDuration(400) 711 .onChange((index: number) => { 712 console.info(index.toString()) 713 }) 714 .height('100%').width('100%') 715 } 716 .height('100%') 717 } 718} 719``` 720 721 722 723### Example 6 724 725```ts 726// xxx.ets 727@Entry 728@Component 729struct TabContentExample6 { 730 private controller: TabsController = new TabsController() 731 @State text: string = "2" 732 @State tabPadding: number = 0; 733 @State symmetricExtensible: boolean = false; 734 @State layoutMode: LayoutMode = LayoutMode.VERTICAL; 735 @State verticalAlign: VerticalAlign = VerticalAlign.Center; 736 737 build() { 738 Column() { 739 Row() { 740 Button("padding+10 " + this.tabPadding) 741 .width('47%') 742 .height(50) 743 .margin({ top: 5 }) 744 .onClick((event?: ClickEvent) => { 745 this.tabPadding += 10 746 }) 747 .margin({ right: '6%', bottom: '12vp' }) 748 Button("padding-10 " + this.tabPadding) 749 .width('47%') 750 .height(50) 751 .margin({ top: 5 }) 752 .onClick((event?: ClickEvent) => { 753 this.tabPadding -= 10 754 }) 755 .margin({ bottom: '12vp' }) 756 } 757 758 Row() { 759 Button ("Add Text") 760 .width('47%') 761 .height(50) 762 .margin({ top: 5 }) 763 .onClick((event?: ClickEvent) => { 764 this.text += 'Add Text' 765 }) 766 .margin({ right: '6%', bottom: '12vp' }) 767 Button ("Reset Text") 768 .width('47%') 769 .height(50) 770 .margin({ top: 5 }) 771 .onClick((event?: ClickEvent) => { 772 this.text = "2" 773 }) 774 .margin({ bottom: '12vp' }) 775 } 776 777 Row() { 778 Button ("Set SymmetricExtensible to " + this.symmetricExtensible) 779 .width('100%') 780 .height(50) 781 .margin({ top: 5 }) 782 .onClick((event?: ClickEvent) => { 783 this.symmetricExtensible = !this.symmetricExtensible 784 }) 785 .margin({ bottom: '12vp' }) 786 } 787 788 Row() { 789 Button ("Vertical Layout") 790 .width('47%') 791 .height(50) 792 .margin({ top: 5 }) 793 .onClick((event?: ClickEvent) => { 794 this.layoutMode = LayoutMode.VERTICAL; 795 }) 796 .margin({ right: '6%', bottom: '12vp' }) 797 Button ("horizontal Layout") 798 .width('47%') 799 .height(50) 800 .margin({ top: 5 }) 801 .onClick((event?: ClickEvent) => { 802 this.layoutMode = LayoutMode.HORIZONTAL; 803 }) 804 .margin({ bottom: '12vp' }) 805 } 806 807 Row() { 808 Button ("VerticalAlign.Top") 809 .width('100%') 810 .height(50) 811 .margin({ top: 5 }) 812 .onClick((event?: ClickEvent) => { 813 this.verticalAlign = VerticalAlign.Top; 814 }) 815 .margin({ bottom: '12vp' }) 816 } 817 818 Row() { 819 Button ("VerticalAlign.Center") 820 .width('100%') 821 .height(50) 822 .margin({ top: 5 }) 823 .onClick((event?: ClickEvent) => { 824 this.verticalAlign = VerticalAlign.Center; 825 }) 826 .margin({ bottom: '12vp' }) 827 } 828 829 Row() { 830 Button ("VerticalAlign.Bottom") 831 .width('100%') 832 .height(50) 833 .margin({ top: 5 }) 834 .onClick((event?: ClickEvent) => { 835 this.verticalAlign = VerticalAlign.Bottom; 836 }) 837 .margin({ bottom: '12vp' }) 838 } 839 840 841 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 842 TabContent() { 843 Column().width('100%').height('100%').backgroundColor(Color.Pink) 844 }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "1")) 845 846 TabContent() { 847 Column().width('100%').height('100%').backgroundColor(Color.Green) 848 }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), this.text) 849 .padding(this.tabPadding) 850 .verticalAlign(this.verticalAlign) 851 .layoutMode(this.layoutMode) 852 .symmetricExtensible(this.symmetricExtensible)) 853 854 TabContent() { 855 Column().width('100%').height('100%').backgroundColor(Color.Blue) 856 }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "3")) 857 } 858 .animationDuration(300) 859 .height('60%') 860 .backgroundColor(0xf1f3f5) 861 .barMode(BarMode.Fixed) 862 } 863 .width('100%') 864 .height(500) 865 .margin({ top: 5 }) 866 .padding('24vp') 867 } 868} 869``` 870 871 872