• 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>  Since API version 11, this component supports the safe area attribute by default, with the default attribute value being **expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])**. You can override this attribute to change the default behavior. In earlier versions, you need to use the [expandSafeArea](ts-universal-attributes-expand-safe-area.md) attribute to implement the safe area feature.
10
11
12## Child Components
13
14Custom components cannot be used as child components. Only the [TabContent](ts-container-tabcontent.md) child component is allowed, with support for [if/else](../../../quick-start/arkts-rendering-control-ifelse.md) and [ForEach](../../../quick-start/arkts-rendering-control-foreach.md) rendering control. In addition, the **if/else** and **ForEach** statements support **TabContent** components only, but not custom components.
15
16>  **NOTE**
17>
18>  If the child component has the **visibility** attribute set to **None** or **Hidden**, it is hidden but still takes up space in the layout.
19>
20>  The **TabContent** child component is not destroyed once it is displayed. If you need to implement lazy loading and resource release of pages, see [Example 12](#example-12-implementing-lazy-loading-and-resource-release-of-pages).
21
22
23## APIs
24
25Tabs(options?: TabsOptions)
26
27Create a **Tabs** container.
28
29**Atomic service API**: This API can be used in atomic services since API version 11.
30
31**System capability**: SystemCapability.ArkUI.ArkUI.Full
32
33**Parameters**
34
35| Name| Type        | Mandatory| Description|
36| -------- | -------- | -------- | -------- |
37| options | [TabsOptions](#tabsoptions15) | No| Options of the **Tabs** component.|
38
39## TabsOptions<sup>15+</sup>
40
41Provides parameters for configuring the **Tabs** component, including tab positions, the current index of the displayed tab, the **Tabs** controller, and [universal attributes](ts-component-general-attributes.md) for the **TabBar**.
42
43**System capability**: SystemCapability.ArkUI.ArkUI.Full
44
45| Name        | Type                             | Mandatory  | Description                                    |
46| ----------- | --------------------------------- | ---- | ---------------------------------------- |
47| barPosition<sup>7+</sup> | [BarPosition](#barposition)| No   | Position of the **Tabs** component.<br>Default value: **BarPosition.Start**<br>**Atomic service API**: This API can be used in atomic services since API version 11.  |
48| index<sup>7+</sup>       | 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** nodes minus 1.<br>When the tab is switched by changing the index, the tab switching animation does not take effect. When **changeIndex** of **TabController** is used for tab switching, the tab switching animation is enabled by default. You can disable the animation by setting **animationDuration** to **0**.<br>Since API version 10, this parameter supports two-way binding through [$$](../../../quick-start/arkts-two-way-sync.md).<br>When the **Tabs** component is rebuilt, system resources are switched (for example, system font or theme changes), or component attributes change, the **Tab** component will switch to the one specified by **index**. To prevent this behavior, you are advised to use two-way binding.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
49| controller<sup>7+</sup>  | [TabsController](#tabscontroller) | No   | Tab controller.<br>**Atomic service API**: This API can be used in atomic services since API version 11.        |
50| barModifier<sup>15+</sup>  | [CommonModifier](#commonmodifier15) | No   | [Universal attributes](ts-component-general-attributes.md) of the tab bar.<br>**NOTE**<br>If this parameter is dynamically set to **undefined**, the current state will be preserved, and universal attributes will not be reset.<br>If the setting switches from one **CommonModifier** to another, overlapping attributes will be overwritten, while non-overlapping attributes will coexist without resetting the attributes of the previous **CommonModifier**.<br>The [barWidth](#barwidth), [barHeight](#barheight), [barBackgroundColor](#barbackgroundcolor10), [barBackgroundBlurStyle](#barbackgroundblurstyle15), and [barBackgroundEffect] (#barbackgroundeffect15) attributes of **Tabs** will overwrite the [width](ts-universal-attributes-size.md#width), [height](ts-universal-attributes-size.md#height), [backgroundColor](ts-universal-attributes-background.md#backgroundcolor18), [backgroundBlurStyle](ts-universal-attributes-background.md#backgroundblurstyle18), and [backgroundEffect](ts-universal-attributes-background.md#backgroundeffect18) attributes of **CommonModifier**.<br>The [align](ts-universal-attributes-location.md#align) attribute works only in [BarMode.Scrollable](#barmode10-1) mode. In addition, for a horizontal **Tabs** component, it only takes effect when [nonScrollableLayoutStyle](#scrollablebarmodeoptions10) is set to an invalid value or is not set.<br>When set to the bottom tab style, [tabBar](ts-container-tabcontent.md#tabbar18) attribute of the [TabContent](ts-container-tabcontent.md) component does not support the dragging feature.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
51
52## BarPosition
53
54Enumerates the positions of the **Tabs** component.
55
56**Atomic service API**: This API can be used in atomic services since API version 11.
57
58**System capability**: SystemCapability.ArkUI.ArkUI.Full
59
60| Name | Description                                                        |
61| ----- | ------------------------------------------------------------ |
62| 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.|
63| 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.|
64
65
66## Attributes
67
68In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported.
69
70### vertical
71
72vertical(value: boolean)
73
74Sets whether to use vertical tabs.
75
76**Atomic service API**: This API can be used in atomic services since API version 11.
77
78**System capability**: SystemCapability.ArkUI.ArkUI.Full
79
80**Parameters**
81
82| Name| Type   | Mandatory| Description                                                        |
83| ------ | ------- | ---- | ------------------------------------------------------------ |
84| value  | boolean | Yes  | Whether to use vertical tabs.<br>The value **true** means to use vertical tabs, and **false** means to use horizontal tabs.<br>Default value: **false**<br>If set to have a height of **auto**, horizontal tabs auto-adapt the height to child components, which is calculated as follows: Tab bar height + Divider width + Tab content height + Top and bottom paddings + Top and bottom border widths.<br>If set to have a width of **auto**, vertical tabs auto-adapt the width to child components, which is calculated as follows: Tab bar width + Divider width + Tab content width + Left and right paddings + Left and right border widths.<br>To avoid animation jitter when switching between tabs, maintain a consistent size for child components on each tab.|
85
86### scrollable
87
88scrollable(value: boolean)
89
90Sets whether the tabs are scrollable.
91
92**Atomic service API**: This API can be used in atomic services since API version 11.
93
94**System capability**: SystemCapability.ArkUI.ArkUI.Full
95
96**Parameters**
97
98| Name| Type   | Mandatory| Description                                                        |
99| ------ | ------- | ---- | ------------------------------------------------------------ |
100| value  | boolean | Yes  | Whether the tabs are scrollable.<br>**true** (default): The tabs are scrollable.<br> **false**: The tabs are not scrollable.|
101
102### barMode
103
104barMode(value: BarMode, options?: ScrollableBarModeOptions)
105
106Sets the tab bar layout mode.
107
108**Atomic service API**: This API can be used in atomic services since API version 11.
109
110**System capability**: SystemCapability.ArkUI.ArkUI.Full
111
112**Parameters**
113
114| Name               | Type                                                        | Mandatory| Description                                                        |
115| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
116| value                 | [BarMode](#barmode)                                  | Yes  | Layout mode.<br>Default value: **BarMode.Fixed**                                                |
117| options<sup>10+</sup> | [ScrollableBarModeOptions](#scrollablebarmodeoptions10)| No  | Layout style of the tab bar in scrollable mode.<br>**NOTE**<br>This parameter is effective only when the tab bar is in horizontal scrollable mode.|
118
119### barMode<sup>10+</sup>
120
121barMode(value: BarMode.Fixed)
122
123Sets the tab bar layout mode to **BarMode.Fixed**.
124
125**Atomic service API**: This API can be used in atomic services since API version 11.
126
127**System capability**: SystemCapability.ArkUI.ArkUI.Full
128
129**Parameters**
130
131| Name   | Type                            | Mandatory| Description                                   |
132| -------- | -------------------------------- | ---- | ------------------------------------ |
133| value    | [BarMode.Fixed](#barmode)| Yes  | 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).  |
134
135### barMode<sup>10+</sup>
136
137barMode(value: BarMode.Scrollable, options: ScrollableBarModeOptions)
138
139Sets the tab bar layout mode to **BarMode.Scrollable**.
140
141**Atomic service API**: This API can be used in atomic services since API version 11.
142
143**System capability**: SystemCapability.ArkUI.ArkUI.Full
144
145**Parameters**
146
147| Name   | Type                             | Mandatory| Description                                   |
148| -------- | --------------------------------- | ---- | ------------------------------------- |
149| value    | [BarMode.Scrollable](#barmode)| Yes  | 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 vertical layout, the total height exceeds the tab bar height.       |
150| options | [ScrollableBarModeOptions](#scrollablebarmodeoptions10)| Yes  | Layout style of the tab bar in scrollable mode.<br>**NOTE**<br>This parameter is effective only when the tab bar is in scrollable mode. |
151
152### barWidth
153
154barWidth(value: Length)
155
156Sets the width of the tab bar. If the set value is less than 0 or greater than the width of the **Tabs** component, the default value is used.
157
158**Atomic service API**: This API can be used in atomic services since API version 11.
159
160**System capability**: SystemCapability.ArkUI.ArkUI.Full
161
162**Parameters**
163
164| Name| Type                                     | Mandatory| Description                                                        |
165| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
166| value  | [Length](ts-types.md#length)<sup>8+</sup> | Yes  | Width of the tab bar.<br>Default value:<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 neither **SubTabBarStyle** nor **BottomTabBarStyle** is set, and the **vertical** attribute is **true**, the default value is 56 vp.<br>If **SubTabBarStyle** is set, and the **vertical** attribute is **false**, the default value is the width of the **Tabs** component.<br>If **SubTabBarStyle** is set, and the **vertical** attribute is **true**, the default value is 56 vp.<br>If **BottomTabBarStyle** is set, and the **vertical** attribute is **true**, the default value is 96 vp.<br>If **BottomTabBarStyle** is set, and the **vertical** attribute is **false**, the default value is the width of the **Tabs** component.|
167
168### barHeight
169
170barHeight(value: Length)
171
172Sets the height of the tab bar. If this attribute is set to **'auto'**, which takes effect only in horizontal mode, the tab bar adapts to the height of its child components. If the set value is less than 0 or greater than the height of the **Tabs** component, the default value is used.
173
174In versions earlier than API version 14, setting **barHeight** to a fixed value restricts the tab bar from extending beyond the bottom safe area. Since API version 14, the [safeAreaPadding](./ts-universal-attributes-size.md#safeareapadding14) attribute is supported. When **safeAreaPadding** is set to 0 or is not explicitly set, the tab bar is allowed to extend beyond the bottom safe area.
175
176**Atomic service API**: This API can be used in atomic services since API version 11.
177
178**System capability**: SystemCapability.ArkUI.ArkUI.Full
179
180**Parameters**
181
182| Name| Type                                     | Mandatory| Description                                                        |
183| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
184| value  | [Length](ts-types.md#length)<sup>8+</sup> | Yes  | Height of the tab bar.<br>Default value:<br>If the tab bar has the **vertical** attribute set to **false** and does not have a style specified, the default value is 56 vp.<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 [SubTabBarStyle](ts-container-tabcontent.md#subtabbarstyle9) is set, and the **vertical** attribute is **false**, the default value is 56 vp.<br>If **SubTabBarStyle** is set, and the **vertical** attribute is **true**, the default value is the height of the **Tabs** component.<br>If [BottomTabBarStyle](ts-container-tabcontent.md#bottomtabbarstyle9) is set, and the **vertical** attribute is **true**, the default value is the height of the **Tabs** component.<br>If **BottomTabBarStyle** is set, and the **vertical** attribute is **false**, the default value is 56 vp in versions earlier than API version 12 and 48 vp since API version 12.|
185
186### animationDuration
187
188animationDuration(value: number)
189
190Sets the length of time required to complete the tab switching animation, which is initiated by clicking a specific tab or by calling the **changeIndex** API of **TabsController**. This parameter cannot be set in percentage.
191
192**Atomic service API**: This API can be used in atomic services since API version 11.
193
194**System capability**: SystemCapability.ArkUI.ArkUI.Full
195
196**Parameters**
197
198| Name| Type  | Mandatory| Description                                                        |
199| ------ | ------ | ---- | ------------------------------------------------------------ |
200| value  | number | Yes  | Length of time required to complete the tab switching animation, which is initiated by clicking a specific tab or by calling the **changeIndex** API of **TabsController**.<br>The default value varies.<br>API version 10 and earlier versions: If this parameter is set to **null** or is not set, the default value **0** is used, which means that no tab switching animation is displayed when a specific tab is clicked or the **changeIndex** API of **TabsController** is called. If this parameter is set to **undefined** or a value less than 0, the default value **300** is used.<br>API version 11 and later versions: If this parameter is set to an invalid value or is not set, the default value is **0** when the tab bar is set to **BottomTabBarStyle** and **300** when the tab bar is set to any other style.<br>Unit: ms<br>Value range: [0, +∞)|
201
202### animationMode<sup>12+</sup>
203
204animationMode(mode: Optional\<AnimationMode\>)
205
206Sets the animation mode for tab switching initiated by clicking a specific tab or by calling the **changeIndex** API of **TabsController**.
207
208**Atomic service API**: This API can be used in atomic services since API version 12.
209
210**System capability**: SystemCapability.ArkUI.ArkUI.Full
211
212**Parameters**
213
214| Name| Type  | Mandatory| Description                                                        |
215| ------ | ------ | ---- | ------------------------------------------------------------ |
216| mode  | Optional\<[AnimationMode](#animationmode12)\>| Yes  | Animation mode for tab switching initiated by clicking a specific tab or by calling the **changeIndex** API of **TabsController**.<br>Default value: **AnimationMode.CONTENT_FIRST**, which means the target page content is loaded first, followed by the animation.|
217
218### barPosition<sup>9+</sup>
219
220barPosition(value: BarPosition)
221
222Sets the position of the **Tabs** component.
223
224**Atomic service API**: This API can be used in atomic services since API version 11.
225
226**System capability**: SystemCapability.ArkUI.ArkUI.Full
227
228**Parameters**
229
230| Name| Type                              | Mandatory| Description                 |
231| ----- | ---------------------------------- | ---- | -------------------- |
232| value | [BarPosition](#barposition)| Yes | Position of the **Tabs** component.<br>Default value: **BarPosition.Start**  |
233
234### divider<sup>10+</sup>
235
236divider(value: DividerStyle | null)
237
238Sets the divider between the **TabBar** and **TabContent** components.
239
240**Atomic service API**: This API can be used in atomic services since API version 11.
241
242**System capability**: SystemCapability.ArkUI.ArkUI.Full
243
244**Parameters**
245
246| Name| Type                                                     | Mandatory| Description                                                        |
247| ------ | --------------------------------------------------------- | ---- | ------------------------------------------------------------ |
248| value  | [DividerStyle](#dividerstyle10) \| null | Yes  | Divider style. By default, the divider is not displayed.<br>**DividerStyle**: divider style.<br>**null**: The divider is not displayed.|
249
250### fadingEdge<sup>10+</sup>
251
252fadingEdge(value: boolean)
253
254Sets whether the tab fades out when it exceeds the container width. 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.
255
256**Atomic service API**: This API can be used in atomic services since API version 11.
257
258**System capability**: SystemCapability.ArkUI.ArkUI.Full
259
260**Parameters**
261
262| Name| Type   | Mandatory| Description                                              |
263| ------ | ------- | ---- | -------------------------------------------------- |
264| value  | boolean | Yes  | Whether the tab fades out when it exceeds the container width.<br>Default value: **true**, indicating that the tab fades out when it exceeds the container width|
265
266### barOverlap<sup>10+</sup>
267
268barOverlap(value: boolean)
269
270Sets whether the tab bar is superimposed on the **TabContent** component after having its background blurred.
271
272**Atomic service API**: This API can be used in atomic services since API version 11.
273
274**System capability**: SystemCapability.ArkUI.ArkUI.Full
275
276**Parameters**
277
278| Name| Type   | Mandatory| Description                                                        |
279| ------ | ------- | ---- | ------------------------------------------------------------ |
280| value  | boolean | Yes  | Whether the tab bar is superimposed on the **TabContent** component after having its background blurred. When **barOverlap** is set to **true**, the default value of **BlurStyle** for the **TabBar** is automatically changed to **'BlurStyle.COMPONENT_THICK'**.<br>Default value: **false**|
281
282### barBackgroundColor<sup>10+</sup>
283
284barBackgroundColor(value: ResourceColor)
285
286Background color of the tab bar.
287
288**Atomic service API**: This API can be used in atomic services since API version 11.
289
290**System capability**: SystemCapability.ArkUI.ArkUI.Full
291
292**Parameters**
293
294| Name| Type                                      | Mandatory| Description                                |
295| ------ | ------------------------------------------ | ---- | ------------------------------------ |
296| value  | [ResourceColor](ts-types.md#resourcecolor) | Yes  | Background color of the tab bar.<br>Default value: **Color.Transparent**|
297
298### barBackgroundBlurStyle<sup>11+</sup>
299
300barBackgroundBlurStyle(value: BlurStyle)
301
302Sets the background blur style of the tab bar.
303
304**Atomic service API**: This API can be used in atomic services since API version 11.
305
306**System capability**: SystemCapability.ArkUI.ArkUI.Full
307
308**Parameters**
309
310| Name| Type                                        | Mandatory| Description                                    |
311| ------ | -------------------------------------------- | ---- | ---------------------------------------- |
312| value  | [BlurStyle](ts-universal-attributes-background.md#blurstyle9) | Yes  | Background blur style of the tab bar.<br>Default value: **BlurStyle.NONE**|
313
314### barBackgroundBlurStyle<sup>15+</sup>
315
316barBackgroundBlurStyle(style: BlurStyle, options: BackgroundBlurStyleOptions)
317
318Defines the blur style to apply between the background and content of a tab bar. It encapsulates various blur radius, mask color, mask opacity, saturation, and brightness values through enum values.
319
320**Atomic service API**: This API can be used in atomic services since API version 15.
321
322**System capability**: SystemCapability.ArkUI.ArkUI.Full
323
324**Parameters**
325
326| Name               | Type                                                        | Mandatory| Description                                                        |
327| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
328| style                 | [BlurStyle](ts-universal-attributes-background.md#blurstyle9)                 | Yes  | Settings of the background blur style, including the blur radius, mask color, mask opacity, saturation, and brightness.|
329| options | [BackgroundBlurStyleOptions](ts-universal-attributes-background.md#backgroundblurstyleoptions10) | Yes  | Background blur options.
330
331### barGridAlign<sup>10+</sup>
332
333barGridAlign(value: BarGridColumnOptions)
334
335Sets the 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).
336
337**Atomic service API**: This API can be used in atomic services since API version 11.
338
339**System capability**: SystemCapability.ArkUI.ArkUI.Full
340
341**Parameters**
342
343| Name| Type                                                   | Mandatory| Description                              |
344| ------ | ------------------------------------------------------- | ---- | ---------------------------------- |
345| value  | [BarGridColumnOptions](#bargridcolumnoptions10) | Yes  | Visible area of the tab bar in grid mode.|
346
347### edgeEffect<sup>12+</sup>
348
349edgeEffect(edgeEffect: Optional&lt;EdgeEffect&gt;)
350
351Sets the edge effect used when the boundary of the scrolling area is reached.
352
353**Atomic service API**: This API can be used in atomic services since API version 12.
354
355**System capability**: SystemCapability.ArkUI.ArkUI.Full
356
357**Parameters**
358
359| Name| Type                                         | Mandatory| Description                                        |
360| ------ | --------------------------------------------- | ---- | -------------------------------------------- |
361| edgeEffect  | Optional&lt;[EdgeEffect](ts-appendix-enums.md#edgeeffect)&gt; | Yes  | Effect used when the boundary of the scrolling area is reached.<br>Default value: **EdgeEffect.Spring**|
362
363### barBackgroundEffect<sup>15+</sup>
364
365barBackgroundEffect(options: BackgroundEffectOptions)
366
367Sets the background effect of the tab bar, including the blur radius, brightness, saturation, and color.
368
369**Atomic service API**: This API can be used in atomic services since API version 15.
370
371**System capability**: SystemCapability.ArkUI.ArkUI.Full
372
373**Parameters**
374
375| Name | Type                                                        | Mandatory| Description                                      |
376| ------- | ------------------------------------------------------------ | ---- | ------------------------------------------ |
377| options | [BackgroundEffectOptions](ts-universal-attributes-background.md#backgroundeffectoptions11) | Yes  | Background effect options, including the blur radius, brightness, saturation, and color.|
378
379### pageFlipMode<sup>15+</sup>
380
381pageFlipMode(mode: Optional\<PageFlipMode>)
382
383Sets the mode for flipping pages using the mouse wheel.
384
385**Atomic service API**: This API can be used in atomic services since API version 15.
386
387**System capability**: SystemCapability.ArkUI.ArkUI.Full
388
389**Parameters**
390
391| Name| Type                                                       | Mandatory| Description                                                        |
392| ------ | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ |
393| mode  | Optional\<[PageFlipMode](ts-appendix-enums.md#pageflipmode15)> | Yes  | Mode for flipping pages using the mouse wheel.<br>Default value: **PageFlipMode.CONTINUOUS**|
394
395## DividerStyle<sup>10+</sup>
396
397Describes the divider style.
398
399**Atomic service API**: This API can be used in atomic services since API version 11.
400
401**System capability**: SystemCapability.ArkUI.ArkUI.Full
402
403| Name         | Type                                    | Mandatory  | Description                                      |
404| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
405| strokeWidth | [Length](ts-types.md#length)             | Yes   | Width of the divider. It cannot be set in percentage.<br>Default value: **0.0**<br>Unit: vp<br>Value range: [0, +∞)          |
406| color       | [ResourceColor](ts-types.md#resourcecolor) | No   | Color of the divider.<br>Default value: **#33182431**               |
407| 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<br>Value range: [0, +∞)|
408| 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<br>Value range: [0, +∞)|
409
410## BarGridColumnOptions<sup>10+</sup>
411
412Implements a **BarGridColumnOptions** object for setting the visible area of the tab bar in grid mode, including the column margin and gutter, as well as the number of columns occupied by tabs under small, medium, and large screen sizes.
413
414**Atomic service API**: This API can be used in atomic services since API version 11.
415
416**System capability**: SystemCapability.ArkUI.ArkUI.Full
417
418| Name         | Type                                    | Mandatory  | Description                                      |
419| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
420| 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                       |
421| 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                    |
422| 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.|
423| 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.|
424| 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.|
425
426## ScrollableBarModeOptions<sup>10+</sup>
427
428Implements a **ScrollableBarModeOptions** object.
429
430**Atomic service API**: This API can be used in atomic services since API version 11.
431
432**System capability**: SystemCapability.ArkUI.ArkUI.Full
433
434| Name         | Type                                    | Mandatory  | Description                                      |
435| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
436| 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<br>Value range: [0, +∞)|
437| nonScrollableLayoutStyle      | [LayoutStyle](#layoutstyle10) | No   | Tab layout mode of the tab bar when not scrolling in scrollable mode.<br>Default value: **LayoutStyle.ALWAYS_CENTER**          |
438
439## BarMode
440
441Enumerates layout modes of the tab bar.
442
443**Atomic service API**: This API can be used in atomic services since API version 11.
444
445**System capability**: SystemCapability.ArkUI.ArkUI.Full
446
447| Name       | Value| Description                                    |
448| ---------- | -- | ---------------------------------------- |
449| Scrollable | 0  | 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 vertical layout, the total height exceeds the tab bar height.|
450| Fixed      | 1  | 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).|
451
452## AnimationMode<sup>12+</sup>
453
454Enumerates the animation modes for switching between tabs.
455
456**System capability**: SystemCapability.ArkUI.ArkUI.Full
457
458| Name         | Value  | Description                                                        |
459| ------------- | ---- | ------------------------------------------------------------ |
460| CONTENT_FIRST | 0    | Load the content of the target page before starting the switching animation.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
461| ACTION_FIRST  | 1    | Start the switching animation before loading the content of the target page. For the settings to take effect, the height and width of tabs must be set to **auto**.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
462| NO_ANIMATION  | 2    | Disable the default switching animation. This value is ineffective when **TabContent** is switched using the **changeIndex** API of **TabsController**.<br>To disable the animation under this scenario, set **animationDuration** to **0**.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
463| CONTENT_FIRST_WITH_JUMP<sup>15+</sup> | 3    | Load the content of the target page first, then jump to the vicinity of the target page without animation, and finally jump to the target page with animation.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
464| ACTION_FIRST_WITH_JUMP<sup>15+</sup>  | 4    | Jump to the vicinity of the target page without animation first, then jump to the target page with animation, and finally load the content of the target page. For the settings to take effect, the height and width of tabs must be set to **auto**.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
465
466## LayoutStyle<sup>10+</sup>
467
468Enumerates the tab layout styles of the tab bar when not scrolling in scrollable mode.
469
470**Atomic service API**: This API can be used in atomic services since API version 11.
471
472**System capability**: SystemCapability.ArkUI.ArkUI.Full
473
474| Name        | Value| Description                                    |
475| ---------- | -- | ---------------------------------------- |
476| ALWAYS_CENTER | 0 | If the tab content exceeds the tab bar width, the tabs are scrollable.<br>If not, the tabs are compactly centered on the tab bar and not scrollable.|
477| ALWAYS_AVERAGE_SPLIT | 1 | If the tab content exceeds the tab bar width, the tabs are scrollable.<br>If not, the tabs are not scrollable, and the width of the tab bar is evenly distributed among all tabs.|
478| SPACE_BETWEEN_OR_CENTER      | 2 | If the tab content exceeds the tab bar width, the tabs are scrollable.<br>If the tab content exceeds half the width of the tab bar but is still within the tab bar width, the tabs are compactly centered and not scrollable.<br>If the tab content does not exceed half the width of the tab bar, the tabs are centered within half the width of the tab bar with even spacing between them and are not scrollable.|
479
480## CommonModifier<sup>15+</sup>
481
482type CommonModifier = CommonModifier
483
484Defines a parameter object for the **Tabs** component.
485
486**Atomic service API**: This API can be used in atomic services since API version 15.
487
488**System capability**: SystemCapability.ArkUI.ArkUI.Full
489
490| Type        | Description                                    |
491| ---------- | ---------------------------------------- |
492| [CommonModifier](ts-universal-attributes-attribute-modifier.md#attributemodifier) | Universal attributes for the tab bar.|
493
494## Events
495
496In addition to the [universal events](ts-component-general-events.md), the following events are supported.
497
498### onChange
499
500onChange(event: Callback\<number>)
501
502Triggered when a tab is switched.
503
504This event is triggered when any of the following conditions is met:
505
5061. The swiping animation is completed, followed by tab switching.
507
5082. The [Controller](#tabscontroller) API is called.
509
5103. The attribute value is updated using a [state variable](../../../quick-start/arkts-state.md).
511
5124. A tab is clicked.
513
514>  **NOTE**
515>
516>  When a custom tab is used, the synchronization between tabs and swipe gestures in the **onChange** event may be performed only after tab switching occurs. This can lead to a delay in switching to the custom tab. To address this issue, listen for the current tab index in [onAnimationStart](#onanimationstart11) and update the tab index accordingly. For details about the implementation, see [Example 1](#example-1-setting-up-custom-tab-switching-synchronization).
517
518**Atomic service API**: This API can be used in atomic services since API version 11.
519
520**System capability**: SystemCapability.ArkUI.ArkUI.Full
521
522**Parameters**
523
524| Name| Type  | Mandatory| Description                                  |
525| ------ | ------ | ---- | -------------------------------------- |
526| event  | [Callback](./ts-types.md#callback12)\<number> | Yes  | Index of the active tab. The index starts from 0.|
527
528### onTabBarClick<sup>10+</sup>
529
530onTabBarClick(event: Callback\<number>)
531
532Triggered when a tab is clicked.
533
534**Atomic service API**: This API can be used in atomic services since API version 11.
535
536**System capability**: SystemCapability.ArkUI.ArkUI.Full
537
538**Parameters**
539
540| Name| Type  | Mandatory| Description                                |
541| ------ | ------ | ---- | ------------------------------------ |
542| event  | [Callback](./ts-types.md#callback12)\<number> | Yes  | Index of the clicked tab. The index starts from 0.|
543
544### onAnimationStart<sup>11+</sup>
545
546onAnimationStart(handler: OnTabsAnimationStartCallback)
547
548Triggered when the tab switching animation starts. This callback is not triggered when **animationDuration** is set to **0**, which effectively disables the animation.
549
550**Atomic service API**: This API can be used in atomic services since API version 12.
551
552**System capability**: SystemCapability.ArkUI.ArkUI.Full
553
554**Parameters**
555
556| Name| Type  | Mandatory| Description                |
557| ------ | ------ | ---- | -------------------- |
558| handler  | [OnTabsAnimationStartCallback](#ontabsanimationstartcallback18) | Yes  | Callback triggered when the switching animation starts.|
559
560### onAnimationEnd<sup>11+</sup>
561
562onAnimationEnd(handler: OnTabsAnimationEndCallback)
563
564Triggered when the tab switching animation ends. This event is triggered when the tab switching animation ends, whether it is caused by gesture interruption or not. This callback is not triggered when **animationDuration** is set to **0**, which effectively disables the animation.
565
566**Atomic service API**: This API can be used in atomic services since API version 12.
567
568**System capability**: SystemCapability.ArkUI.ArkUI.Full
569
570**Parameters**
571
572| Name| Type  | Mandatory| Description                |
573| ------ | ------ | ---- | -------------------- |
574| handler  | [OnTabsAnimationEndCallback](#ontabsanimationendcallback18) | Yes  | Callback triggered when the switching animation ends.|
575
576### onGestureSwipe<sup>11+</sup>
577
578onGestureSwipe(handler: OnTabsGestureSwipeCallback)
579
580Triggered on a frame-by-frame basis when the tab is switched by a swipe.
581
582**Atomic service API**: This API can be used in atomic services since API version 12.
583
584**System capability**: SystemCapability.ArkUI.ArkUI.Full
585
586**Parameters**
587
588| Name| Type  | Mandatory| Description                |
589| ------ | ------ | ---- | -------------------- |
590| handler  | [OnTabsGestureSwipeCallback](#ontabsgestureswipecallback18) | Yes  | Triggered on a frame-by-frame basis when the page is turned by a swipe.|
591
592### customContentTransition<sup>11+</sup>
593
594customContentTransition(delegate: TabsCustomContentTransitionCallback)
595
596Sets the custom tab switching animation.
597
598Instructions:
599
6001. When the custom tab switching animation is used, the default switching animation of the **Tabs** component is disabled, and tabs cannot be switched through swiping.<br>2. The value **undefined** means not to use the custom tab switching animation, in which case the default switching animation is used.<br>3. The custom tab switching animation cannot be interrupted.<br>4. Currently, the custom tab switching animation can be triggered only by clicking a tab or by calling the **TabsController.changeIndex()** API.<br>5. When the custom tab switching animation is used, the **Tabs** component supports all events except **onGestureSwipe**.<br>6. Notes about the **onChange** and **onAnimationEnd** events: If the second custom animation is triggered during the execution of the first custom animation, the **onChange** and **onAnimationEnd** events of the first custom animation will be triggered when the second custom animation starts.<br>7. When the custom animation is used, the stack layout is used for pages involved in the animation. If the **zIndex** attribute is not set for related pages, the **zIndex** values of all pages are the same. In this case, the pages are rendered in the order in which they are added to the component tree (that is, the sequence of page indexes). In light of this, to control the rendering levels of pages, set the **zIndex** attribute of the pages.
601
602**Atomic service API**: This API can be used in atomic services since API version 12.
603
604**System capability**: SystemCapability.ArkUI.ArkUI.Full
605
606**Parameters**
607
608| Name| Type  | Mandatory| Description                |
609| ------ | ------ | ---- | -------------------- |
610| delegate  | [TabsCustomContentTransitionCallback](#tabscustomcontenttransitioncallback18) | Yes  | Callback invoked when the custom tab switching animation starts.|
611
612
613### onContentWillChange<sup>12+</sup>
614
615onContentWillChange(handler: OnTabsContentWillChangeCallback)
616
617Triggered when a new page is about to be displayed.
618
619Specifically, this event is triggered in the following cases:
620
6211. When the user swipes on the **TabContent** component (provided that it supports swiping) to switch to a new page.
622
6232. When **TabsController.changeIndex** is called to switch to a new page.
624
6253. When the **index** attribute is changed to switch to a new page.
626
6274. When the user clicks a tab on the tab bar to switch to a new page.
628
6295. When the user presses the left or right arrow key on the keyboard to switch to a new page while the tab bar is focused.
630
631**Atomic service API**: This API can be used in atomic services since API version 12.
632
633**System capability**: SystemCapability.ArkUI.ArkUI.Full
634
635**Parameters**
636
637| Name| Type  | Mandatory| Description                |
638| ------ | ------ | ---- | -------------------- |
639| handler  | [OnTabsContentWillChangeCallback](#ontabscontentwillchangecallback18) | Yes  | Callback invoked when a new page is about to be displayed.|
640
641### onSelected<sup>18+</sup>
642
643onSelected(event: Callback\<number>)
644
645Triggered when the selected element changes. The index of the currently selected element is returned.
646
647This event is triggered under the following conditions:
648
6491. When the page switching animation starts after the user lifts their finger after swiping and the swipe meets the threshold for page turning.
650
6512. The API of [TabsController](#tabscontroller) is called.
652
6533. The attribute value is updated using a [state variable](../../../quick-start/arkts-state.md).
654
6554. A tab is clicked.
656
657**Atomic service API**: This API can be used in atomic services since API version 18.
658
659**System capability**: SystemCapability.ArkUI.ArkUI.Full
660
661**Parameters**
662
663| Name| Type  | Mandatory| Description                                  |
664| ------ | ------ | ---- | -------------------------------------- |
665| event  | [Callback](./ts-types.md#callback12)\<number> | Yes  | Index of the currently selected element.|
666
667> **NOTE**
668>
669> In the **onSelected** callback, the index of the current displayed page cannot be set using **index** of **TabsOptions**, and **TabsController.changeIndex()** cannot be called.
670
671### onUnselected<sup>18+</sup>
672
673onUnselected(event: Callback\<number>)
674
675Triggered when the selected element changes. The index of the element that is about to be hidden is returned.
676
677This event is triggered under the following conditions:
678
6791. When the page switching animation starts after the user lifts their finger after swiping and the swipe meets the threshold for page turning.
680
6812. The API of [TabsController](#tabscontroller) is called.
682
6833. The attribute value is updated using a [state variable](../../../quick-start/arkts-state.md).
684
6854. A tab is clicked.
686
687**Atomic service API**: This API can be used in atomic services since API version 18.
688
689**System capability**: SystemCapability.ArkUI.ArkUI.Full
690
691**Parameters**
692
693| Name| Type  | Mandatory| Description                                  |
694| ------ | ------ | ---- | -------------------------------------- |
695| event  | [Callback](./ts-types.md#callback12)\<number> | Yes  | Index of the element that is about to be hidden.|
696
697> **NOTE**
698>
699> In the **onUnselected** callback, the index of the current displayed page cannot be set using **index** of **TabsOptions**, and **TabsController.changeIndex()** cannot be called.
700
701## OnTabsAnimationStartCallback<sup>18+</sup>
702
703type OnTabsAnimationStartCallback = (index: number, targetIndex: number, extraInfo: TabsAnimationEvent) => void
704
705Defines the callback triggered when the switching animation starts.
706
707**Atomic service API**: This API can be used in atomic services since API version 18.
708
709**System capability**: SystemCapability.ArkUI.ArkUI.Full
710
711**Parameters**
712
713| Name     | Type                                                  | Mandatory| Description                                                        |
714| ----------- | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
715| index       | number                                                 | Yes  | Index of the currently displayed element. The index is zero-based.                            |
716| targetIndex | number                                                 | Yes  | Index of the target element to switch to. The index is zero-based.                        |
717| extraInfo       | [TabsAnimationEvent](#tabsanimationevent11) | Yes  | Extra information of the animation, including the offset of the currently displayed element and target element relative to the start position of the **Tabs** along the main axis, and the hands-off velocity.|
718
719## OnTabsAnimationEndCallback<sup>18+</sup>
720
721type OnTabsAnimationEndCallback = (index: number, extraInfo: TabsAnimationEvent) => void
722
723Defines the callback triggered when the switching animation ends.
724
725**Atomic service API**: This API can be used in atomic services since API version 18.
726
727**System capability**: SystemCapability.ArkUI.ArkUI.Full
728
729**Parameters**
730
731| Name| Type                                                  | Mandatory| Description                                                        |
732| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
733| index  | number                                                 | Yes  | Index of the currently displayed element. The index is zero-based.                                   |
734| extraInfo  | [TabsAnimationEvent](#tabsanimationevent11) | Yes  | Extra information of the animation, which is the offset of the currently displayed element relative to the start position of the **Tabs** along the main axis.|
735
736## OnTabsGestureSwipeCallback<sup>18+</sup>
737
738type OnTabsGestureSwipeCallback = (index: number, extraInfo: TabsAnimationEvent) => void
739
740Defines the callback invoked on a frame-by-frame basis when the page is turned by a swipe.
741
742**Atomic service API**: This API can be used in atomic services since API version 18.
743
744**System capability**: SystemCapability.ArkUI.ArkUI.Full
745
746**Parameters**
747
748| Name| Type                                                  | Mandatory| Description                                                        |
749| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
750| index  | number                                                 | Yes  | Index of the currently displayed element. The index is zero-based.                                   |
751| extraInfo  | [TabsAnimationEvent](#tabsanimationevent11) | Yes  | Extra information of the animation, which is the offset of the currently displayed element relative to the start position of the **Tabs** along the main axis.|
752
753## TabsCustomContentTransitionCallback<sup>18+</sup>
754
755type TabsCustomContentTransitionCallback = (from: number, to: number) => TabContentAnimatedTransition | undefined
756
757Defines the callback invoked when the custom tab switching animation starts.
758
759**Atomic service API**: This API can be used in atomic services since API version 18.
760
761**System capability**: SystemCapability.ArkUI.ArkUI.Full
762
763**Parameters**
764
765| Name| Type  | Mandatory| Description                           |
766| ------ | ------ | ---- | ------------------------------- |
767| from   | number | Yes  | Index of the currently displayed tab before the animation starts. The index is zero-based.|
768| to     | number | Yes  | Index of the target tab before the animation starts. The index is zero-based.|
769
770**Return value**
771
772| Type                                                        | Description                    |
773| ------------------------------------------------------------ | ------------------------ |
774| [TabContentAnimatedTransition](#tabcontentanimatedtransition11) \| undefined | Information about the custom tab switching animation.|
775
776## OnTabsContentWillChangeCallback<sup>18+</sup>
777
778type OnTabsContentWillChangeCallback = (currentIndex: number, comingIndex: number) => boolean
779
780Defines the callback invoked when a new page is about to be displayed.
781
782**Atomic service API**: This API can be used in atomic services since API version 18.
783
784**System capability**: SystemCapability.ArkUI.ArkUI.Full
785
786**Parameters**
787
788| Name      | Type  | Mandatory| Description                                      |
789| ------------ | ------ | ---- | ------------------------------------------ |
790| currentIndex | number | Yes  | Index of the active tab. The index starts from 0.|
791| comingIndex  | number | Yes  | Index of the new tab to be displayed.             |
792
793**Return value**
794
795| Type   | Description                                                        |
796| ------- | ------------------------------------------------------------ |
797| boolean | The value **true** means that the tab can switch to the new page.<br>The value **false** means that the tab cannot switch to the new page and will remain on the current page.|
798
799## TabsAnimationEvent<sup>11+</sup>
800
801Describes the animation information of the **Tabs** component.
802
803**Atomic service API**: This API can be used in atomic services since API version 12.
804
805**System capability**: SystemCapability.ArkUI.ArkUI.Full
806
807| Name           | Type     | Read Only| Optional| Description                                      |
808| ------------- | ---------- | ---- | ---- | ------------------------ |
809| currentOffset | number | No| No| Offset of the currently displayed element relative to the start position of the **Tabs** component along the main axis.<br> Unit: vp<br>Default value: **0**|
810| targetOffset | number | No| No| Offset of the target element relative to the start position of the **Tabs** component along the main axis.<br> Unit: vp<br>Default value: **0**|
811| velocity | number | No| No| Hands-off velocity at the beginning of the animation. Unit: VP/S<br>Default value: **0**|
812
813## TabContentAnimatedTransition<sup>11+</sup>
814
815Provides the information about the custom tab page switching animation.
816
817**Widget capability**: This API can be used in ArkTS widgets since API version 11.
818
819**Atomic service API**: This API can be used in atomic services since API version 12.
820
821**System capability**: SystemCapability.ArkUI.ArkUI.Full
822
823| Name           | Type        | Mandatory  | Description                                      |
824| ------------- | ---------------------- | ---- |---------------------- |
825| timeout | number | No| Timeout for the custom switching animation. The timer starts when the switching begins. If this timeframe passes without you calling the **finishTransition** API in [TabContentTransitionProxy](#tabcontenttransitionproxy11), the component will assume that the custom animation has ended and will proceed directly with subsequent operations.<br>Default value: **1000**<br>Unit: ms<br>Value range: [0, +∞)|
826| transition | [Callback](./ts-types.md#callback12)\<[TabContentTransitionProxy](#tabcontenttransitionproxy11)> | Yes| Content of the custom switching animation.|
827
828## TabContentTransitionProxy<sup>11+</sup>
829
830Implements the proxy object returned during the execution of the custom switching animation of the **Tabs** component. You can use this object to obtain the start and target pages for the custom tab switching animation. In addition, you can call the **finishTransition** API of this object to notify the **Tabs** component of the ending of the custom animation.
831
832**Widget capability**: This API can be used in ArkTS widgets since API version 11.
833
834**Atomic service API**: This API can be used in atomic services since API version 12.
835
836**System capability**: SystemCapability.ArkUI.ArkUI.Full
837
838### Attributes
839
840| Name | Type    | Read Only| Optional| Description                        |
841| ----- | ------- | ---- | ---- | --------------------------- |
842| from | number | No| No| Index of the starting page of the custom animation.|
843| to | number | No| No| Index of the target tab to switch to.|
844
845### finishTransition
846
847finishTransition(): void
848
849Notifies the **Tabs** component that the custom animation has finished playing.
850
851**Widget capability**: This API can be used in ArkTS widgets since API version 11.
852
853**Atomic service API**: This API can be used in atomic services since API version 12.
854
855**System capability**: SystemCapability.ArkUI.ArkUI.Full
856
857## TabsController
858
859Defines a tab controller, which is used to control switching of tabs. One **TabsController** cannot control multiple **Tabs** components.
860
861**Atomic service API**: This API can be used in atomic services since API version 11.
862
863**System capability**: SystemCapability.ArkUI.ArkUI.Full
864
865### Objects to Import
866
867```ts
868let controller: TabsController = new TabsController()
869```
870
871### constructor
872
873constructor()
874
875A constructor used to create a **TabsController** object.
876
877**Atomic service API**: This API can be used in atomic services since API version 11.
878
879**System capability**: SystemCapability.ArkUI.ArkUI.Full
880
881### changeIndex
882
883changeIndex(value: number): void
884
885Switches to the specified tab.
886
887**Atomic service API**: This API can be used in atomic services since API version 11.
888
889**System capability**: SystemCapability.ArkUI.ArkUI.Full
890
891**Parameters**
892
893| Name  | Type  | Mandatory  | Description                                    |
894| ----- | ------ | ---- | ---------------------------------------- |
895| 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.|
896
897### preloadItems<sup>12+</sup>
898
899preloadItems(indices: Optional\<Array\<number>>): Promise\<void>
900
901Preloads child nodes. After this API is called, all specified child nodes will be loaded at once. Therefore, for performance considerations, it is recommended that you load child nodes in batches.
902
903**Atomic service API**: This API can be used in atomic services since API version 12.
904
905**System capability**: SystemCapability.ArkUI.ArkUI.Full
906
907**Parameters**
908
909| Name  | Type  | Mandatory  | Description                                    |
910| ----- | ------ | ---- | ---------------------------------------- |
911| indices | Optional\<Array\<number>> | Yes| Array of indexes of the child nodes to preload.<br>The default value is an empty array.|
912
913**Return value**
914
915| Type                                                        | Description                    |
916| ------------------------------------------------------------ | ------------------------ |
917| Promise\<void> | Promise used to return the value.|
918
919**Error codes**
920
921For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md).
922
923| ID  | Error Message                                     |
924| --------   | -------------------------------------------- |
925| 401 | Parameter invalid. Possible causes: 1. The parameter type is not Array\<number>; 2. The parameter is an empty array; 3. The parameter contains an invalid index. |
926
927### setTabBarTranslate<sup>13+</sup>
928
929setTabBarTranslate(translate: TranslateOptions): void
930
931Sets the translation distance of the tab bar.
932
933> **NOTE**
934>
935> When **bindTabsToScrollable** or **bindTabsToNestedScrollable** is used to bind the **Tabs** component with a scrollable container, scrolling the container will trigger the display and hide animations of the tab bar for all **Tabs** components bound to it. In this case, calling the **setTabBarTranslate** API has no effect. Therefore, avoid using **bindTabsToScrollable**, **bindTabsToNestedScrollable**, and **setTabBarTranslate** simultaneously.
936>
937
938**Atomic service API**: This API can be used in atomic services since API version 13.
939
940**System capability**: SystemCapability.ArkUI.ArkUI.Full
941
942**Parameters**
943
944| Name  | Type  | Mandatory  | Description                                    |
945| ----- | ------ | ---- | ---------------------------------------- |
946| translate | [TranslateOptions](ts-universal-attributes-transformation.md#translateoptions) | Yes| Translation distance of the tab bar.|
947
948### setTabBarOpacity<sup>13+</sup>
949
950setTabBarOpacity(opacity: number): void
951
952Sets the opacity of the tab bar.
953
954> **NOTE**
955>
956> When **bindTabsToScrollable** or **bindTabsToNestedScrollable** is used to bind the **Tabs** component with a scrollable container, scrolling the container will trigger the display and hide animations of the tab bar for all **Tabs** components bound to it. In this case, calling the **setTabBarOpacity** API has no effect. Therefore, avoid using **bindTabsToScrollable**, **bindTabsToNestedScrollable**, and **setTabBarOpacity** simultaneously.
957>
958
959**Atomic service API**: This API can be used in atomic services since API version 13.
960
961**System capability**: SystemCapability.ArkUI.ArkUI.Full
962
963**Parameters**
964
965| Name  | Type  | Mandatory  | Description                                    |
966| ----- | ------ | ---- | ---------------------------------------- |
967| opacity | number | Yes| Opacity of the tab bar. The value range is [0.0, 1.0].|
968
969## Example
970
971### Example 1: Setting Up Custom Tab Switching Synchronization
972
973This example demonstrates how to use **onAnimationStart** and **onChange** to synchronize tabs with swiping gestures during tab switching.
974
975```ts
976// xxx.ets
977@Entry
978@Component
979struct TabsExample {
980  @State fontColor: string = '#182431'
981  @State selectedFontColor: string = '#007DFF'
982  @State currentIndex: number = 0
983  @State selectedIndex: number = 0
984  private controller: TabsController = new TabsController()
985
986  @Builder tabBuilder(index: number, name: string) {
987    Column() {
988      Text(name)
989        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
990        .fontSize(16)
991        .fontWeight(this.selectedIndex === index ? 500 : 400)
992        .lineHeight(22)
993        .margin({ top: 17, bottom: 7 })
994      Divider()
995        .strokeWidth(2)
996        .color('#007DFF')
997        .opacity(this.selectedIndex === index ? 1 : 0)
998    }.width('100%')
999  }
1000
1001  build() {
1002    Column() {
1003      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
1004        TabContent() {
1005          Column().width('100%').height('100%').backgroundColor('#00CB87')
1006        }.tabBar(this.tabBuilder(0, 'green'))
1007
1008        TabContent() {
1009          Column().width('100%').height('100%').backgroundColor('#007DFF')
1010        }.tabBar(this.tabBuilder(1, 'blue'))
1011
1012        TabContent() {
1013          Column().width('100%').height('100%').backgroundColor('#FFBF00')
1014        }.tabBar(this.tabBuilder(2, 'yellow'))
1015
1016        TabContent() {
1017          Column().width('100%').height('100%').backgroundColor('#E67C92')
1018        }.tabBar(this.tabBuilder(3, 'pink'))
1019      }
1020      .vertical(false)
1021      .barMode(BarMode.Fixed)
1022      .barWidth(360)
1023      .barHeight(56)
1024      .animationDuration(400)
1025      .onChange((index: number) => {
1026        // currentIndex controls which tab is displayed.
1027        this.currentIndex = index
1028        this.selectedIndex = index
1029      })
1030      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
1031        if (index === targetIndex) {
1032          return
1033        }
1034        // selectedIndex controls the color switching for the image and text in the custom tab bar.
1035        this.selectedIndex = targetIndex
1036      })
1037      .width(360)
1038      .height(296)
1039      .margin({ top: 52 })
1040      .backgroundColor('#F1F3F5')
1041    }.width('100%')
1042  }
1043}
1044```
1045
1046![tabs2](figures/tabs2.gif)
1047
1048### Example 2: Setting the Basic Attributes of the Divider
1049
1050This example uses **divider** to present dividers in different styles.
1051
1052```ts
1053// xxx.ets
1054@Entry
1055@Component
1056struct TabsDivider1 {
1057  private controller1: TabsController = new TabsController()
1058  @State dividerColor: string = 'red'
1059  @State strokeWidth: number = 2
1060  @State startMargin: number = 0
1061  @State endMargin: number = 0
1062  @State nullFlag: boolean = false
1063
1064  build() {
1065    Column() {
1066      Tabs({ controller: this.controller1 }) {
1067        TabContent() {
1068          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1069        }.tabBar('pink')
1070
1071        TabContent() {
1072          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
1073        }.tabBar('yellow')
1074
1075        TabContent() {
1076          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1077        }.tabBar('blue')
1078
1079        TabContent() {
1080          Column().width('100%').height('100%').backgroundColor(Color.Green)
1081        }.tabBar('green')
1082
1083        TabContent() {
1084          Column().width('100%').height('100%').backgroundColor(Color.Red)
1085        }.tabBar('red')
1086      }
1087      .vertical(true)
1088      .scrollable(true)
1089      .barMode(BarMode.Fixed)
1090      .barWidth(70)
1091      .barHeight(200)
1092      .animationDuration(400)
1093      .onChange((index: number) => {
1094        console.info(index.toString())
1095      })
1096      .height('200vp')
1097      .margin({ bottom: '12vp' })
1098      .divider(this.nullFlag ? null : {
1099        strokeWidth: this.strokeWidth,
1100        color: this.dividerColor,
1101        startMargin: this.startMargin,
1102        endMargin: this.endMargin
1103      })
1104
1105      Button('Regular Divider').width('100%').margin({ bottom: '12vp' })
1106        .onClick(() => {
1107          this.nullFlag = false;
1108          this.strokeWidth = 2;
1109          this.dividerColor = 'red';
1110          this.startMargin = 0;
1111          this.endMargin = 0;
1112        })
1113      Button('Empty Divider').width('100%').margin({ bottom: '12vp' })
1114        .onClick(() => {
1115          this.nullFlag = true
1116        })
1117      Button('Change to Blue').width('100%').margin({ bottom: '12vp'})
1118        .onClick(() => {
1119          this.dividerColor = 'blue'
1120        })
1121      Button('Increase Width').width('100%').margin({ bottom: '12vp' })
1122        .onClick(() => {
1123          this.strokeWidth += 2
1124        })
1125      Button('Decrease Width').width('100%').margin({ bottom: '12vp'})
1126        .onClick(() => {
1127          if (this.strokeWidth > 2) {
1128            this.strokeWidth -= 2
1129          }
1130        })
1131      Button('Increase Top Margin').width('100%').margin({ bottom: '12vp' })
1132        .onClick(() => {
1133          this.startMargin += 2
1134        })
1135      Button('Decrease Top Margin').width('100%').margin({ bottom: '12vp' })
1136        .onClick(() => {
1137          if (this.startMargin > 2) {
1138            this.startMargin -= 2
1139          }
1140        })
1141      Button('Increase Bottom Margin').width('100%').margin({ bottom:'12vp'})
1142        .onClick(() => {
1143          this.endMargin += 2
1144        })
1145      Button('Decrease Bottom Margin').width('100%').margin({ bottom:'12vp' })
1146        .onClick(() => {
1147          if (this.endMargin > 2) {
1148            this.endMargin -= 2
1149          }
1150        })
1151    }.padding({ top: '24vp', left: '24vp', right: '24vp' })
1152  }
1153}
1154```
1155
1156![tabs3](figures/tabs3.gif)
1157
1158### Example 3: Setting Tab Bar Fading
1159
1160This example uses **fadingEdge** to specify whether to fade out tabs.
1161
1162```ts
1163// xxx.ets
1164@Entry
1165@Component
1166struct TabsOpaque {
1167  @State message: string = 'Hello World'
1168  private controller: TabsController = new TabsController()
1169  private controller1: TabsController = new TabsController()
1170  @State selfFadingFade: boolean = true;
1171
1172  build() {
1173    Column() {
1174      Button('Set Tab to Fade').width('100%').margin({ bottom: '12vp' })
1175        .onClick((event?: ClickEvent) => {
1176          this.selfFadingFade = true;
1177        })
1178      Button('Set Tab Not to Fade').width('100%').margin({ bottom: '12vp' })
1179        .onClick((event?: ClickEvent) => {
1180          this.selfFadingFade = false;
1181        })
1182      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1183        TabContent() {
1184          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1185        }.tabBar('pink')
1186
1187        TabContent() {
1188          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
1189        }.tabBar('yellow')
1190
1191        TabContent() {
1192          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1193        }.tabBar('blue')
1194
1195        TabContent() {
1196          Column().width('100%').height('100%').backgroundColor(Color.Green)
1197        }.tabBar('green')
1198
1199        TabContent() {
1200          Column().width('100%').height('100%').backgroundColor(Color.Green)
1201        }.tabBar('green')
1202
1203        TabContent() {
1204          Column().width('100%').height('100%').backgroundColor(Color.Green)
1205        }.tabBar('green')
1206
1207        TabContent() {
1208          Column().width('100%').height('100%').backgroundColor(Color.Green)
1209        }.tabBar('green')
1210
1211        TabContent() {
1212          Column().width('100%').height('100%').backgroundColor(Color.Green)
1213        }.tabBar('green')
1214      }
1215      .vertical(false)
1216      .scrollable(true)
1217      .barMode(BarMode.Scrollable)
1218      .barHeight(80)
1219      .animationDuration(400)
1220      .onChange((index: number) => {
1221        console.info(index.toString())
1222      })
1223      .fadingEdge(this.selfFadingFade)
1224      .height('30%')
1225      .width('100%')
1226
1227      Tabs({ barPosition: BarPosition.Start, controller: this.controller1 }) {
1228        TabContent() {
1229          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1230        }.tabBar('pink')
1231
1232        TabContent() {
1233          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
1234        }.tabBar('yellow')
1235
1236        TabContent() {
1237          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1238        }.tabBar('blue')
1239
1240        TabContent() {
1241          Column().width('100%').height('100%').backgroundColor(Color.Green)
1242        }.tabBar('green')
1243
1244        TabContent() {
1245          Column().width('100%').height('100%').backgroundColor(Color.Green)
1246        }.tabBar('green')
1247
1248        TabContent() {
1249          Column().width('100%').height('100%').backgroundColor(Color.Green)
1250        }.tabBar('green')
1251      }
1252      .vertical(true)
1253      .scrollable(true)
1254      .barMode(BarMode.Scrollable)
1255      .barHeight(200)
1256      .barWidth(80)
1257      .animationDuration(400)
1258      .onChange((index: number) => {
1259        console.info(index.toString())
1260      })
1261      .fadingEdge(this.selfFadingFade)
1262      .height('30%')
1263      .width('100%')
1264    }
1265    .padding({ top: '24vp', left: '24vp', right: '24vp' })
1266  }
1267}
1268```
1269
1270![tabs4](figures/tabs4.gif)
1271
1272### Example 4: Setting the Tab Bar to Be Superimposed on the TabContent Component
1273
1274This example uses **barOverlap** to specify whether the tab bar is superimposed on the **TabContent** component after having its background blurred.
1275
1276```ts
1277// xxx.ets
1278@Entry
1279@Component
1280struct barHeightTest {
1281  @State arr: number[] = [0, 1, 2, 3]
1282  @State barOverlap: boolean = true;
1283  build() {
1284    Column() {
1285      Text(`barOverlap ${this.barOverlap}`).fontSize(16)
1286      Button("Change barOverlap").width('100%').margin({ bottom: '12vp' })
1287        .onClick((event?: ClickEvent) => {
1288          if (this.barOverlap) {
1289            this.barOverlap = false;
1290          } else {
1291            this.barOverlap = true;
1292          }
1293        })
1294
1295      Tabs({ barPosition: BarPosition.End }) {
1296        TabContent() {
1297          Column() {
1298            List({ space: 10 }) {
1299              ForEach(this.arr, (item: number) => {
1300                ListItem() {
1301                  Text("item" + item).width('80%').height(200).fontSize(16).textAlign(TextAlign.Center).backgroundColor('#fff8b81e')
1302                }
1303              }, (item: string) => item)
1304            }.width('100%').height('100%')
1305            .lanes(2).alignListItem(ListItemAlign.Center)
1306          }.width('100%').height('100%')
1307          .backgroundColor(Color.Pink)
1308        }
1309        .tabBar(new BottomTabBarStyle($r('sys.media.ohos_icon_mask_svg'), "test 0"))
1310      }
1311      .scrollable(false)
1312      .height('60%')
1313      .barOverlap(this.barOverlap)
1314    }
1315    .height(500)
1316    .padding({ top: '24vp', left: '24vp', right: '24vp' })
1317  }
1318}
1319```
1320
1321![tabs5](figures/tabs5.gif)
1322
1323### Example 5: Setting the Grid-Aligned Visible Area for the TabBar
1324
1325This example uses **barGridAlign** to set the visible area of the tab bar in grid mode.
1326
1327```ts
1328// xxx.ets
1329@Entry
1330@Component
1331struct TabsExample5 {
1332  private controller: TabsController = new TabsController()
1333  @State gridMargin: number = 10
1334  @State gridGutter: number = 10
1335  @State sm: number = -2
1336  @State clickedContent: string = "";
1337
1338  build() {
1339    Column() {
1340      Row() {
1341        Button("gridMargin+10 " + this.gridMargin)
1342          .width('47%')
1343          .height(50)
1344          .margin({ top: 5 })
1345          .onClick((event?: ClickEvent) => {
1346            this.gridMargin += 10
1347          })
1348          .margin({ right: '6%', bottom: '12vp' })
1349        Button("gridMargin-10 " + this.gridMargin)
1350          .width('47%')
1351          .height(50)
1352          .margin({ top: 5 })
1353          .onClick((event?: ClickEvent) => {
1354            this.gridMargin -= 10
1355          })
1356          .margin({ bottom: '12vp' })
1357      }
1358
1359      Row() {
1360        Button("gridGutter+10 " + this.gridGutter)
1361          .width('47%')
1362          .height(50)
1363          .margin({ top: 5 })
1364          .onClick((event?: ClickEvent) => {
1365            this.gridGutter += 10
1366          })
1367          .margin({ right: '6%', bottom: '12vp' })
1368        Button("gridGutter-10 " + this.gridGutter)
1369          .width('47%')
1370          .height(50)
1371          .margin({ top: 5 })
1372          .onClick((event?: ClickEvent) => {
1373            this.gridGutter -= 10
1374          })
1375          .margin({ bottom: '12vp' })
1376      }
1377
1378      Row() {
1379        Button("sm+2 " + this.sm)
1380          .width('47%')
1381          .height(50)
1382          .margin({ top: 5 })
1383          .onClick((event?: ClickEvent) => {
1384            this.sm += 2
1385          })
1386          .margin({ right: '6%' })
1387        Button("sm-2 " + this.sm).width('47%').height(50).margin({ top: 5 })
1388          .onClick((event?: ClickEvent) => {
1389            this.sm -= 2
1390          })
1391      }
1392
1393      Text("Clicked content: " + this.clickedContent).width('100%').height(200).margin({ top: 5 })
1394
1395
1396      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1397        TabContent() {
1398          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1399        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "1"))
1400
1401        TabContent() {
1402          Column().width('100%').height('100%').backgroundColor(Color.Green)
1403        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "2"))
1404
1405        TabContent() {
1406          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1407        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "3"))
1408      }
1409      .width('350vp')
1410      .animationDuration(300)
1411      .height('60%')
1412      .barGridAlign({ sm: this.sm, margin: this.gridMargin, gutter: this.gridGutter })
1413      .backgroundColor(0xf1f3f5)
1414      .onTabBarClick((index: number) => {
1415        this.clickedContent += "index " + index + " was clicked\n";
1416      })
1417    }
1418    .width('100%')
1419    .height(500)
1420    .margin({ top: 5 })
1421    .padding('10vp')
1422  }
1423}
1424```
1425
1426![tabs5](figures/tabs6.gif)
1427
1428### Example 6: Setting the Layout Style for a Scrollable TabBar
1429
1430This example implements the **ScrollableBarModeOptions** parameter of **barMode**. This parameter is effective only in **Scrollable** mode.
1431
1432```ts
1433// xxx.ets
1434@Entry
1435@Component
1436struct TabsExample6 {
1437  private controller: TabsController = new TabsController()
1438  @State scrollMargin: number = 0
1439  @State layoutStyle: LayoutStyle = LayoutStyle.ALWAYS_CENTER
1440  @State text: string = "Text"
1441
1442  build() {
1443    Column() {
1444      Row() {
1445        Button("scrollMargin+10 " + this.scrollMargin)
1446          .width('47%')
1447          .height(50)
1448          .margin({ top: 5 })
1449          .onClick((event?: ClickEvent) => {
1450            this.scrollMargin += 10
1451          })
1452          .margin({ right: '6%', bottom: '12vp' })
1453        Button("scrollMargin-10 " + this.scrollMargin)
1454          .width('47%')
1455          .height(50)
1456          .margin({ top: 5 })
1457          .onClick((event?: ClickEvent) => {
1458            this.scrollMargin -= 10
1459          })
1460          .margin({ bottom: '12vp' })
1461      }
1462
1463      Row() {
1464        Button("Add Text")
1465          .width('47%')
1466          .height(50)
1467          .margin({ top: 5 })
1468          .onClick((event?: ClickEvent) => {
1469            this.text += 'Add Text'
1470          })
1471          .margin({ right: '6%', bottom: '12vp' })
1472        Button("Reset Text")
1473          .width('47%')
1474          .height(50)
1475          .margin({ top: 5 })
1476          .onClick((event?: ClickEvent) => {
1477            this.text = "Text"
1478          })
1479          .margin({ bottom: '12vp' })
1480      }
1481
1482      Row() {
1483        Button("layoutStyle.ALWAYS_CENTER")
1484          .width('100%')
1485          .height(50)
1486          .margin({ top: 5 })
1487          .fontSize(15)
1488          .onClick((event?: ClickEvent) => {
1489            this.layoutStyle = LayoutStyle.ALWAYS_CENTER;
1490          })
1491          .margin({ bottom: '12vp' })
1492      }
1493
1494      Row() {
1495        Button("layoutStyle.ALWAYS_AVERAGE_SPLIT")
1496          .width('100%')
1497          .height(50)
1498          .margin({ top: 5 })
1499          .fontSize(15)
1500          .onClick((event?: ClickEvent) => {
1501            this.layoutStyle = LayoutStyle.ALWAYS_AVERAGE_SPLIT;
1502          })
1503          .margin({ bottom: '12vp' })
1504      }
1505
1506      Row() {
1507        Button("layoutStyle.SPACE_BETWEEN_OR_CENTER")
1508          .width('100%')
1509          .height(50)
1510          .margin({ top: 5 })
1511          .fontSize(15)
1512          .onClick((event?: ClickEvent) => {
1513            this.layoutStyle = LayoutStyle.SPACE_BETWEEN_OR_CENTER;
1514          })
1515          .margin({ bottom: '12vp' })
1516      }
1517
1518      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1519        TabContent() {
1520          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1521        }.tabBar(SubTabBarStyle.of(this.text))
1522
1523        TabContent() {
1524          Column().width('100%').height('100%').backgroundColor(Color.Green)
1525        }.tabBar(SubTabBarStyle.of(this.text))
1526
1527        TabContent() {
1528          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1529        }.tabBar(SubTabBarStyle.of(this.text))
1530      }
1531      .animationDuration(300)
1532      .height('60%')
1533      .backgroundColor(0xf1f3f5)
1534      .barMode(BarMode.Scrollable, { margin: this.scrollMargin, nonScrollableLayoutStyle: this.layoutStyle })
1535    }
1536    .width('100%')
1537    .height(500)
1538    .margin({ top: 5 })
1539    .padding('24vp')
1540  }
1541}
1542```
1543
1544![tabs5](figures/tabs7.gif)
1545
1546### Example 7: Implementing a Custom Tab Switching Animation
1547
1548This example uses **customContentTransition** to implement a custom tab switching animation.
1549
1550```ts
1551// xxx.ets
1552interface itemType {
1553  text: string,
1554  backgroundColor: Color
1555}
1556
1557@Entry
1558@Component
1559struct TabsCustomAnimationExample {
1560  @State data: itemType[] = [
1561    {
1562      text: 'Red',
1563      backgroundColor: Color.Red
1564    },
1565    {
1566      text: 'Yellow',
1567      backgroundColor: Color.Yellow
1568    },
1569    {
1570      text: 'Blue',
1571      backgroundColor: Color.Blue
1572    }]
1573  @State opacityList: number[] = []
1574  @State scaleList: number[] = []
1575
1576  private durationList: number[] = []
1577  private timeoutList: number[] = []
1578  private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => {
1579    let tabContentAnimatedTransition = {
1580      timeout: this.timeoutList[from],
1581      transition: (proxy: TabContentTransitionProxy) => {
1582        this.scaleList[from] = 1.0
1583        this.scaleList[to] = 0.5
1584        this.opacityList[from] = 1.0
1585        this.opacityList[to] = 0.5
1586        animateTo({
1587          duration: this.durationList[from],
1588          onFinish: () => {
1589            proxy.finishTransition()
1590          }
1591        }, () => {
1592          this.scaleList[from] = 0.5
1593          this.scaleList[to] = 1.0
1594          this.opacityList[from] = 0.5
1595          this.opacityList[to] = 1.0
1596        })
1597      }
1598    } as TabContentAnimatedTransition
1599    return tabContentAnimatedTransition
1600  }
1601
1602  aboutToAppear(): void {
1603    let duration = 1000
1604    let timeout = 1000
1605    for (let i = 1; i <= this.data.length; i++) {
1606      this.opacityList.push(1.0)
1607      this.scaleList.push(1.0)
1608      this.durationList.push(duration * i)
1609      this.timeoutList.push(timeout * i)
1610    }
1611  }
1612
1613  build() {
1614    Column() {
1615      Tabs() {
1616        ForEach(this.data, (item: itemType, index: number) => {
1617          TabContent() {}
1618          .tabBar(item.text)
1619          .backgroundColor(item.backgroundColor)
1620          // Customize the opacity and scale animation.
1621          .opacity(this.opacityList[index])
1622          .scale({ x: this.scaleList[index], y: this.scaleList[index] })
1623        })
1624      }
1625      .backgroundColor(0xf1f3f5)
1626      .width('100%')
1627      .height(500)
1628      .customContentTransition(this.customContentTransition)
1629    }
1630  }
1631}
1632```
1633
1634![tabs5](figures/tabs8.gif)
1635
1636### Example 8: Intercepting Page Switching
1637
1638This example uses **onContentWillChange** to intercept and customize the gesture-based swiping actions for page switching.
1639
1640```ts
1641//xxx.ets
1642@Entry
1643@Component
1644struct TabsExample {
1645  @State selectedIndex: number = 2
1646  @State currentIndex: number = 2
1647  private controller: TabsController = new TabsController()
1648  @Builder tabBuilder(title: string,targetIndex: number) {
1649    Column(){
1650      Text(title).fontColor(this.selectedIndex === targetIndex ? '#1698CE' : '#6B6B6B')
1651    }.width('100%')
1652    .height(50)
1653    .justifyContent(FlexAlign.Center)
1654  }
1655  build() {
1656    Column() {
1657      Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) {
1658        TabContent() {
1659          Column(){
1660            Text('Home tab content')
1661          }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
1662        }.tabBar(this.tabBuilder('Home',0))
1663
1664        TabContent() {
1665          Column(){
1666            Text('Discover tab content')
1667          }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center)
1668        }.tabBar(this.tabBuilder('Discover',1))
1669
1670        TabContent() {
1671          Column(){
1672            Text('Recommended tab content')
1673          }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center)
1674        }.tabBar(this.tabBuilder('Recommended',2))
1675
1676        TabContent() {
1677          Column(){
1678            Text('Me tab content')
1679          }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center)
1680        }.tabBar(this.tabBuilder('Me',3))
1681      }
1682      .vertical(false)
1683      .barMode(BarMode.Fixed)
1684      .barWidth(360)
1685      .barHeight(60)
1686      .animationDuration(0)
1687      .onChange((index: number) => {
1688        this.currentIndex = index
1689        this.selectedIndex = index
1690      })
1691      .width(360)
1692      .height(600)
1693      .backgroundColor('#F1F3F5')
1694      .scrollable(true)
1695      .onContentWillChange((currentIndex, comingIndex) => {
1696        if (comingIndex == 2) {
1697          return false
1698        }
1699        return true
1700      })
1701
1702      Button('Change Index').width('50%').margin({ top: 20 })
1703        .onClick(()=>{
1704          this.currentIndex = (this.currentIndex + 1) % 4
1705        })
1706
1707      Button('changeIndex').width('50%').margin({ top: 20 })
1708        .onClick(()=>{
1709          this.currentIndex = (this.currentIndex + 1) % 4
1710          this.controller.changeIndex(this.currentIndex)
1711        })
1712    }.width('100%')
1713  }
1714}
1715```
1716
1717
1718
1719### Example 9: Customizing the Tab Bar Switching Animation
1720
1721This example uses **onChange**, **onAnimationStart**, **onAnimationEnd**, and **onGestureSwipe** APIs to customize the tab bar switching animation.
1722
1723<!--code_no_check-->
1724
1725```ts
1726// EntryAbility.ets
1727import { Configuration, UIAbility } from '@kit.AbilityKit';
1728import { i18n } from '@kit.LocalizationKit';
1729import { CommonUtil } from '../common/CommonUtil';
1730
1731export default class EntryAbility extends UIAbility {
1732  onConfigurationUpdate(newConfig: Configuration): void {
1733    // Listen for system configuration changes.
1734    if (newConfig.language) {
1735      CommonUtil.setIsRTL(i18n.isRTL(newConfig.language))
1736    }
1737  }
1738}
1739```
1740
1741<!--code_no_check-->
1742
1743```ts
1744// CommonUtil.ets
1745import { i18n, intl } from '@kit.LocalizationKit';
1746
1747export class CommonUtil {
1748  private static isRTL: boolean = i18n.isRTL((new intl.Locale()).language)
1749
1750  public static setIsRTL(isRTL: boolean): void {
1751    CommonUtil.isRTL = isRTL
1752  }
1753
1754  public static getIsRTL(): boolean {
1755    return CommonUtil.isRTL
1756  }
1757}
1758```
1759
1760<!--code_no_check-->
1761
1762```ts
1763// xxx.ets
1764import { LengthMetrics } from '@kit.ArkUI';
1765import { CommonUtil } from '../common/CommonUtil';
1766
1767@Entry
1768@Component
1769struct TabsExample {
1770  @State colorArray: [string, string][] =
1771    [['green', '#00CB87'], ['blue', '#007DFF'], ['yellow', '#FFBF00'], ['pink', '#E67C92']]
1772  @State currentIndex: number = 0
1773  @State animationDuration: number = 300
1774  @State indicatorLeftMargin: number = 0
1775  @State indicatorWidth: number = 0
1776  private tabsWidth: number = 0
1777  private textInfos: [number, number][] = []
1778  private isStartAnimateTo: boolean = false
1779
1780  aboutToAppear():void {
1781    for (let i = 0; i < this.colorArray.length; i++) {
1782      this.textInfos.push([0, 0]);
1783    }
1784  }
1785
1786  @Builder
1787  tabBuilder(index: number, name: string) {
1788    Column() {
1789      Text(name)
1790        .fontSize(16)
1791        .fontColor(this.currentIndex === index ? '#007DFF' : '#182431')
1792        .fontWeight(this.currentIndex === index ? 500 : 400)
1793        .id(index.toString())
1794        .onAreaChange((oldValue: Area, newValue: Area) => {
1795          this.textInfos[index] = [newValue.globalPosition.x as number, newValue.width as number]
1796          if (!this.isStartAnimateTo && this.currentIndex === index && this.tabsWidth > 0) {
1797            this.setIndicatorAttr(this.textInfos[this.currentIndex][0], this.textInfos[this.currentIndex][1])
1798          }
1799        })
1800    }.width('100%')
1801  }
1802
1803  build() {
1804    Stack({ alignContent: Alignment.TopStart }) {
1805      Tabs({ barPosition: BarPosition.Start }) {
1806        ForEach(this.colorArray, (item: [string, string], index:number) => {
1807          TabContent() {
1808            Column().width('100%').height('100%').backgroundColor(item[1])
1809          }.tabBar(this.tabBuilder(index, item[0]))
1810        })
1811      }
1812      .onAreaChange((oldValue: Area, newValue: Area)=> {
1813        this.tabsWidth = newValue.width as number
1814        if (!this.isStartAnimateTo) {
1815          this.setIndicatorAttr(this.textInfos[this.currentIndex][0], this.textInfos[this.currentIndex][1])
1816        }
1817      })
1818      .barWidth('100%')
1819      .barHeight(56)
1820      .width('100%')
1821      .height(296)
1822      .backgroundColor('#F1F3F5')
1823      .animationDuration(this.animationDuration)
1824      .onChange((index: number) => {
1825        this.currentIndex = index // Listen for index changes to switch between tab pages.
1826      })
1827      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
1828        // Triggered when the tab switching animation starts. The underline moves with the active tab, along with a width gradient.
1829        this.currentIndex = targetIndex
1830        this.startAnimateTo(this.animationDuration, this.textInfos[targetIndex][0], this.textInfos[targetIndex][1])
1831      })
1832      .onAnimationEnd((index: number, event: TabsAnimationEvent) => {
1833        // Triggered when the tab switching animation ends. The underline animation stops.
1834        let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event)
1835        this.startAnimateTo(0, currentIndicatorInfo.left, currentIndicatorInfo.width)
1836      })
1837      .onGestureSwipe((index: number, event: TabsAnimationEvent) => {
1838        // Triggered on a frame-by-frame basis when the tab is switched by a swipe.
1839        let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event)
1840        this.currentIndex = currentIndicatorInfo.index
1841        this.setIndicatorAttr(currentIndicatorInfo.left, currentIndicatorInfo.width)
1842      })
1843
1844      Column()
1845        .height(2)
1846        .width(this.indicatorWidth)
1847        .margin({ start: LengthMetrics.vp(this.indicatorLeftMargin), top: LengthMetrics.vp(48) })
1848        .backgroundColor('#007DFF')
1849    }.width('100%')
1850  }
1851
1852  private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
1853    let nextIndex = index
1854    if (index > 0 && (CommonUtil.getIsRTL() ? event.currentOffset < 0 : event.currentOffset > 0)) {
1855      nextIndex--
1856    } else if (index < this.textInfos.length - 1 &&
1857        (CommonUtil.getIsRTL() ? event.currentOffset > 0 : event.currentOffset < 0)) {
1858      nextIndex++
1859    }
1860    let indexInfo = this.textInfos[index]
1861    let nextIndexInfo = this.textInfos[nextIndex]
1862    let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth)
1863    let currentIndex = swipeRatio > 0.5 ? nextIndex : index // If the swipe distance exceeds half the page width, the tab bar switches to the next page.
1864    let currentLeft = indexInfo[0] + (nextIndexInfo[0] - indexInfo[0]) * swipeRatio
1865    let currentWidth = indexInfo[1] + (nextIndexInfo[1] - indexInfo[1]) * swipeRatio
1866    return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth }
1867  }
1868
1869  private startAnimateTo(duration: number, leftMargin: number, width: number) {
1870    this.isStartAnimateTo = true
1871    animateTo({
1872      duration: duration, // Animation duration.
1873      curve: Curve.Linear, // Animation curve.
1874      iterations: 1, // Number of playback times.
1875      playMode: PlayMode.Normal, // Animation playback mode.
1876      onFinish: () => {
1877        this.isStartAnimateTo = false
1878        console.info('play end')
1879      }
1880    }, () => {
1881      this.setIndicatorAttr(leftMargin, width)
1882    })
1883  }
1884
1885  private setIndicatorAttr(leftMargin: number, width: number) {
1886    this.indicatorWidth = width
1887    if (CommonUtil.getIsRTL()) {
1888      this.indicatorLeftMargin = this.tabsWidth - leftMargin - width
1889    } else {
1890      this.indicatorLeftMargin = leftMargin
1891    }
1892  }
1893}
1894```
1895
1896![tabs10](figures/tabs10.gif)
1897
1898### Example 10: Preloading Child Nodes
1899
1900In this example, the **preloadItems** API is used to preload specified child nodes.
1901
1902```ts
1903// xxx.ets
1904import { BusinessError } from '@kit.BasicServicesKit';
1905
1906@Entry
1907@Component
1908struct TabsPreloadItems {
1909  @State currentIndex: number = 1
1910  private tabsController: TabsController = new TabsController()
1911
1912  build() {
1913    Column() {
1914      Tabs({ index: this.currentIndex, controller: this.tabsController }) {
1915        TabContent() {
1916          MyComponent({ color: '#00CB87' })
1917        }.tabBar(SubTabBarStyle.of('green'))
1918
1919        TabContent() {
1920          MyComponent({ color: '#007DFF' })
1921        }.tabBar(SubTabBarStyle.of('blue'))
1922
1923        TabContent() {
1924          MyComponent({ color: '#FFBF00' })
1925        }.tabBar(SubTabBarStyle.of('yellow'))
1926
1927        TabContent() {
1928          MyComponent({ color: '#E67C92' })
1929        }.tabBar(SubTabBarStyle.of('pink'))
1930      }
1931      .width(360)
1932      .height(296)
1933      .backgroundColor('#F1F3F5')
1934      .onChange((index: number) => {
1935        this.currentIndex = index
1936      })
1937
1938      Button('preload items: [0, 2, 3]')
1939        .margin(5)
1940        .onClick(() => {
1941          // Preload child nodes 0, 2, and 3 to improve the performance when users swipe or click to switch to these nodes.
1942          this.tabsController.preloadItems([0, 2, 3])
1943            .then(() => {
1944              console.info('preloadItems success.')
1945            })
1946            .catch((error: BusinessError) => {
1947              console.error('preloadItems failed, error code: ' + error.code + ', error message: ' + error.message)
1948            })
1949        })
1950    }
1951  }
1952}
1953
1954@Component
1955struct MyComponent {
1956  private color: string = ""
1957
1958  aboutToAppear(): void {
1959    console.info('aboutToAppear backgroundColor:' + this.color)
1960  }
1961
1962  aboutToDisappear(): void {
1963    console.info('aboutToDisappear backgroundColor:' + this.color)
1964  }
1965
1966  build() {
1967    Column()
1968      .width('100%')
1969      .height('100%')
1970      .backgroundColor(this.color)
1971  }
1972}
1973```
1974
1975### Example 11: Setting Tab Bar Translation and Opacity
1976
1977This example demonstrates how to set the translation distance and opacity of the tab bar using the **setTabBarTranslate** and **setTabBarOpacity** APIs.
1978
1979```ts
1980// xxx.ets
1981@Entry
1982@Component
1983struct TabsExample {
1984  private controller: TabsController = new TabsController()
1985
1986  build() {
1987    Column() {
1988      Button('Set TabBar Translation Distance').margin({ top: 20 })
1989        .onClick(() => {
1990          this.controller.setTabBarTranslate({ x: -20, y: -20 })
1991        })
1992
1993      Button('Set TabBar Opacity').margin({ top: 20 })
1994        .onClick(() => {
1995          this.controller.setTabBarOpacity(0.5)
1996        })
1997
1998      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1999        TabContent() {
2000          Column().width('100%').height('100%').backgroundColor('#00CB87')
2001        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'green'))
2002
2003        TabContent() {
2004          Column().width('100%').height('100%').backgroundColor('#007DFF')
2005        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'blue'))
2006
2007        TabContent() {
2008          Column().width('100%').height('100%').backgroundColor('#FFBF00')
2009        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'yellow'))
2010
2011        TabContent() {
2012          Column().width('100%').height('100%').backgroundColor('#E67C92')
2013        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'pink'))
2014      }
2015      .width(360)
2016      .height(296)
2017      .margin({ top: 20 })
2018      .barBackgroundColor('#F1F3F5')
2019    }
2020    .width('100%')
2021  }
2022}
2023```
2024
2025![tabs11](figures/tabs11.gif)
2026
2027### Example 12: Implementing Lazy Loading and Resource Release of Pages
2028
2029This example demonstrates how to use a custom tab bar with the **Swiper** component and **LazyForEach** to implement lazy loading and resource release of pages.
2030
2031```ts
2032// xxx.ets
2033class MyDataSource implements IDataSource {
2034  private list: number[] = []
2035
2036  constructor(list: number[]) {
2037    this.list = list
2038  }
2039
2040  totalCount(): number {
2041    return this.list.length
2042  }
2043
2044  getData(index: number): number {
2045    return this.list[index]
2046  }
2047
2048  registerDataChangeListener(listener: DataChangeListener): void {
2049  }
2050
2051  unregisterDataChangeListener() {
2052  }
2053}
2054
2055@Entry
2056@Component
2057struct TabsSwiperExample {
2058  @State fontColor: string = '#182431'
2059  @State selectedFontColor: string = '#007DFF'
2060  @State currentIndex: number = 0
2061  private list: number[] = []
2062  private tabsController: TabsController = new TabsController()
2063  private swiperController: SwiperController = new SwiperController()
2064  private swiperData: MyDataSource = new MyDataSource([])
2065
2066  aboutToAppear(): void {
2067    for (let i = 0; i <= 9; i++) {
2068      this.list.push(i);
2069    }
2070    this.swiperData = new MyDataSource(this.list)
2071  }
2072
2073  @Builder tabBuilder(index: number, name: string) {
2074    Column() {
2075      Text(name)
2076        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
2077        .fontSize(16)
2078        .fontWeight(this.currentIndex === index ? 500 : 400)
2079        .lineHeight(22)
2080        .margin({ top: 17, bottom: 7 })
2081      Divider()
2082        .strokeWidth(2)
2083        .color('#007DFF')
2084        .opacity(this.currentIndex === index ? 1 : 0)
2085    }.width('20%')
2086  }
2087
2088  build() {
2089    Column() {
2090      Tabs({ barPosition: BarPosition.Start, controller: this.tabsController }) {
2091        ForEach(this.list, (item: number) => {
2092          TabContent().tabBar(this.tabBuilder(item, 'Tab ' + this.list[item]))
2093        })
2094      }
2095      .onTabBarClick((index: number) => {
2096        this.currentIndex = index
2097        this.swiperController.changeIndex(index, true)
2098      })
2099      .barMode(BarMode.Scrollable)
2100      .backgroundColor('#F1F3F5')
2101      .height(56)
2102      .width('100%')
2103
2104      Swiper(this.swiperController) {
2105        LazyForEach(this.swiperData, (item: string) => {
2106          Text(item.toString())
2107            .onAppear(()=>{
2108              console.info('onAppear ' + item.toString())
2109            })
2110            .onDisAppear(()=>{
2111              console.info('onDisAppear ' + item.toString())
2112            })
2113            .width('100%')
2114            .height('100%')
2115            .backgroundColor(0xAFEEEE)
2116            .textAlign(TextAlign.Center)
2117            .fontSize(30)
2118        }, (item: string) => item)
2119      }
2120      .loop(false)
2121      .onChange((index: number) => {
2122        this.currentIndex = index
2123      })
2124      .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => {
2125        this.currentIndex = targetIndex
2126        this.tabsController.changeIndex(targetIndex)
2127      })
2128    }
2129  }
2130}
2131```
2132
2133![tabs12](figures/tabs12.gif)
2134
2135### Example 13: Setting the Tab Switching Animation
2136
2137This example demonstrates how to implement a tab switching animation by setting **animationMode**.
2138
2139```ts
2140// xxx.ets
2141class TabsMyDataSource implements IDataSource {
2142  private list: number[] = []
2143  constructor(list: number[]) {
2144    this.list = list
2145  }
2146  totalCount(): number {
2147    return this.list.length
2148  }
2149  getData(index: number): number {
2150    return this.list[index]
2151  }
2152  registerDataChangeListener(listener: DataChangeListener): void {
2153  }
2154  unregisterDataChangeListener() {
2155  }
2156}
2157@Entry
2158@Component
2159struct TabsExample {
2160  @State currentIndex: number = 0
2161  @State currentAnimationMode: AnimationMode = AnimationMode.CONTENT_FIRST
2162  private controller: TabsController = new TabsController()
2163  private data: TabsMyDataSource = new TabsMyDataSource([])
2164  private sum : number = 10
2165  aboutToAppear(): void {
2166    let list: number[] = []
2167    for (let i = 0; i < this.sum; i++) {
2168      list.push(i);
2169    }
2170    this.data = new TabsMyDataSource(list)
2171  }
2172  @Builder
2173  tabBuilder(title: string,targetIndex: number) {
2174    Column(){
2175      Text(title).fontColor(this.currentIndex === targetIndex ? '#FF0000' : '#6B6B6B')
2176    }.width('100%')
2177    .height(50)
2178    .justifyContent(FlexAlign.Center)
2179  }
2180  build() {
2181    Column() {
2182      Tabs({ barPosition: BarPosition.End, controller: this.controller, index: this.currentIndex }) {
2183        LazyForEach(this.data, (item: string) => {
2184          TabContent() {
2185            Column(){
2186              Text('' + item)
2187            }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
2188          }.tabBar(this.tabBuilder('P' + item, parseInt(item)))
2189        }, (item: string) => item)
2190      }
2191      .vertical(false)
2192      .barMode(BarMode.Fixed)
2193      .barWidth(360)
2194      .barHeight(60)
2195      .animationMode(this.currentAnimationMode)
2196      .animationDuration(4000)
2197      .onChange((index: number) => {
2198        this.currentIndex = index
2199      })
2200      .width(360)
2201      .height(120)
2202      .backgroundColor('#F1F3F5')
2203      .scrollable(true)
2204      Text('AnimationMode:' + AnimationMode[this.currentAnimationMode])
2205      Button('AnimationMode').width('50%').margin({ top: 1 }).height(25)
2206        .onClick(()=>{
2207          if (this.currentAnimationMode === AnimationMode.CONTENT_FIRST) {
2208            this.currentAnimationMode = AnimationMode.ACTION_FIRST
2209          } else if (this.currentAnimationMode === AnimationMode.ACTION_FIRST) {
2210            this.currentAnimationMode = AnimationMode.NO_ANIMATION
2211          } else if (this.currentAnimationMode === AnimationMode.NO_ANIMATION) {
2212            this.currentAnimationMode = AnimationMode.CONTENT_FIRST_WITH_JUMP
2213          } else if (this.currentAnimationMode === AnimationMode.CONTENT_FIRST_WITH_JUMP) {
2214            this.currentAnimationMode = AnimationMode.ACTION_FIRST_WITH_JUMP
2215          } else if (this.currentAnimationMode === AnimationMode.ACTION_FIRST_WITH_JUMP) {
2216            this.currentAnimationMode = AnimationMode.CONTENT_FIRST
2217          }
2218        })
2219    }.width('100%')
2220  }
2221}
2222```
2223
2224![tabs13](figures/tabs13.gif)
2225
2226### Example 14: Enabling Tabs to Exceed the Tab Bar Area
2227
2228This example shows how to enable tabs to exceed the tab bar area by setting the **clip** property of the **TabBar** using **barModifier**.
2229
2230```ts
2231// xxx.ets
2232import { CommonModifier } from '@kit.ArkUI';
2233
2234@Entry
2235@Component
2236struct TabsBarModifierExample {
2237  @State selectedIndex: number = 2
2238  @State currentIndex: number = 2
2239  @State isClip: boolean = false
2240  @State tabBarModifier: CommonModifier = new CommonModifier()
2241  private controller: TabsController = new TabsController()
2242
2243  aboutToAppear(): void {
2244    this.tabBarModifier.clip(this.isClip)
2245  }
2246
2247  @Builder
2248  tabBuilder(title: string, targetIndex: number) {
2249    Column() {
2250      Image($r("app.media.startIcon")).width(30).height(30)
2251      Text(title).fontColor(this.selectedIndex === targetIndex ? '#1698CE' : '#6B6B6B')
2252    }.width('100%')
2253    .height(50)
2254    .justifyContent(FlexAlign.Center)
2255    .offset({ y: this.selectedIndex === targetIndex ? -15 : 0 })
2256  }
2257
2258  build() {
2259    Column() {
2260      Tabs({
2261        barPosition: BarPosition.End,
2262        index: this.currentIndex,
2263        controller: this.controller,
2264        barModifier: this.tabBarModifier
2265      }) {
2266        TabContent() {
2267          Column() {
2268            Text('Home tab content')
2269          }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
2270        }.tabBar(this.tabBuilder('Home', 0))
2271
2272        TabContent() {
2273          Column() {
2274            Text('Discover tab content')
2275          }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center)
2276        }.tabBar(this.tabBuilder('Discover', 1))
2277
2278        TabContent() {
2279          Column() {
2280            Text('Recommended tab content')
2281          }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center)
2282        }.tabBar(this.tabBuilder('Recommended', 2))
2283
2284        TabContent() {
2285          Column() {
2286            Text('Me tab content')
2287          }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center)
2288        }.tabBar(this.tabBuilder('Me',3))
2289      }
2290      .vertical(false)
2291      .barMode(BarMode.Fixed)
2292      .barWidth(340)
2293      .barHeight(60)
2294      .onChange((index: number) => {
2295        this.currentIndex = index
2296        this.selectedIndex = index
2297      })
2298      .width(340)
2299      .height(400)
2300      .backgroundColor('#F1F3F5')
2301      .scrollable(true)
2302
2303      Button("isClip: " + this.isClip)
2304        .margin({ top: 30 })
2305        .onClick(() => {
2306          this.isClip = !this.isClip
2307          this.tabBarModifier.clip(this.isClip)
2308        })
2309    }.width('100%')
2310  }
2311}
2312```
2313
2314![tabs14](figures/tabs14.gif)
2315
2316### Example 15: Aligning Tabs
2317
2318This example demonstrates how to align tabs by setting the **align** property of the **TabBar** using **barModifier**.
2319
2320```ts
2321// xxx.ets
2322import { CommonModifier } from '@kit.ArkUI';
2323
2324@Entry
2325@Component
2326struct TabsBarModifierExample {
2327  private controller: TabsController = new TabsController()
2328  @State text: string = "Text"
2329  @State isVertical: boolean = false
2330  @State tabBarModifier: CommonModifier = new CommonModifier()
2331
2332  build() {
2333    Column() {
2334      Row() {
2335        Button("Alignment.Start ")
2336          .width('47%')
2337          .height(50)
2338          .margin({ top: 5 })
2339          .onClick((event?: ClickEvent) => {
2340            this.tabBarModifier.align(Alignment.Start)
2341          })
2342          .margin({ right: '6%', bottom: '12vp' })
2343        Button("Alignment.End")
2344          .width('47%')
2345          .height(50)
2346          .margin({ top: 5 })
2347          .onClick((event?: ClickEvent) => {
2348            this.tabBarModifier.align(Alignment.End)
2349          })
2350          .margin({ bottom: '12vp' })
2351      }
2352
2353      Row() {
2354        Button("Alignment.Center")
2355          .width('47%')
2356          .height(50)
2357          .margin({ top: 5 })
2358          .onClick((event?: ClickEvent) => {
2359            this.tabBarModifier.align(Alignment.Center)
2360          })
2361          .margin({ right: '6%', bottom: '12vp' })
2362        Button("isVertical: " + this.isVertical)
2363          .width('47%')
2364          .height(50)
2365          .margin({ top: 5 })
2366          .onClick((event?: ClickEvent) => {
2367            this.isVertical = !this.isVertical
2368          })
2369          .margin({ bottom: '12vp' })
2370      }
2371
2372      Row() {
2373        Button("Alignment.Top")
2374          .width('47%')
2375          .height(50)
2376          .margin({ top: 5 })
2377          .onClick((event?: ClickEvent) => {
2378            this.tabBarModifier.align(Alignment.Top)
2379          })
2380          .margin({ right: '6%', bottom: '12vp' })
2381        Button("Alignment.Bottom")
2382          .width('47%')
2383          .height(50)
2384          .margin({ top: 5 })
2385          .onClick((event?: ClickEvent) => {
2386            this.tabBarModifier.align(Alignment.Bottom)
2387          })
2388          .margin({ bottom: '12vp' })
2389      }
2390
2391      Tabs({ barPosition: BarPosition.End, controller: this.controller, barModifier: this.tabBarModifier }) {
2392        TabContent() {
2393          Column().width('100%').height('100%').backgroundColor(Color.Pink)
2394        }.tabBar(SubTabBarStyle.of(this.text))
2395
2396        TabContent() {
2397          Column().width('100%').height('100%').backgroundColor(Color.Green)
2398        }.tabBar(SubTabBarStyle.of(this.text))
2399
2400        TabContent() {
2401          Column().width('100%').height('100%').backgroundColor(Color.Blue)
2402        }.tabBar(SubTabBarStyle.of(this.text))
2403      }
2404      .vertical(this.isVertical)
2405      .height('60%')
2406      .backgroundColor(0xf1f3f5)
2407      .barMode(BarMode.Scrollable)
2408    }
2409    .width('100%')
2410    .height(500)
2411    .margin({ top: 5 })
2412    .padding('24vp')
2413  }
2414}
2415```
2416
2417![tabs15](figures/tabs15.gif)
2418
2419### Example 16: Implementing Synchronized Switching Between the Tabs and TabBar Components
2420
2421This example shows how to implement synchronized switching between the **Tabs** and **TabBar** components using the **onSelected** callback.
2422
2423```ts
2424@Entry
2425@Component
2426struct TabsExample {
2427  @State fontColor: string = '#182431'
2428  @State selectedFontColor: string = '#007DFF'
2429  @State currentIndex: number = 0
2430  @State selectedIndex: number = 0
2431  private controller: TabsController = new TabsController()
2432
2433  @Builder tabBuilder(index: number, name: string) {
2434    Column() {
2435      Text(name)
2436        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
2437        .fontSize(16)
2438        .fontWeight(this.selectedIndex === index ? 500 : 400)
2439        .lineHeight(22)
2440        .margin({ top: 17, bottom: 7 })
2441      Divider()
2442        .strokeWidth(2)
2443        .color('#007DFF')
2444        .opacity(this.selectedIndex === index ? 1 : 0)
2445    }.width('100%')
2446  }
2447
2448  build() {
2449    Column() {
2450      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
2451        TabContent() {
2452          Column().width('100%').height('100%').backgroundColor('#00CB87')
2453        }.tabBar(this.tabBuilder(0, 'green'))
2454
2455        TabContent() {
2456          Column().width('100%').height('100%').backgroundColor('#007DFF')
2457        }.tabBar(this.tabBuilder(1, 'blue'))
2458
2459        TabContent() {
2460          Column().width('100%').height('100%').backgroundColor('#FFBF00')
2461        }.tabBar(this.tabBuilder(2, 'yellow'))
2462
2463        TabContent() {
2464          Column().width('100%').height('100%').backgroundColor('#E67C92')
2465        }.tabBar(this.tabBuilder(3, 'pink'))
2466      }
2467      .vertical(false)
2468      .barMode(BarMode.Fixed)
2469      .barWidth(360)
2470      .barHeight(56)
2471      .animationDuration(400)
2472      .animationMode(AnimationMode.CONTENT_FIRST)
2473      .onChange((index: number) => {
2474        console.log("onChange index:" + index);
2475        this.currentIndex = index
2476      })
2477      .onSelected((index: number) => {
2478        console.log("onSelected index:" + index);
2479        this.selectedIndex = index
2480      })
2481      .width('100%')
2482      .height('100%')
2483      .backgroundColor('#F1F3F5')
2484    }.width('100%')
2485  }
2486}
2487```
2488![tabs_tarbar](figures/tabs_tarbar.gif)
2489