• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Tabs
2
3通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。
4
5>  **说明:**
6>
7>  该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8>
9>  该组件从API version 11开始默认支持安全区避让特性(默认值为:expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])),开发者可以重写该属性覆盖默认行为,API version 11之前的版本需配合[expandSafeArea](ts-universal-attributes-expand-safe-area.md)属性实现安全区避让。
10
11
12## 子组件
13
14不支持自定义组件作为子组件,仅可包含子组件[TabContent](ts-container-tabcontent.md),以及渲染控制类型[if/else](../../../ui/state-management/arkts-rendering-control-ifelse.md)和[ForEach](../../../ui/state-management/arkts-rendering-control-foreach.md),并且if/else和ForEach下也仅支持TabContent,不支持自定义组件。
15
16>  **说明:**
17>
18>  Tabs子组件的visibility属性设置为None,或者visibility属性设置为Hidden时,对应子组件不显示,但依然会在视窗内占位。
19>
20>  Tabs子组件TabContent显示之后不会销毁,若需要页面懒加载和释放,可以参考[示例13](#示例13页面懒加载和释放)。
21
22
23## 接口
24
25Tabs(options?: TabsOptions)
26
27创建Tabs容器。
28
29**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
30
31**系统能力:** SystemCapability.ArkUI.ArkUI.Full
32
33**参数:**
34
35| 参数名 | 类型         | 必填 | 说明 |
36| -------- | -------- | -------- | -------- |
37| options | [TabsOptions](#tabsoptions15) | 否 | Tabs组件参数。 |
38
39## TabsOptions<sup>15+</sup>
40
41Tabs组件参数,设置Tabs的页签位置,当前显示页签的索引,Tabs控制器和TabBar的[通用属性](ts-component-general-attributes.md)。
42
43**系统能力:** SystemCapability.ArkUI.ArkUI.Full
44
45| 名称         | 类型                              | 必填   | 说明                                     |
46| ----------- | --------------------------------- | ---- | ---------------------------------------- |
47| barPosition<sup>7+</sup> | [BarPosition](#barposition枚举说明)| 否    | 设置Tabs的页签位置。<br/>默认值:BarPosition.Start。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。   |
48| index<sup>7+</sup>       | number                            | 否    | 设置当前显示页签的索引。<br/>默认值:0<br/>**说明:** <br/>设置为小于0的值时按默认值显示。<br/>可选值为[0, TabContent子节点数量-1]。<br/>直接修改index跳页时,切换动效不生效。 使用TabController的changeIndex时,默认生效切换动效,可以设置animationDuration为0关闭动画。<br />从API version 10开始,该参数支持[$$](../../../ui/state-management/arkts-two-way-sync.md)双向绑定变量。<br/>Tabs重建、系统资源切换(如系统字体切换、系统深浅色切换)或者组件属性变化时,会跳转到index对应的页面。若需要在上述情况下不跳转,建议使用双向绑定。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 |
49| controller<sup>7+</sup>  | [TabsController](#tabscontroller) | 否    | 设置Tabs控制器。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。         |
50| barModifier<sup>15+</sup>  | [CommonModifier](#commonmodifier15) | 否    | 设置TabBar的[通用属性](ts-component-general-attributes.md)。<br/>**说明:** <br/>动态置为undefined时会保持当前状态不变,不会重置各通用属性。 <br/>由一个CommonModifier切换为另一个CommonModifier时,重复属性会进行覆盖,非重复属性会同时生效,不会重置前一个CommonModifier的通用属性。<br/>Tabs的[barWidth](#barwidth)、[barHeight](#barheight)、[barBackgroundColor](#barbackgroundcolor10)、[barBackgroundBlurStyle](#barbackgroundblurstyle15)、[barBackgroundEffect](#barbackgroundeffect15)属性会覆盖CommonModifier的[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)、[backgroundEffect](ts-universal-attributes-background.md#backgroundeffect18)属性。<br/>[align](ts-universal-attributes-location.md#align)属性仅在[BarMode.Scrollable](#barmode10-1)模式下生效,且Tabs为横向时还需[nonScrollableLayoutStyle](#scrollablebarmodeoptions10对象说明)未设置或设置为异常值时才能生效。<br/>[TabContent](ts-container-tabcontent.md)组件的[tabBar](ts-container-tabcontent.md#tabbar18)属性为底部页签样式时不支持拖拽功能。<br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。|
51
52## BarPosition枚举说明
53
54Tabs页签位置枚举。
55
56**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
57
58**系统能力:** SystemCapability.ArkUI.ArkUI.Full
59
60| 名称  | 说明                                                         |
61| ----- | ------------------------------------------------------------ |
62| Start | vertical属性方法设置为true时,页签位于容器左侧;vertical属性方法设置为false时,页签位于容器顶部。 |
63| End   | vertical属性方法设置为true时,页签位于容器右侧;vertical属性方法设置为false时,页签位于容器底部。 |
64
65
66## 属性
67
68除支持[通用属性](ts-component-general-attributes.md)外,还支持以下属性:
69
70### vertical
71
72vertical(value: boolean)
73
74设置是否为纵向Tab。
75
76**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
77
78**系统能力:** SystemCapability.ArkUI.ArkUI.Full
79
80**参数:**
81
82| 参数名 | 类型    | 必填 | 说明                                                         |
83| ------ | ------- | ---- | ------------------------------------------------------------ |
84| value  | boolean | 是   | 是否为纵向Tab。<br/>默认值:false,横向Tabs,为true时纵向Tabs。<br/>当横向Tabs设置height为auto时,Tabs组件高度自适应子组件高度,即为tabBar高度+divider线宽+TabContent高度+上下padding值+上下border宽度。<br/>当纵向Tabs设置width为auto时,Tabs组件宽度自适应子组件宽度,即为tabBar宽度+divider线宽+TabContent宽度+左右padding值+左右border宽度。<br/>尽量保持每一个页面中的子组件尺寸大小一致,避免滑动页面时出现页面切换动画跳动现象。 |
85
86### scrollable
87
88scrollable(value: boolean)
89
90设置是否可以通过滑动页面进行页面切换。
91
92**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
93
94**系统能力:** SystemCapability.ArkUI.ArkUI.Full
95
96**参数:**
97
98| 参数名 | 类型    | 必填 | 说明                                                         |
99| ------ | ------- | ---- | ------------------------------------------------------------ |
100| value  | boolean | 是   | 是否可以通过滑动页面进行页面切换。<br/>默认值:true,可以通过滑动页面进行页面切换。为false时不可滑动切换页面。 |
101
102### barMode
103
104barMode(value: BarMode, options?: ScrollableBarModeOptions)
105
106设置TabBar布局模式。
107
108**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
109
110**系统能力:** SystemCapability.ArkUI.ArkUI.Full
111
112**参数:**
113
114| 参数名                | 类型                                                         | 必填 | 说明                                                         |
115| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
116| value                 | [BarMode](#barmode枚举说明)                                  | 是   | 布局模式。<br/>默认值:BarMode.Fixed                                                 |
117| options<sup>10+</sup> | [ScrollableBarModeOptions](#scrollablebarmodeoptions10对象说明) | 否   | Scrollable模式下的TabBar的布局样式。<br/>**说明:** <br/>仅Scrollable且水平模式下有效。 |
118
119### barMode<sup>10+</sup>
120
121barMode(value: BarMode.Fixed)
122
123设置TabBar布局模式为BarMode.Fixed124
125**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
126
127**系统能力:** SystemCapability.ArkUI.ArkUI.Full
128
129**参数:**
130
131| 参数名    | 类型                             | 必填 | 说明                                    |
132| -------- | -------------------------------- | ---- | ------------------------------------ |
133| value    | [BarMode.Fixed](#barmode枚举说明) | 是   | 所有TabBar会平均分配barWidth宽度(纵向时平均分配barHeight高度)。   |
134
135### barMode<sup>10+</sup>
136
137barMode(value: BarMode.Scrollable, options: ScrollableBarModeOptions)
138
139设置TabBar布局模式为BarMode.Scrollable140
141**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
142
143**系统能力:** SystemCapability.ArkUI.ArkUI.Full
144
145**参数:**
146
147| 参数名    | 类型                              | 必填 | 说明                                    |
148| -------- | --------------------------------- | ---- | ------------------------------------- |
149| value    | [BarMode.Scrollable](#barmode枚举说明) | 是   | 所有TabBar都使用实际布局宽度,超过总宽度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。        |
150| options | [ScrollableBarModeOptions](#scrollablebarmodeoptions10对象说明) | 是   | Scrollable模式下的TabBar的布局样式。<br/>**说明:** <br/>仅水平模式下有效。  |
151
152### barWidth
153
154barWidth(value: Length)
155
156设置TabBar的宽度值。设置为小于0或大于Tabs宽度值时,按默认值显示。
157
158**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
159
160**系统能力:** SystemCapability.ArkUI.ArkUI.Full
161
162**参数:**
163
164| 参数名 | 类型                                      | 必填 | 说明                                                         |
165| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
166| value  | [Length](ts-types.md#length)<sup>8+</sup> | 是   | TabBar的宽度值。<br/>默认值:<br/>未设置[SubTabBarStyle](ts-container-tabcontent.md#subtabbarstyle9)和[BottomTabBarStyle](ts-container-tabcontent.md#bottomtabbarstyle9)的TabBar且vertical属性为false时,默认值为Tabs的宽度。<br/>未设置SubTabBarStyle和BottomTabBarStyle的TabBar且vertical属性为true时,默认值为56vp。<br/>设置SubTabBarStyle样式且vertical属性为false时,默认值为Tabs的宽度。<br/>设置SubTabBarStyle样式且vertical属性为true时,默认值为56vp。<br/>设置BottomTabBarStyle样式且vertical属性为true时,默认值为96vp。<br/>设置BottomTabBarStyle样式且vertical属性为false时,默认值为Tabs的宽度。 |
167
168### barHeight
169
170barHeight(value: Length)
171
172设置TabBar的高度值。设置为'auto'时,TabBar自适应子组件高度,仅在水平模式下有效。设置为小于0或大于Tabs高度值时,按默认值显示。
173
174API Version 14之前的版本,若设置barHeight为固定值后,TabBar无法扩展底部安全区。从API Version 14开始支持配合[safeAreaPadding](./ts-universal-attributes-size.md#safeareapadding14)属性,当safeAreaPadding不设置bottom或者bottom设置为0时,可以实现扩展安全区。
175
176**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
177
178**系统能力:** SystemCapability.ArkUI.ArkUI.Full
179
180**参数:**
181
182| 参数名 | 类型                                      | 必填 | 说明                                                         |
183| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
184| value  | [Length](ts-types.md#length)<sup>8+</sup> | 是   | TabBar的高度值。<br/>默认值:<br/>未设置带样式的TabBar且vertical属性为false时,默认值为56vp。<br/>未设置带样式的TabBar且vertical属性为true时,默认值为Tabs的高度。<br/>设置[SubTabBarStyle](ts-container-tabcontent.md#subtabbarstyle9)样式且vertical属性为false时,默认值为56vp。<br/>设置SubTabBarStyle样式且vertical属性为true时,默认值为Tabs的高度。<br/>设置[BottomTabBarStyle](ts-container-tabcontent.md#bottomtabbarstyle9)样式且vertical属性为true时,默认值为Tabs的高度。<br/>设置BottomTabBarStyle样式且vertical属性为false时,默认值为56vp,从API Version 12开始,默认值变更为48vp。 |
185
186### animationDuration
187
188animationDuration(value: number)
189
190设置点击TabBar页签和调用TabsController的changeIndex接口切换TabContent的动画时长。
191
192**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
193
194**系统能力:** SystemCapability.ArkUI.ArkUI.Full
195
196**参数:**
197
198| 参数名 | 类型   | 必填 | 说明                                                         |
199| ------ | ------ | ---- | ------------------------------------------------------------ |
200| value  | number | 是   | 点击TabBar页签和调用TabsController的changeIndex接口切换TabContent的动画时长。<br/>默认值:<br/>API version 10及以前,不设置该属性或设置为null时,默认值为0,即点击TabBar页签和调用TabsController的changeIndex接口切换TabContent无动画。设置为小于0或undefined时,默认值为300。<br/>API version 11及以后,不设置该属性或设置为异常值,且设置TabBar为BottomTabBarStyle样式时,默认值为0。设置TabBar为其他样式时,默认值为300。<br/>单位:ms<br/>取值范围:[0, +∞)。 |
201
202### animationMode<sup>12+</sup>
203
204animationMode(mode: Optional\<AnimationMode\>)
205
206设置点击TabBar页签或调用TabsController的changeIndex接口时切换TabContent的动画形式。
207
208**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
209
210**系统能力:** SystemCapability.ArkUI.ArkUI.Full
211
212**参数:**
213
214| 参数名 | 类型   | 必填 | 说明                                                         |
215| ------ | ------ | ---- | ------------------------------------------------------------ |
216| mode  | Optional\<[AnimationMode](#animationmode12枚举说明)\> | 是   | 点击TabBar页签或调用TabsController的changeIndex接口时切换TabContent的动画形式。<br/>默认值:AnimationMode.CONTENT_FIRST,表示在点击TabBar页签或调用TabsController的changeIndex接口切换TabContent时,先加载目标页内容,再开始切换动画。|
217
218### barPosition<sup>9+</sup>
219
220barPosition(value: BarPosition)
221
222设置Tabs的页签位置。
223
224**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
225
226**系统能力:** SystemCapability.ArkUI.ArkUI.Full
227
228**参数:**
229
230| 参数名 | 类型                               | 必填 | 说明                  |
231| ----- | ---------------------------------- | ---- | -------------------- |
232| value | [BarPosition](#barposition枚举说明)| 是  | 设置Tabs的页签位置。<br/>默认值:BarPosition.Start   |
233
234### divider<sup>10+</sup>
235
236divider(value: DividerStyle | null)
237
238设置区分TabBar和TabContent的分割线样式。
239
240**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
241
242**系统能力:** SystemCapability.ArkUI.ArkUI.Full
243
244**参数:**
245
246| 参数名 | 类型                                                      | 必填 | 说明                                                         |
247| ------ | --------------------------------------------------------- | ---- | ------------------------------------------------------------ |
248| value  | [DividerStyle](#dividerstyle10对象说明)&nbsp;\|&nbsp;null | 是   | 分割线样式,默认不显示分割线。<br/>DividerStyle:分割线的样式;<br/>null:不显示分割线。 |
249
250### fadingEdge<sup>10+</sup>
251
252fadingEdge(value: boolean)
253
254设置页签超过容器宽度时是否渐隐消失。建议配合barBackgroundColor属性一起使用,如果barBackgroundColor属性没有定义,会默认显示页签末端为白色的渐隐效果。
255
256**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
257
258**系统能力:** SystemCapability.ArkUI.ArkUI.Full
259
260**参数:**
261
262| 参数名 | 类型    | 必填 | 说明                                               |
263| ------ | ------- | ---- | -------------------------------------------------- |
264| value  | boolean | 是   | 页签超过容器宽度时是否渐隐消失。<br />默认值:true,页签超过容器宽度时会渐隐消失。设置为false时,页签超过容器宽度直接截断显示,不产生任何渐变效果‌。 |
265
266### barOverlap<sup>10+</sup>
267
268barOverlap(value: boolean)
269
270设置TabBar是否背后变模糊并叠加在TabContent之上。
271
272**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
273
274**系统能力:** SystemCapability.ArkUI.ArkUI.Full
275
276**参数:**
277
278| 参数名 | 类型    | 必填 | 说明                                                         |
279| ------ | ------- | ---- | ------------------------------------------------------------ |
280| value  | boolean | 是   | TabBar是否背后变模糊并叠加在TabContent之上。当barOverlap设置为true时,TabBar背后变模糊并叠加在TabContent之上,并且TabBar默认模糊材质的BlurStyle值修改为'BlurStyle.COMPONENT_THICK'。当barOverlap设置为false时,无模糊和叠加效果。<br />默认值:false |
281
282### barBackgroundColor<sup>10+</sup>
283
284barBackgroundColor(value: ResourceColor)
285
286设置TabBar的背景颜色。
287
288**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
289
290**系统能力:** SystemCapability.ArkUI.ArkUI.Full
291
292**参数:**
293
294| 参数名 | 类型                                       | 必填 | 说明                                 |
295| ------ | ------------------------------------------ | ---- | ------------------------------------ |
296| value  | [ResourceColor](ts-types.md#resourcecolor) | 是   | TabBar的背景颜色。<br />默认值:Color.Transparent,透明 |
297
298### barBackgroundBlurStyle<sup>11+</sup>
299
300barBackgroundBlurStyle(value: BlurStyle)
301
302设置TabBar的背景模糊材质。
303
304**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
305
306**系统能力:** SystemCapability.ArkUI.ArkUI.Full
307
308**参数:**
309
310| 参数名 | 类型                                         | 必填 | 说明                                     |
311| ------ | -------------------------------------------- | ---- | ---------------------------------------- |
312| value  | [BlurStyle](ts-universal-attributes-background.md#blurstyle9) | 是   | TabBar的背景模糊材质。<br />默认值:BlurStyle.NONE |
313
314### barBackgroundBlurStyle<sup>15+</sup>
315
316barBackgroundBlurStyle(style: BlurStyle, options: BackgroundBlurStyleOptions)
317
318为TabBar提供一种在背景和内容之间的模糊能力,通过枚举值的方式封装了不同的模糊半径、蒙版颜色、蒙版透明度、饱和度、亮度。
319
320**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。
321
322**系统能力:** SystemCapability.ArkUI.ArkUI.Full
323
324**参数:**
325
326| 参数名                | 类型                                                         | 必填 | 说明                                                         |
327| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
328| style                 | [BlurStyle](ts-universal-attributes-background.md#blurstyle9)                 | 是   | 背景模糊样式。模糊样式中封装了模糊半径、蒙版颜色、蒙版透明度、饱和度、亮度五个参数。 |
329| options | [BackgroundBlurStyleOptions](ts-universal-attributes-background.md#backgroundblurstyleoptions10对象说明) | 是   | 背景模糊选项。
330
331### barGridAlign<sup>10+</sup>
332
333barGridAlign(value: BarGridColumnOptions)
334
335以栅格化方式设置TabBar的可见区域。具体参见BarGridColumnOptions对象。仅水平模式下有效,[不适用于XS、XL和XXL设备](../../../ui/arkts-layout-development-grid-layout.md#栅格容器断点)。
336
337**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
338
339**系统能力:** SystemCapability.ArkUI.ArkUI.Full
340
341**参数:**
342
343| 参数名 | 类型                                                    | 必填 | 说明                               |
344| ------ | ------------------------------------------------------- | ---- | ---------------------------------- |
345| value  | [BarGridColumnOptions](#bargridcolumnoptions10对象说明) | 是   | 以栅格化方式设置TabBar的可见区域。 |
346
347### edgeEffect<sup>12+</sup>
348
349edgeEffect(edgeEffect: Optional&lt;EdgeEffect&gt;)
350
351设置边缘回弹效果。
352
353**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
354
355**系统能力:** SystemCapability.ArkUI.ArkUI.Full
356
357**参数:**
358
359| 参数名 | 类型                                          | 必填 | 说明                                         |
360| ------ | --------------------------------------------- | ---- | -------------------------------------------- |
361| edgeEffect  | Optional&lt;[EdgeEffect](ts-appendix-enums.md#edgeeffect)&gt; | 是   | 边缘滑动效果。<br/>默认值:EdgeEffect.Spring |
362
363### barBackgroundEffect<sup>15+</sup>
364
365barBackgroundEffect(options: BackgroundEffectOptions)
366
367设置TabBar背景属性,包含背景模糊半径,亮度,饱和度,颜色等参数。
368
369**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。
370
371**系统能力:** SystemCapability.ArkUI.ArkUI.Full
372
373**参数:**
374
375| 参数名  | 类型                                                         | 必填 | 说明                                       |
376| ------- | ------------------------------------------------------------ | ---- | ------------------------------------------ |
377| options | [BackgroundEffectOptions](ts-universal-attributes-background.md#backgroundeffectoptions11) | 是   | 设置TabBar背景属性包括:模糊半径,亮度,饱和度,颜色等。 |
378
379### pageFlipMode<sup>15+</sup>
380
381pageFlipMode(mode: Optional\<PageFlipMode>)
382
383设置鼠标滚轮翻页模式。
384
385**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。
386
387**系统能力:** SystemCapability.ArkUI.ArkUI.Full
388
389**参数:**
390
391| 参数名 | 类型                                                        | 必填 | 说明                                                         |
392| ------ | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ |
393| mode  | Optional\<[PageFlipMode](ts-appendix-enums.md#pageflipmode15)> | 是   | 鼠标滚轮翻页模式。<br/>默认值:PageFlipMode.CONTINUOUS |
394
395## DividerStyle<sup>10+</sup>对象说明
396
397分割线样式对象。
398
399**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
400
401**系统能力:** SystemCapability.ArkUI.ArkUI.Full
402
403| 名称          | 类型                                     | 必填   | 说明                                       |
404| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
405| strokeWidth | [Length](ts-types.md#length)             | 是    | 分割线的线宽(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp<br/>取值范围:[0, +∞)。           |
406| color       | [ResourceColor](ts-types.md#resourcecolor) | 否    | 分割线的颜色。<br/>默认值:#33182431                |
407| startMargin | [Length](ts-types.md#length)             | 否    | 分割线与侧边栏顶端的距离(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp<br/>取值范围:[0, +∞)。 |
408| endMargin   | [Length](ts-types.md#length)             | 否    | 分割线与侧边栏底端的距离(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp<br/>取值范围:[0, +∞)。 |
409
410## BarGridColumnOptions<sup>10+</sup>对象说明
411
412TabBar栅格化方式设置的对象,包括栅格模式下的column边距和间隔,以及小、中、大屏下,页签占用的columns数量。
413
414**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
415
416**系统能力:** SystemCapability.ArkUI.ArkUI.Full
417
418| 名称          | 类型                                     | 必填   | 说明                                       |
419| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
420| margin | [Dimension](ts-types.md#dimension10)             | 否    | 栅格模式下的column边距(不支持百分比设置)。<br/>默认值:24.0<br/>单位:vp                        |
421| gutter      | [Dimension](ts-types.md#dimension10) | 否    | 栅格模式下的column间隔(不支持百分比设置)。<br/>默认值:24.0<br/>单位:vp                     |
422| sm | number            | 否    | 小屏下,页签占用的columns数量,必须是非负偶数。小屏为大于等于320vp但小于600vp。<br/>默认值为-1,代表页签占用TabBar全部宽度。 |
423| md   | number          | 否    | 中屏下,页签占用的columns数量,必须是非负偶数。中屏为大于等于600vp但小于800vp。<br/>默认值为-1,代表页签占用TabBar全部宽度。 |
424| lg   | number           | 否    | 大屏下,页签占用的columns数量,必须是非负偶数。大屏为大于等于840vp但小于1024vp。<br/>默认值为-1,代表页签占用TabBar全部宽度。 |
425
426## ScrollableBarModeOptions<sup>10+</sup>对象说明
427
428Scrollable模式下的TabBar的布局样式对象。
429
430**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
431
432**系统能力:** SystemCapability.ArkUI.ArkUI.Full
433
434| 名称          | 类型                                     | 必填   | 说明                                       |
435| ----------- | ---------------------------------------- | ---- | ---------------------------------------- |
436| margin | [Dimension](ts-types.md#dimension10)          | 否    | Scrollable模式下的TabBar的左右边距(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp<br/>取值范围:[0, +∞)。|
437| nonScrollableLayoutStyle      | [LayoutStyle](#layoutstyle10枚举说明) | 否    | Scrollable模式下不滚动时的页签排布方式。<br/>默认值:LayoutStyle.ALWAYS_CENTER           |
438
439## BarMode枚举说明
440
441TabBar布局模式枚举。
442
443**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
444
445**系统能力:** SystemCapability.ArkUI.ArkUI.Full
446
447| 名称        | 值 | 说明                                     |
448| ---------- | -- | ---------------------------------------- |
449| Scrollable | 0  | 每一个TabBar均使用实际布局宽度,超过总长度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。 |
450| Fixed      | 1  | 所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度)。 |
451
452## AnimationMode<sup>12+</sup>枚举说明
453
454点击TabBar页签时切换TabContent的动画形式枚举。
455
456**系统能力:** SystemCapability.ArkUI.ArkUI.Full
457
458| 名称          | 值   | 说明                                                         |
459| ------------- | ---- | ------------------------------------------------------------ |
460| CONTENT_FIRST | 0    | 先加载目标页内容,再开始切换动画。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。|
461| ACTION_FIRST  | 1    | 先开始切换动画,再加载目标页内容;生效需要同时需要满足:Tabs的height、width没有设置成auto。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 |
462| NO_ANIMATION  | 2    | 关闭默认动画。调用TabsController的changeIndex接口切换TabContent时该枚举值不生效。<br>可以通过设置animationDuration为0实现调用TabsController的changeIndex接口时不带动画。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。|
463| CONTENT_FIRST_WITH_JUMP<sup>15+</sup> | 3    | 先加载目标页内容,再无动画跳转到目标页附近,最后有动画跳转到目标页。<br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。|
464| ACTION_FIRST_WITH_JUMP<sup>15+</sup>  | 4    | 先无动画跳转到目标页附近,再有动画跳转到目标页,最后加载目标页内容。此项生效需要同时需要满足:Tabs的height、width没有设置成auto。<br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 |
465
466## LayoutStyle<sup>10+</sup>枚举说明
467
468Scrollable模式下不滚动时的页签排布方式枚举。
469
470**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
471
472**系统能力:** SystemCapability.ArkUI.ArkUI.Full
473
474| 名称         | 值 | 说明                                     |
475| ---------- | -- | ---------------------------------------- |
476| ALWAYS_CENTER | 0 | 当页签内容超过TabBar宽度时,TabBar可滚动。<br/>当页签内容不超过TabBar宽度时,TabBar不可滚动,页签紧凑居中。|
477| ALWAYS_AVERAGE_SPLIT | 1 | 当页签内容超过TabBar宽度时,TabBar可滚动。<br/>当页签内容不超过TabBar宽度时,TabBar不可滚动,且所有页签平均分配TabBar宽度。|
478| SPACE_BETWEEN_OR_CENTER      | 2 | 当页签内容超过TabBar宽度时,TabBar可滚动。<br/>当页签内容不超过TabBar宽度但超过TabBar宽度一半时,TabBar不可滚动,页签紧凑居中。<br/>当页签内容不超过TabBar宽度一半时,TabBar不可滚动,保证页签居中排列在TabBar宽度一半,且间距相同。|
479
480## CommonModifier<sup>15+</sup>
481
482type CommonModifier = CommonModifier
483
484作为Tabs组件的参数对象。
485
486**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。
487
488**系统能力:** SystemCapability.ArkUI.ArkUI.Full
489
490| 类型         | 说明                                     |
491| ---------- | ---------------------------------------- |
492| [CommonModifier](ts-universal-attributes-attribute-modifier.md#attributemodifier) | 设置TabBar的通用属性。 |
493
494## 事件
495
496除支持[通用事件](ts-component-general-events.md)外,还支持以下事件:
497
498### onChange
499
500onChange(event: Callback\<number>)
501
502Tab页签切换后触发的事件。
503
504满足以下任一条件,即可触发该事件:
505
5061、滑动页面进行页面切换时,组件滑动动画结束后触发。
507
5082、通过[控制器](#tabscontroller)调用[changeIndex](#changeindex)接口,Tab页签切换后触发。
509
5103、动态修改[状态变量](../../../ui/state-management/arkts-state.md)构造的index属性值,Tab页签切换后触发。
511
5124、点击TabBar页签,Tab页签切换后触发。
513
514>  **说明:**
515>
516>  使用自定义页签时,在onChange事件中联动可能会导致滑动页面切换后才执行页签联动,引起自定义页签切换效果延迟。建议在[onAnimationStart](#onanimationstart11)中监听并刷新当前索引,以确保动效能够及时触发。具体实现可参考[示例3](#示例3自定义页签切换联动)。
517
518**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
519
520**系统能力:** SystemCapability.ArkUI.ArkUI.Full
521
522**参数:**
523
524| 参数名 | 类型   | 必填 | 说明                                   |
525| ------ | ------ | ---- | -------------------------------------- |
526| event  | [Callback](./ts-types.md#callback12)\<number> | 是   | 当前显示的index索引,索引从0开始计算。 |
527
528### onTabBarClick<sup>10+</sup>
529
530onTabBarClick(event: Callback\<number>)
531
532Tab页签点击后触发的事件。
533
534**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
535
536**系统能力:** SystemCapability.ArkUI.ArkUI.Full
537
538**参数:**
539
540| 参数名 | 类型   | 必填 | 说明                                 |
541| ------ | ------ | ---- | ------------------------------------ |
542| event  | [Callback](./ts-types.md#callback12)\<number> | 是   | 被点击的index索引,索引从0开始计算。 |
543
544### onAnimationStart<sup>11+</sup>
545
546onAnimationStart(handler: OnTabsAnimationStartCallback)
547
548切换动画开始时触发该回调。当[animationDuration](#animationduration)为0时动画关闭,不触发该回调。
549
550**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
551
552**系统能力:** SystemCapability.ArkUI.ArkUI.Full
553
554**参数:**
555
556| 参数名 | 类型   | 必填 | 说明                 |
557| ------ | ------ | ---- | -------------------- |
558| handler  | [OnTabsAnimationStartCallback](#ontabsanimationstartcallback18) | 是   | 切换动画开始时触发的回调。 |
559
560### onAnimationEnd<sup>11+</sup>
561
562onAnimationEnd(handler: OnTabsAnimationEndCallback)
563
564切换动画结束时触发该回调,包括动画过程中手势中断。当animationDuration为0时动画关闭,不触发该回调。
565
566**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
567
568**系统能力:** SystemCapability.ArkUI.ArkUI.Full
569
570**参数:**
571
572| 参数名 | 类型   | 必填 | 说明                 |
573| ------ | ------ | ---- | -------------------- |
574| handler  | [OnTabsAnimationEndCallback](#ontabsanimationendcallback18) | 是   | 切换动画结束时触发的回调。 |
575
576### onGestureSwipe<sup>11+</sup>
577
578onGestureSwipe(handler: OnTabsGestureSwipeCallback)
579
580在页面跟手滑动过程中,逐帧触发该回调。
581
582**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
583
584**系统能力:** SystemCapability.ArkUI.ArkUI.Full
585
586**参数:**
587
588| 参数名 | 类型   | 必填 | 说明                 |
589| ------ | ------ | ---- | -------------------- |
590| handler  | [OnTabsGestureSwipeCallback](#ontabsgestureswipecallback18) | 是   | 在页面跟手滑动过程中,逐帧触发的回调。 |
591
592### customContentTransition<sup>11+</sup>
593
594customContentTransition(delegate: TabsCustomContentTransitionCallback)
595
596自定义Tabs页面切换动画。
597
598使用说明:
599
6001、当使用自定义切换动画时,Tabs组件自带的默认切换动画会被禁用,同时,页面也无法跟手滑动。<br>2、当设置为undefined时,表示不使用自定义切换动画,仍然使用组件自带的默认切换动画。<br>3、当前自定义切换动画不支持打断。<br>4、目前自定义切换动画只支持两种场景触发:点击页签和调用TabsController.changeIndex()接口。<br>5、当使用自定义切换动画时,Tabs组件支持的事件中,除了onGestureSwipe,其他事件均支持。<br>6、onChange和onAnimationEnd事件的触发时机需要特殊说明:如果在第一次自定义动画执行过程中,触发了第二次自定义动画,那么在开始第二次自定义动画时,就会触发第一次自定义动画的onChange和onAnimationEnd事件。<br>7、当使用自定义动画时,参与动画的页面布局方式会改为Stack布局。如果开发者未主动设置相关页面的zIndex属性,那么所有页面的zIndex值是一样的,页面的渲染层级会按照在组件树上的顺序(即页面的index值顺序)确定。因此,开发者需要主动修改页面的zIndex属性,来控制页面的渲染层级。
601
602**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
603
604**系统能力:** SystemCapability.ArkUI.ArkUI.Full
605
606**参数:**
607
608| 参数名 | 类型   | 必填 | 说明                 |
609| ------ | ------ | ---- | -------------------- |
610| delegate  | [TabsCustomContentTransitionCallback](#tabscustomcontenttransitioncallback18) | 是   | 自定义Tabs页面切换动画开始时触发的回调。 |
611
612
613### onContentWillChange<sup>12+</sup>
614
615onContentWillChange(handler: OnTabsContentWillChangeCallback)
616
617自定义Tabs页面切换拦截事件能力,新页面即将显示时触发该回调。
618
619满足以下任一条件,即可触发该事件:
620
6211、滑动TabContent切换新页面时触发。
622
6232、通过TabsController.changeIndex接口切换新页面时触发。
624
6253、通过动态修改index属性值切换新页面时触发。
626
6274、通过点击TabBar页签切换新页面时触发。
628
6295、TabBar页签获焦后,通过键盘左右方向键等切换新页面时触发。
630
631**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
632
633**系统能力:** SystemCapability.ArkUI.ArkUI.Full
634
635**参数:**
636
637| 参数名 | 类型   | 必填 | 说明                 |
638| ------ | ------ | ---- | -------------------- |
639| handler  | [OnTabsContentWillChangeCallback](#ontabscontentwillchangecallback18) | 是   | 自定义Tabs页面切换拦截事件能力,新页面即将显示时触发的回调。 |
640
641### onSelected<sup>18+</sup>
642
643onSelected(event: Callback\<number>)
644
645当选中元素改变时触发该回调,返回值为当前选中的元素的索引值。
646
647满足以下任一条件,即可触发该事件:
648
6491. 滑动离手时满足翻页阈值,开始切换动画时触发。
650
6512. 通过[TabsController控制器](#tabscontroller)调用[changeIndex](#changeindex)接口,开始切换动画时触发。
652
6533. 动态修改[状态变量](../../../ui/state-management/arkts-state.md)构造的index属性值后触发。
654
6554. 通过页签处点击触发。
656
657**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
658
659**系统能力:** SystemCapability.ArkUI.ArkUI.Full
660
661**参数:**
662
663| 参数名 | 类型   | 必填 | 说明                                   |
664| ------ | ------ | ---- | -------------------------------------- |
665| event  | [Callback](./ts-types.md#callback12)\<number> | 是   | 当前选中元素的索引。 |
666
667> **说明:**
668>
669> onSelected回调中不可通过TabsOptions的index设置当前显示页的索引,不可调用TabsController.changeIndex()方法。
670
671### onUnselected<sup>18+</sup>
672
673onUnselected(event: Callback\<number>)
674
675当选中元素改变时触发该回调,返回值为将要隐藏的元素的索引值。
676
677满足以下任一条件,即可触发该事件:
678
6791. 滑动离手时满足翻页阈值,开始切换动画时触发。
680
6812. 通过[TabsController控制器](#tabscontroller)调用[changeIndex](#changeindex)接口,开始切换动画时触发。
682
6833. 动态修改[状态变量](../../../ui/state-management/arkts-state.md)构造的index属性值后触发。
684
6854. 通过页签处点击触发。
686
687**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
688
689**系统能力:** SystemCapability.ArkUI.ArkUI.Full
690
691**参数:**
692
693| 参数名 | 类型   | 必填 | 说明                                   |
694| ------ | ------ | ---- | -------------------------------------- |
695| event  | [Callback](./ts-types.md#callback12)\<number> | 是   | 将要隐藏元素的索引。 |
696
697> **说明:**
698>
699> onUnselected回调中不可通过TabsOptions的index设置当前显示页的索引,不可调用TabsController.changeIndex()方法。
700
701## OnTabsAnimationStartCallback<sup>18+</sup>
702
703type OnTabsAnimationStartCallback = (index: number, targetIndex: number, extraInfo: TabsAnimationEvent) => void
704
705切换动画开始时触发的回调。
706
707**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
708
709**系统能力:** SystemCapability.ArkUI.ArkUI.Full
710
711**参数:**
712
713| 参数名      | 类型                                                   | 必填 | 说明                                                         |
714| ----------- | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
715| index       | number                                                 | 是   | 当前显示元素的索引,索引从0开始。                             |
716| targetIndex | number                                                 | 是   | 切换动画目标元素的索引,索引从0开始。                         |
717| extraInfo       | [TabsAnimationEvent](#tabsanimationevent11对象说明) | 是   | 动画相关信息,包括主轴方向上当前显示元素和目标元素相对Tabs起始位置的位移,以及离手速度。 |
718
719## OnTabsAnimationEndCallback<sup>18+</sup>
720
721type OnTabsAnimationEndCallback = (index: number, extraInfo: TabsAnimationEvent) => void
722
723切换动画结束时触发的回调。
724
725**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
726
727**系统能力:** SystemCapability.ArkUI.ArkUI.Full
728
729**参数:**
730
731| 参数名 | 类型                                                   | 必填 | 说明                                                         |
732| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
733| index  | number                                                 | 是   | 当前显示元素的索引,索引从0开始。                                    |
734| extraInfo  | [TabsAnimationEvent](#tabsanimationevent11对象说明) | 是   | 动画相关信息,只返回主轴方向上当前显示元素相对于Tabs起始位置的位移。 |
735
736## OnTabsGestureSwipeCallback<sup>18+</sup>
737
738type OnTabsGestureSwipeCallback = (index: number, extraInfo: TabsAnimationEvent) => void
739
740在页面跟手滑动过程中,逐帧触发的回调。
741
742**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
743
744**系统能力:** SystemCapability.ArkUI.ArkUI.Full
745
746**参数:**
747
748| 参数名 | 类型                                                   | 必填 | 说明                                                         |
749| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ |
750| index  | number                                                 | 是   | 当前显示元素的索引,索引从0开始。                                    |
751| extraInfo  | [TabsAnimationEvent](#tabsanimationevent11对象说明) | 是   | 动画相关信息,只返回主轴方向上当前显示元素相对于Tabs起始位置的位移。 |
752
753## TabsCustomContentTransitionCallback<sup>18+</sup>
754
755type TabsCustomContentTransitionCallback = (from: number, to: number) => TabContentAnimatedTransition | undefined
756
757自定义Tabs页面切换动画开始时触发的回调。
758
759**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
760
761**系统能力:** SystemCapability.ArkUI.ArkUI.Full
762
763**参数:**
764
765| 参数名 | 类型   | 必填 | 说明                            |
766| ------ | ------ | ---- | ------------------------------- |
767| from   | number | 是   | 动画开始时,当前页面的index值,索引从0开始。 |
768| to     | number | 是   | 动画开始时,目标页面的index值,索引从0开始。 |
769
770**返回值:**
771
772| 类型                                                         | 说明                     |
773| ------------------------------------------------------------ | ------------------------ |
774| [TabContentAnimatedTransition](#tabcontentanimatedtransition11)&nbsp;\|&nbsp;undefined | 自定义切换动画相关信息。 |
775
776## OnTabsContentWillChangeCallback<sup>18+</sup>
777
778type OnTabsContentWillChangeCallback = (currentIndex: number, comingIndex: number) => boolean
779
780自定义Tabs页面切换拦截事件能力,新页面即将显示时触发的回调。
781
782**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。
783
784**系统能力:** SystemCapability.ArkUI.ArkUI.Full
785
786**参数:**
787
788| 参数名       | 类型   | 必填 | 说明                                       |
789| ------------ | ------ | ---- | ------------------------------------------ |
790| currentIndex | number | 是   | 当前显示页面的index索引,索引从0开始计算。 |
791| comingIndex  | number | 是   | 将要显示的新页面的index索引。              |
792
793**返回值:**
794
795| 类型    | 说明                                                         |
796| ------- | ------------------------------------------------------------ |
797| boolean | 当回调函数handler的返回值为true时,Tabs可以切换到新页面。<br/>当回调函数handler的返回值为false时,Tabs无法切换到新页面,仍然显示原来页面内容。 |
798
799## TabsAnimationEvent<sup>11+</sup>对象说明
800
801Tabs组件动画相关信息集合。
802
803**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
804
805**系统能力:** SystemCapability.ArkUI.ArkUI.Full
806
807| 名称            | 类型      | 只读 | 可选 | 说明                                       |
808| ------------- | ---------- | ---- | ---- | ------------------------ |
809| currentOffset | number | 否 | 否 | Tabs当前显示元素在主轴方向上,相对于Tabs起始位置的位移。单位VP,默认值为0。|
810| targetOffset | number | 否 | 否 | Tabs动画目标元素在主轴方向上,相对于Tabs起始位置的位移。单位VP,默认值为0。|
811| velocity | number | 否 | 否 | Tabs离手动画开始时的离手速度。单位VP/S,默认值为0。|
812
813## TabContentAnimatedTransition<sup>11+</sup>
814
815Tabs自定义切换动画相关信息。
816
817**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。
818
819**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
820
821**系统能力:** SystemCapability.ArkUI.ArkUI.Full
822
823| 名称            | 类型         | 必填   | 说明                                       |
824| ------------- | ---------------------- | ---- |---------------------- |
825| timeout | number | 否 | Tabs自定义切换动画超时时间。从自定义动画开始切换计时,如果到达该时间后,开发者仍未调用[TabContentTransitionProxy](#tabcontenttransitionproxy11)的finishTransition接口通知Tabs组件自定义动画结束,那么组件就会认为此次自定义动画已结束,直接执行后续操作。<br/>默认值:1000<br/>单位:ms<br/>取值范围:[0, +∞)。|
826| transition | [Callback](./ts-types.md#callback12)\<[TabContentTransitionProxy](#tabcontenttransitionproxy11)> | 是 | 自定义切换动画具体内容。|
827
828## TabContentTransitionProxy<sup>11+</sup>
829
830Tabs自定义切换动画执行过程中,返回给开发者的proxy对象。开发者可通过该对象获取自定义动画的起始和目标页面信息,同时,也可以通过调用该对象的finishTransition接口通知Tabs组件自定义动画已结束。
831
832**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。
833
834**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
835
836**系统能力:** SystemCapability.ArkUI.ArkUI.Full
837
838### 属性
839
840| 名称  | 类型     | 只读 | 可选 | 说明                         |
841| ----- | ------- | ---- | ---- | --------------------------- |
842| from | number | 否 | 否 | 自定义动画起始页面对应的index值,索引从0开始。|
843| to | number | 否 | 否 | 自定义动画目标页面对应的index值,索引从0开始。|
844
845### finishTransition
846
847finishTransition(): void
848
849通知Tabs组件,此页面的自定义动画已结束。
850
851**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。
852
853**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
854
855**系统能力:** SystemCapability.ArkUI.ArkUI.Full
856
857## TabsController
858
859Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。
860
861**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
862
863**系统能力:** SystemCapability.ArkUI.ArkUI.Full
864
865### constructor
866
867constructor()
868
869TabsController的构造函数。
870
871**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
872
873**系统能力:** SystemCapability.ArkUI.ArkUI.Full
874
875### changeIndex
876
877changeIndex(value: number): void
878
879控制Tabs切换到指定页签。
880
881**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
882
883**系统能力:** SystemCapability.ArkUI.ArkUI.Full
884
885**参数:**
886
887| 参数名   | 类型   | 必填   | 说明                                     |
888| ----- | ------ | ---- | ---------------------------------------- |
889| value | number | 是    | 页签在Tabs里的索引值,索引值从0开始。<br/>**说明:** <br/>设置小于0或大于最大数量的值时,取默认值0。 |
890
891### preloadItems<sup>12+</sup>
892
893preloadItems(indices: Optional\<Array\<number>>): Promise\<void>
894
895控制Tabs预加载指定子节点。调用该接口后会一次性加载所有指定的子节点,因此为了性能考虑,建议分批加载子节点。
896
897**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
898
899**系统能力:** SystemCapability.ArkUI.ArkUI.Full
900
901**参数:**
902
903| 参数名   | 类型   | 必填   | 说明                                     |
904| ----- | ------ | ---- | ---------------------------------------- |
905| indices | Optional\<Array\<number>> | 是 | 需预加载的子节点的下标数组。<br/>默认值:空数组。 |
906
907**返回值:**
908
909| 类型                                                         | 说明                     |
910| ------------------------------------------------------------ | ------------------------ |
911| Promise\<void> | 预加载完成后触发的回调。 |
912
913**错误码:**
914
915以下错误码的详细介绍请参见[通用错误码](../../errorcode-universal.md)。
916
917| 错误码ID   | 错误信息                                      |
918| --------   | -------------------------------------------- |
919| 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. |
920
921### setTabBarTranslate<sup>13+</sup>
922
923setTabBarTranslate(translate: TranslateOptions): void
924
925设置TabBar的平移距离。
926
927> **说明:**
928>
929> 当使用[bindTabsToScrollable](../js-apis-arkui-UIContext.md#bindtabstoscrollable13)或[bindTabsToNestedScrollable](../js-apis-arkui-UIContext.md#bindtabstonestedscrollable13)等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效,调用setTabBarTranslate接口设置的TabBar平移距离会失效。因此不建议同时使用bindTabsToScrollable、bindTabsToNestedScrollable和setTabBarTranslate接口。
930>
931
932**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。
933
934**系统能力:** SystemCapability.ArkUI.ArkUI.Full
935
936**参数:**
937
938| 参数名   | 类型   | 必填   | 说明                                     |
939| ----- | ------ | ---- | ---------------------------------------- |
940| translate | [TranslateOptions](ts-universal-attributes-transformation.md#translateoptions对象说明) | 是 | 设置TabBar的平移距离。 |
941
942### setTabBarOpacity<sup>13+</sup>
943
944setTabBarOpacity(opacity: number): void
945
946设置TabBar的不透明度。
947
948> **说明:**
949>
950> 当使用[bindTabsToScrollable](../js-apis-arkui-UIContext.md#bindtabstoscrollable13)或[bindTabsToNestedScrollable](../js-apis-arkui-UIContext.md#bindtabstonestedscrollable13)等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效,调用setTabBarOpacity接口设置的TabBar不透明度会失效。因此不建议同时使用bindTabsToScrollable、bindTabsToNestedScrollable和setTabBarOpacity接口。
951>
952
953**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。
954
955**系统能力:** SystemCapability.ArkUI.ArkUI.Full
956
957**参数:**
958
959| 参数名   | 类型   | 必填   | 说明                                     |
960| ----- | ------ | ---- | ---------------------------------------- |
961| opacity | number | 是 | 设置TabBar的不透明度,取值范围为[0.0, 1.0]。 |
962
963## 示例
964
965### 示例1(设置TabBar的布局模式)
966
967本示例通过barMode分别实现了页签均分布局和以实际长度布局,且展示了当页签布局长度之和超过了TabBar总长度后可滑动的效果。
968
969```ts
970// xxx.ets
971@Entry
972@Component
973struct TabsExample {
974  @State text: string = "文本";
975  @State barMode: BarMode = BarMode.Fixed;
976
977  build() {
978    Column() {
979      Row() {
980        Button("文本增加 ")
981          .width('47%')
982          .height(50)
983          .onClick((event?: ClickEvent) => {
984            this.text += '文本增加';
985          })
986          .margin({ right: '6%', bottom: '12vp' })
987
988        Button("文本重置")
989          .width('47%')
990          .height(50)
991          .onClick((event?: ClickEvent) => {
992            this.text = "文本";
993          })
994          .margin({ bottom: '12vp' })
995      }
996
997      Row() {
998        Button("BarMode.Fixed")
999          .width('47%')
1000          .height(50)
1001          .onClick((event?: ClickEvent) => {
1002            this.barMode = BarMode.Fixed;
1003          })
1004          .margin({ right: '6%', bottom: '12vp' })
1005
1006        Button("BarMode.Scrollable")
1007          .width('47%')
1008          .height(50)
1009          .onClick((event?: ClickEvent) => {
1010            this.barMode = BarMode.Scrollable;
1011          })
1012          .margin({ bottom: '12vp' })
1013      }
1014
1015      Tabs() {
1016        TabContent() {
1017          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1018        }.tabBar(SubTabBarStyle.of(this.text))
1019
1020        TabContent() {
1021          Column().width('100%').height('100%').backgroundColor(Color.Green)
1022        }.tabBar(SubTabBarStyle.of(this.text))
1023
1024        TabContent() {
1025          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1026        }.tabBar(SubTabBarStyle.of(this.text))
1027      }
1028      .height('60%')
1029      .backgroundColor(0xf1f3f5)
1030      .barMode(this.barMode)
1031    }
1032    .width('100%')
1033    .height(500)
1034    .padding('24vp')
1035  }
1036}
1037```
1038![tabs1](figures/tabs_barMode.gif)
1039
1040### 示例2(设置Scrollable模式下的TabBar的布局样式)
1041
1042本示例实现了barMode的ScrollableBarModeOptions参数,该参数仅在Scrollable模式下有效。
1043
1044```ts
1045// xxx.ets
1046@Entry
1047@Component
1048struct TabsExample6 {
1049  private controller: TabsController = new TabsController();
1050  @State scrollMargin: number = 0;
1051  @State layoutStyle: LayoutStyle = LayoutStyle.ALWAYS_CENTER;
1052  @State text: string = "文本";
1053
1054  build() {
1055    Column() {
1056      Row() {
1057        Button("scrollMargin+10 " + this.scrollMargin)
1058          .width('47%')
1059          .height(50)
1060          .margin({ top: 5 })
1061          .onClick((event?: ClickEvent) => {
1062            this.scrollMargin += 10;
1063          })
1064          .margin({ right: '6%', bottom: '12vp' })
1065        Button("scrollMargin-10 " + this.scrollMargin)
1066          .width('47%')
1067          .height(50)
1068          .margin({ top: 5 })
1069          .onClick((event?: ClickEvent) => {
1070            this.scrollMargin -= 10;
1071          })
1072          .margin({ bottom: '12vp' })
1073      }
1074
1075      Row() {
1076        Button("文本增加 ")
1077          .width('47%')
1078          .height(50)
1079          .margin({ top: 5 })
1080          .onClick((event?: ClickEvent) => {
1081            this.text += '文本增加';
1082          })
1083          .margin({ right: '6%', bottom: '12vp' })
1084        Button("文本重置")
1085          .width('47%')
1086          .height(50)
1087          .margin({ top: 5 })
1088          .onClick((event?: ClickEvent) => {
1089            this.text = "文本";
1090          })
1091          .margin({ bottom: '12vp' })
1092      }
1093
1094      Row() {
1095        Button("layoutStyle.ALWAYS_CENTER")
1096          .width('100%')
1097          .height(50)
1098          .margin({ top: 5 })
1099          .fontSize(15)
1100          .onClick((event?: ClickEvent) => {
1101            this.layoutStyle = LayoutStyle.ALWAYS_CENTER;
1102          })
1103          .margin({ bottom: '12vp' })
1104      }
1105
1106      Row() {
1107        Button("layoutStyle.ALWAYS_AVERAGE_SPLIT")
1108          .width('100%')
1109          .height(50)
1110          .margin({ top: 5 })
1111          .fontSize(15)
1112          .onClick((event?: ClickEvent) => {
1113            this.layoutStyle = LayoutStyle.ALWAYS_AVERAGE_SPLIT;
1114          })
1115          .margin({ bottom: '12vp' })
1116      }
1117
1118      Row() {
1119        Button("layoutStyle.SPACE_BETWEEN_OR_CENTER")
1120          .width('100%')
1121          .height(50)
1122          .margin({ top: 5 })
1123          .fontSize(15)
1124          .onClick((event?: ClickEvent) => {
1125            this.layoutStyle = LayoutStyle.SPACE_BETWEEN_OR_CENTER;
1126          })
1127          .margin({ bottom: '12vp' })
1128      }
1129
1130      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1131        TabContent() {
1132          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1133        }.tabBar(SubTabBarStyle.of(this.text))
1134
1135        TabContent() {
1136          Column().width('100%').height('100%').backgroundColor(Color.Green)
1137        }.tabBar(SubTabBarStyle.of(this.text))
1138
1139        TabContent() {
1140          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1141        }.tabBar(SubTabBarStyle.of(this.text))
1142      }
1143      .animationDuration(300)
1144      .height('60%')
1145      .backgroundColor(0xf1f3f5)
1146      .barMode(BarMode.Scrollable, { margin: this.scrollMargin, nonScrollableLayoutStyle: this.layoutStyle })
1147    }
1148    .width('100%')
1149    .height(500)
1150    .margin({ top: 5 })
1151    .padding('24vp')
1152  }
1153}
1154```
1155
1156![tabs2](figures/tabs_scrollable.gif)
1157
1158### 示例3(自定义页签切换联动)
1159
1160本示例通过onAnimationStart、onChange实现切换时自定义tabBar和TabContent的联动。
1161
1162```ts
1163// xxx.ets
1164@Entry
1165@Component
1166struct TabsExample {
1167  @State fontColor: string = '#182431';
1168  @State selectedFontColor: string = '#007DFF';
1169  @State currentIndex: number = 0;
1170  @State selectedIndex: number = 0;
1171  private controller: TabsController = new TabsController();
1172
1173  @Builder tabBuilder(index: number, name: string) {
1174    Column() {
1175      Text(name)
1176        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
1177        .fontSize(16)
1178        .fontWeight(this.selectedIndex === index ? 500 : 400)
1179        .lineHeight(22)
1180        .margin({ top: 17, bottom: 7 })
1181      Divider()
1182        .strokeWidth(2)
1183        .color('#007DFF')
1184        .opacity(this.selectedIndex === index ? 1 : 0)
1185    }.width('100%')
1186  }
1187
1188  build() {
1189    Column() {
1190      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
1191        TabContent() {
1192          Column().width('100%').height('100%').backgroundColor('#00CB87')
1193        }.tabBar(this.tabBuilder(0, 'green'))
1194
1195        TabContent() {
1196          Column().width('100%').height('100%').backgroundColor('#007DFF')
1197        }.tabBar(this.tabBuilder(1, 'blue'))
1198
1199        TabContent() {
1200          Column().width('100%').height('100%').backgroundColor('#FFBF00')
1201        }.tabBar(this.tabBuilder(2, 'yellow'))
1202
1203        TabContent() {
1204          Column().width('100%').height('100%').backgroundColor('#E67C92')
1205        }.tabBar(this.tabBuilder(3, 'pink'))
1206      }
1207      .vertical(false)
1208      .barMode(BarMode.Fixed)
1209      .barWidth(360)
1210      .barHeight(56)
1211      .animationDuration(400)
1212      .onChange((index: number) => {
1213        // currentIndex控制TabContent显示页签
1214        this.currentIndex = index;
1215        this.selectedIndex = index;
1216      })
1217      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
1218        if (index === targetIndex) {
1219          return;
1220        }
1221        // selectedIndex控制自定义TabBar内Image和Text颜色切换
1222        this.selectedIndex = targetIndex;
1223      })
1224      .width(360)
1225      .height(296)
1226      .margin({ top: 52 })
1227      .backgroundColor('#F1F3F5')
1228    }.width('100%')
1229  }
1230}
1231```
1232
1233![tabs3](figures/tabs_onAnimationStart.gif)
1234
1235### 示例4(分割线基本属性)
1236
1237本示例通过divider实现了分割线各种属性的展示。
1238
1239```ts
1240// xxx.ets
1241@Entry
1242@Component
1243struct TabsDivider1 {
1244  private controller1: TabsController = new TabsController();
1245  @State dividerColor: string = 'red';
1246  @State strokeWidth: number = 2;
1247  @State startMargin: number = 0;
1248  @State endMargin: number = 0;
1249  @State nullFlag: boolean = false;
1250
1251  build() {
1252    Column() {
1253      Tabs({ controller: this.controller1 }) {
1254        TabContent() {
1255          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1256        }.tabBar('pink')
1257
1258        TabContent() {
1259          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
1260        }.tabBar('yellow')
1261
1262        TabContent() {
1263          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1264        }.tabBar('blue')
1265
1266        TabContent() {
1267          Column().width('100%').height('100%').backgroundColor(Color.Green)
1268        }.tabBar('green')
1269
1270        TabContent() {
1271          Column().width('100%').height('100%').backgroundColor(Color.Red)
1272        }.tabBar('red')
1273      }
1274      .vertical(true)
1275      .scrollable(true)
1276      .barMode(BarMode.Fixed)
1277      .barWidth(70)
1278      .barHeight(200)
1279      .animationDuration(400)
1280      .onChange((index: number) => {
1281        console.info(index.toString());
1282      })
1283      .height('200vp')
1284      .margin({ bottom: '12vp' })
1285      .divider(this.nullFlag ? null : {
1286        strokeWidth: this.strokeWidth,
1287        color: this.dividerColor,
1288        startMargin: this.startMargin,
1289        endMargin: this.endMargin
1290      })
1291
1292      Button('常规Divider').width('100%').margin({ bottom: '12vp' })
1293        .onClick(() => {
1294          this.nullFlag = false;
1295          this.strokeWidth = 2;
1296          this.dividerColor = 'red';
1297          this.startMargin = 0;
1298          this.endMargin = 0;
1299        })
1300      Button('空Divider').width('100%').margin({ bottom: '12vp' })
1301        .onClick(() => {
1302          this.nullFlag = true;
1303        })
1304      Button('颜色变为蓝色').width('100%').margin({ bottom: '12vp' })
1305        .onClick(() => {
1306          this.dividerColor = 'blue';
1307        })
1308      Button('宽度增加').width('100%').margin({ bottom: '12vp' })
1309        .onClick(() => {
1310          this.strokeWidth += 2;
1311        })
1312      Button('宽度减小').width('100%').margin({ bottom: '12vp' })
1313        .onClick(() => {
1314          if (this.strokeWidth > 2) {
1315            this.strokeWidth -= 2;
1316          }
1317        })
1318      Button('上边距增加').width('100%').margin({ bottom: '12vp' })
1319        .onClick(() => {
1320          this.startMargin += 2;
1321        })
1322      Button('上边距减少').width('100%').margin({ bottom: '12vp' })
1323        .onClick(() => {
1324          if (this.startMargin > 2) {
1325            this.startMargin -= 2;
1326          }
1327        })
1328      Button('下边距增加').width('100%').margin({ bottom: '12vp' })
1329        .onClick(() => {
1330          this.endMargin += 2;
1331        })
1332      Button('下边距减少').width('100%').margin({ bottom: '12vp' })
1333        .onClick(() => {
1334          if (this.endMargin > 2) {
1335            this.endMargin -= 2;
1336          }
1337        })
1338    }.padding({ top: '24vp', left: '24vp', right: '24vp' })
1339  }
1340}
1341```
1342
1343![tabs4](figures/tabs_divider.gif)
1344
1345### 示例5(设置TabBar渐隐)
1346
1347本示例通过fadingEdge实现了切换子页签渐隐和不渐隐。
1348
1349```ts
1350// xxx.ets
1351@Entry
1352@Component
1353struct TabsOpaque {
1354  @State message: string = 'Hello World';
1355  private controller: TabsController = new TabsController();
1356  private controller1: TabsController = new TabsController();
1357  @State selfFadingFade: boolean = true;
1358
1359  build() {
1360    Column() {
1361      Button('子页签设置渐隐').width('100%').margin({ bottom: '12vp' })
1362        .onClick((event?: ClickEvent) => {
1363          this.selfFadingFade = true;
1364        })
1365      Button('子页签设置不渐隐').width('100%').margin({ bottom: '12vp' })
1366        .onClick((event?: ClickEvent) => {
1367          this.selfFadingFade = false;
1368        })
1369      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1370        TabContent() {
1371          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1372        }.tabBar('pink')
1373
1374        TabContent() {
1375          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
1376        }.tabBar('yellow')
1377
1378        TabContent() {
1379          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1380        }.tabBar('blue')
1381
1382        TabContent() {
1383          Column().width('100%').height('100%').backgroundColor(Color.Green)
1384        }.tabBar('green')
1385
1386        TabContent() {
1387          Column().width('100%').height('100%').backgroundColor(Color.Green)
1388        }.tabBar('green')
1389
1390        TabContent() {
1391          Column().width('100%').height('100%').backgroundColor(Color.Green)
1392        }.tabBar('green')
1393
1394        TabContent() {
1395          Column().width('100%').height('100%').backgroundColor(Color.Green)
1396        }.tabBar('green')
1397
1398        TabContent() {
1399          Column().width('100%').height('100%').backgroundColor(Color.Green)
1400        }.tabBar('green')
1401      }
1402      .vertical(false)
1403      .scrollable(true)
1404      .barMode(BarMode.Scrollable)
1405      .barHeight(80)
1406      .animationDuration(400)
1407      .onChange((index: number) => {
1408        console.info(index.toString());
1409      })
1410      .fadingEdge(this.selfFadingFade)
1411      .height('30%')
1412      .width('100%')
1413
1414      Tabs({ barPosition: BarPosition.Start, controller: this.controller1 }) {
1415        TabContent() {
1416          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1417        }.tabBar('pink')
1418
1419        TabContent() {
1420          Column().width('100%').height('100%').backgroundColor(Color.Yellow)
1421        }.tabBar('yellow')
1422
1423        TabContent() {
1424          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1425        }.tabBar('blue')
1426
1427        TabContent() {
1428          Column().width('100%').height('100%').backgroundColor(Color.Green)
1429        }.tabBar('green')
1430
1431        TabContent() {
1432          Column().width('100%').height('100%').backgroundColor(Color.Green)
1433        }.tabBar('green')
1434
1435        TabContent() {
1436          Column().width('100%').height('100%').backgroundColor(Color.Green)
1437        }.tabBar('green')
1438      }
1439      .vertical(true)
1440      .scrollable(true)
1441      .barMode(BarMode.Scrollable)
1442      .barHeight(200)
1443      .barWidth(80)
1444      .animationDuration(400)
1445      .onChange((index: number) => {
1446        console.info(index.toString());
1447      })
1448      .fadingEdge(this.selfFadingFade)
1449      .height('30%')
1450      .width('100%')
1451    }
1452    .padding({ top: '24vp', left: '24vp', right: '24vp' })
1453  }
1454}
1455```
1456
1457![tabs5](figures/tabs_fadingEdge.gif)
1458
1459### 示例6(设置TabBar叠加在TabContent内容上)
1460
1461本示例通过barOverlap实现了TabBar是否背后变模糊并叠加在TabContent之上。
1462
1463```ts
1464// xxx.ets
1465@Entry
1466@Component
1467struct barHeightTest {
1468  @State arr: number[] = [0, 1, 2, 3];
1469  @State barOverlap: boolean = true;
1470
1471  build() {
1472    Column() {
1473      Text(`barOverlap ${this.barOverlap}`).fontSize(16)
1474      Button("barOverlap变化").width('100%').margin({ bottom: '12vp' })
1475        .onClick((event?: ClickEvent) => {
1476          if (this.barOverlap) {
1477            this.barOverlap = false;
1478          } else {
1479            this.barOverlap = true;
1480          }
1481        })
1482
1483      Tabs({ barPosition: BarPosition.End }) {
1484        TabContent() {
1485          Column() {
1486            List({ space: 10 }) {
1487              ForEach(this.arr, (item: number) => {
1488                ListItem() {
1489                  Text("item" + item).width('80%').height(200).fontSize(16).textAlign(TextAlign.Center).backgroundColor('#fff8b81e')
1490                }
1491              }, (item: string) => item)
1492            }.width('100%').height('100%')
1493            .lanes(2).alignListItem(ListItemAlign.Center)
1494          }.width('100%').height('100%')
1495          .backgroundColor(Color.Pink)
1496        }
1497        .tabBar(new BottomTabBarStyle($r('sys.media.ohos_icon_mask_svg'), "测试0"))
1498      }
1499      .scrollable(false)
1500      .height('60%')
1501      .barOverlap(this.barOverlap)
1502    }
1503    .height(500)
1504    .padding({ top: '24vp', left: '24vp', right: '24vp' })
1505  }
1506}
1507```
1508
1509![tabs6](figures/tabs_barOverlap.gif)
1510
1511### 示例7(设置TabBar栅格化可见区域)
1512
1513本示例通过barGridAlign实现了以栅格化方式设置TabBar的可见区域。
1514
1515```ts
1516// xxx.ets
1517@Entry
1518@Component
1519struct TabsExample5 {
1520  private controller: TabsController = new TabsController();
1521  @State gridMargin: number = 10;
1522  @State gridGutter: number = 10;
1523  @State sm: number = -2;
1524  @State clickedContent: string = "";
1525
1526  build() {
1527    Column() {
1528      Row() {
1529        Button("gridMargin+10 " + this.gridMargin)
1530          .width('47%')
1531          .height(50)
1532          .margin({ top: 5 })
1533          .onClick((event?: ClickEvent) => {
1534            this.gridMargin += 10;
1535          })
1536          .margin({ right: '6%', bottom: '12vp' })
1537        Button("gridMargin-10 " + this.gridMargin)
1538          .width('47%')
1539          .height(50)
1540          .margin({ top: 5 })
1541          .onClick((event?: ClickEvent) => {
1542            this.gridMargin -= 10;
1543          })
1544          .margin({ bottom: '12vp' })
1545      }
1546
1547      Row() {
1548        Button("gridGutter+10 " + this.gridGutter)
1549          .width('47%')
1550          .height(50)
1551          .margin({ top: 5 })
1552          .onClick((event?: ClickEvent) => {
1553            this.gridGutter += 10;
1554          })
1555          .margin({ right: '6%', bottom: '12vp' })
1556        Button("gridGutter-10 " + this.gridGutter)
1557          .width('47%')
1558          .height(50)
1559          .margin({ top: 5 })
1560          .onClick((event?: ClickEvent) => {
1561            this.gridGutter -= 10;
1562          })
1563          .margin({ bottom: '12vp' })
1564      }
1565
1566      Row() {
1567        Button("sm+2 " + this.sm)
1568          .width('47%')
1569          .height(50)
1570          .margin({ top: 5 })
1571          .onClick((event?: ClickEvent) => {
1572            this.sm += 2;
1573          })
1574          .margin({ right: '6%' })
1575        Button("sm-2 " + this.sm).width('47%').height(50).margin({ top: 5 })
1576          .onClick((event?: ClickEvent) => {
1577            this.sm -= 2;
1578          })
1579      }
1580
1581      Text("点击内容:" + this.clickedContent).width('100%').height(200).margin({ top: 5 })
1582
1583
1584      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
1585        TabContent() {
1586          Column().width('100%').height('100%').backgroundColor(Color.Pink)
1587        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "1"))
1588
1589        TabContent() {
1590          Column().width('100%').height('100%').backgroundColor(Color.Green)
1591        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "2"))
1592
1593        TabContent() {
1594          Column().width('100%').height('100%').backgroundColor(Color.Blue)
1595        }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "3"))
1596      }
1597      .width('350vp')
1598      .animationDuration(300)
1599      .height('60%')
1600      .barGridAlign({ sm: this.sm, margin: this.gridMargin, gutter: this.gridGutter })
1601      .backgroundColor(0xf1f3f5)
1602      .onTabBarClick((index: number) => {
1603        this.clickedContent += "now index " + index + " is clicked\n";
1604      })
1605    }
1606    .width('100%')
1607    .height(500)
1608    .margin({ top: 5 })
1609    .padding('10vp')
1610  }
1611}
1612```
1613
1614![tabs7](figures/tabs_barGridAlign.gif)
1615
1616### 示例8(自定义Tabs页面切换动画)
1617
1618本示例通过customContentTransition实现了自定义Tabs页面的切换动画。
1619
1620```ts
1621// xxx.ets
1622interface itemType {
1623  text: string,
1624  backgroundColor: Color
1625}
1626
1627@Entry
1628@Component
1629struct TabsCustomAnimationExample {
1630  @State data: itemType[] = [
1631    {
1632      text: 'Red',
1633      backgroundColor: Color.Red
1634    },
1635    {
1636      text: 'Yellow',
1637      backgroundColor: Color.Yellow
1638    },
1639    {
1640      text: 'Blue',
1641      backgroundColor: Color.Blue
1642    }];
1643  @State opacityList: number[] = [];
1644  @State scaleList: number[] = [];
1645
1646  private durationList: number[] = [];
1647  private timeoutList: number[] = [];
1648  private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => {
1649    let tabContentAnimatedTransition = {
1650      timeout: this.timeoutList[from],
1651      transition: (proxy: TabContentTransitionProxy) => {
1652        this.scaleList[from] = 1.0;
1653        this.scaleList[to] = 0.5;
1654        this.opacityList[from] = 1.0;
1655        this.opacityList[to] = 0.5;
1656        this.getUIContext()?.animateTo({
1657          duration: this.durationList[from],
1658          onFinish: () => {
1659            proxy.finishTransition();
1660          }
1661        }, () => {
1662          this.scaleList[from] = 0.5;
1663          this.scaleList[to] = 1.0;
1664          this.opacityList[from] = 0.5;
1665          this.opacityList[to] = 1.0;
1666        });
1667      }
1668    } as TabContentAnimatedTransition;
1669    return tabContentAnimatedTransition;
1670  };
1671
1672  aboutToAppear(): void {
1673    let duration = 1000;
1674    let timeout = 1000;
1675    for (let i = 1; i <= this.data.length; i++) {
1676      this.opacityList.push(1.0);
1677      this.scaleList.push(1.0);
1678      this.durationList.push(duration * i);
1679      this.timeoutList.push(timeout * i);
1680    }
1681  }
1682
1683  build() {
1684    Column() {
1685      Tabs() {
1686        ForEach(this.data, (item: itemType, index: number) => {
1687          TabContent() {}
1688          .tabBar(item.text)
1689          .backgroundColor(item.backgroundColor)
1690          // 自定义动画变化透明度、缩放页面等
1691          .opacity(this.opacityList[index])
1692          .scale({ x: this.scaleList[index], y: this.scaleList[index] })
1693        })
1694      }
1695      .backgroundColor(0xf1f3f5)
1696      .width('100%')
1697      .height(500)
1698      .customContentTransition(this.customContentTransition)
1699    }
1700  }
1701}
1702```
1703
1704![tabs8](figures/tabs8.gif)
1705
1706### 示例9(页面切换拦截)
1707
1708本示例通过onContentWillChange实现了自定义页面手势滑动切换拦截。
1709
1710```ts
1711//xxx.ets
1712@Entry
1713@Component
1714struct TabsExample {
1715  @State selectedIndex: number = 2;
1716  @State currentIndex: number = 2;
1717  private controller: TabsController = new TabsController();
1718
1719  @Builder tabBuilder(title: string,targetIndex: number) {
1720    Column(){
1721      Image(this.selectedIndex === targetIndex ? $r('app.media.star_fill') : $r('app.media.star'))
1722        .width(24)
1723        .height(24)
1724        .margin({ bottom: 4 })
1725        .objectFit(ImageFit.Contain)
1726      Text(title).fontColor(this.selectedIndex === targetIndex ? '#1698CE' : '#6B6B6B')
1727    }.width('100%')
1728    .height(50)
1729    .justifyContent(FlexAlign.Center)
1730  }
1731
1732  build() {
1733    Column() {
1734      Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) {
1735        TabContent() {
1736          Column(){
1737            Text('首页的内容')
1738          }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
1739        }.tabBar(this.tabBuilder('首页',0))
1740
1741        TabContent() {
1742          Column(){
1743            Text('发现的内容')
1744          }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center)
1745        }.tabBar(this.tabBuilder('发现',1))
1746
1747        TabContent() {
1748          Column(){
1749            Text('推荐的内容')
1750          }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center)
1751        }.tabBar(this.tabBuilder('推荐',2))
1752
1753        TabContent() {
1754          Column(){
1755            Text('我的内容')
1756          }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center)
1757        }.tabBar(this.tabBuilder('我的',3))
1758      }
1759      .vertical(false)
1760      .barMode(BarMode.Fixed)
1761      .barWidth(360)
1762      .barHeight(60)
1763      .animationDuration(0)
1764      .onChange((index: number) => {
1765        this.currentIndex = index;
1766        this.selectedIndex = index;
1767      })
1768      .width(360)
1769      .height(600)
1770      .backgroundColor('#F1F3F5')
1771      .scrollable(true)
1772      .onContentWillChange((currentIndex, comingIndex) => {
1773        if (comingIndex == 2) {
1774          return false;
1775        }
1776        return true;
1777      })
1778
1779      Button('动态修改index').width('50%').margin({ top: 20 })
1780        .onClick(()=>{
1781          this.currentIndex = (this.currentIndex + 1) % 4;
1782        })
1783
1784      Button('changeIndex').width('50%').margin({ top: 20 })
1785        .onClick(()=>{
1786          this.currentIndex = (this.currentIndex + 1) % 4;
1787          this.controller.changeIndex(this.currentIndex);
1788        })
1789    }.width('100%')
1790  }
1791}
1792```
1793
1794![tabs9](figures/tabs9.gif)
1795
1796### 示例10(自定义TabBar切换动画)
1797
1798本示例通过onChange、onAnimationStart、onAnimationEnd、onGestureSwipe等接口实现了自定义TabBar的切换动画。
1799
1800<!--code_no_check-->
1801
1802```ts
1803// EntryAbility.ets
1804import { Configuration, UIAbility } from '@kit.AbilityKit';
1805import { i18n } from '@kit.LocalizationKit';
1806import { CommonUtil } from '../common/CommonUtil';
1807
1808export default class EntryAbility extends UIAbility {
1809  onConfigurationUpdate(newConfig: Configuration): void {
1810    // 监听系统配置变化
1811    if (newConfig.language) {
1812      CommonUtil.setIsRTL(i18n.isRTL(newConfig.language));
1813    }
1814  }
1815}
1816```
1817
1818<!--code_no_check-->
1819
1820```ts
1821// CommonUtil.ets
1822import { i18n, intl } from '@kit.LocalizationKit';
1823
1824export class CommonUtil {
1825  private static isRTL: boolean = i18n.isRTL((new intl.Locale()).language);
1826
1827  public static setIsRTL(isRTL: boolean): void {
1828    CommonUtil.isRTL = isRTL;
1829  }
1830
1831  public static getIsRTL(): boolean {
1832    return CommonUtil.isRTL;
1833  }
1834}
1835```
1836
1837<!--code_no_check-->
1838
1839```ts
1840// xxx.ets
1841import { LengthMetrics } from '@kit.ArkUI';
1842import { CommonUtil } from '../common/CommonUtil';
1843
1844@Entry
1845@Component
1846struct TabsExample {
1847  @State colorArray: [string, string][] =
1848    [['green', '#00CB87'], ['blue', '#007DFF'], ['yellow', '#FFBF00'], ['pink', '#E67C92']];
1849  @State currentIndex: number = 0;
1850  @State animationDuration: number = 300;
1851  @State indicatorLeftMargin: number = 0;
1852  @State indicatorWidth: number = 0;
1853  private tabsWidth: number = 0;
1854  private textInfos: [number, number][] = [];
1855  private isStartAnimateTo: boolean = false;
1856
1857  aboutToAppear():void {
1858    for (let i = 0; i < this.colorArray.length; i++) {
1859      this.textInfos.push([0, 0]);
1860    }
1861  }
1862
1863  @Builder
1864  tabBuilder(index: number, name: string) {
1865    Column() {
1866      Text(name)
1867        .fontSize(16)
1868        .fontColor(this.currentIndex === index ? '#007DFF' : '#182431')
1869        .fontWeight(this.currentIndex === index ? 500 : 400)
1870        .id(index.toString())
1871        .onAreaChange((oldValue: Area, newValue: Area) => {
1872          this.textInfos[index] = [newValue.globalPosition.x as number, newValue.width as number];
1873          if (!this.isStartAnimateTo && this.currentIndex === index && this.tabsWidth > 0) {
1874            this.setIndicatorAttr(this.textInfos[this.currentIndex][0], this.textInfos[this.currentIndex][1]);
1875          }
1876        })
1877    }.width('100%')
1878  }
1879
1880  build() {
1881    Stack({ alignContent: Alignment.TopStart }) {
1882      Tabs({ barPosition: BarPosition.Start }) {
1883        ForEach(this.colorArray, (item: [string, string], index:number) => {
1884          TabContent() {
1885            Column().width('100%').height('100%').backgroundColor(item[1])
1886          }.tabBar(this.tabBuilder(index, item[0]))
1887        })
1888      }
1889      .onAreaChange((oldValue: Area, newValue: Area)=> {
1890        this.tabsWidth = newValue.width as number;
1891        if (!this.isStartAnimateTo) {
1892          this.setIndicatorAttr(this.textInfos[this.currentIndex][0], this.textInfos[this.currentIndex][1]);
1893        }
1894      })
1895      .barWidth('100%')
1896      .barHeight(56)
1897      .width('100%')
1898      .height(296)
1899      .backgroundColor('#F1F3F5')
1900      .animationDuration(this.animationDuration)
1901      .onChange((index: number) => {
1902        this.currentIndex = index; // 监听索引index的变化,实现页签内容的切换。
1903      })
1904      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
1905        // 切换动画开始时触发该回调。下划线跟着页面一起滑动,同时宽度渐变。
1906        this.currentIndex = targetIndex;
1907        this.startAnimateTo(this.animationDuration, this.textInfos[targetIndex][0], this.textInfos[targetIndex][1]);
1908      })
1909      .onAnimationEnd((index: number, event: TabsAnimationEvent) => {
1910        // 切换动画结束时触发该回调。下划线动画停止。
1911        let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event);
1912        this.startAnimateTo(0, currentIndicatorInfo.left, currentIndicatorInfo.width);
1913      })
1914      .onGestureSwipe((index: number, event: TabsAnimationEvent) => {
1915        // 在页面跟手滑动过程中,逐帧触发该回调。
1916        let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event);
1917        this.currentIndex = currentIndicatorInfo.index;
1918        this.setIndicatorAttr(currentIndicatorInfo.left, currentIndicatorInfo.width);
1919      })
1920
1921      Column()
1922        .height(2)
1923        .width(this.indicatorWidth)
1924        .margin({ start: LengthMetrics.vp(this.indicatorLeftMargin), top: LengthMetrics.vp(48) })
1925        .backgroundColor('#007DFF')
1926    }.width('100%')
1927  }
1928
1929  private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
1930    let nextIndex = index;
1931    if (index > 0 && (CommonUtil.getIsRTL() ? event.currentOffset < 0 : event.currentOffset > 0)) {
1932      nextIndex--;
1933    } else if (index < this.textInfos.length - 1 &&
1934        (CommonUtil.getIsRTL() ? event.currentOffset > 0 : event.currentOffset < 0)) {
1935      nextIndex++;
1936    }
1937    let indexInfo = this.textInfos[index];
1938    let nextIndexInfo = this.textInfos[nextIndex];
1939    let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth);
1940    let currentIndex = swipeRatio > 0.5 ? nextIndex : index; // 页面滑动超过一半,tabBar切换到下一页。
1941    let currentLeft = indexInfo[0] + (nextIndexInfo[0] - indexInfo[0]) * swipeRatio;
1942    let currentWidth = indexInfo[1] + (nextIndexInfo[1] - indexInfo[1]) * swipeRatio;
1943    return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth };
1944  }
1945
1946  private startAnimateTo(duration: number, leftMargin: number, width: number) {
1947    this.isStartAnimateTo = true;
1948    this.getUIContext()?.animateTo({
1949      duration: duration, // 动画时长
1950      curve: Curve.Linear, // 动画曲线
1951      iterations: 1, // 播放次数
1952      playMode: PlayMode.Normal, // 动画模式
1953      onFinish: () => {
1954        this.isStartAnimateTo = false;
1955        console.info('play end');
1956      }
1957    }, () => {
1958      this.setIndicatorAttr(leftMargin, width);
1959    });
1960  }
1961
1962  private setIndicatorAttr(leftMargin: number, width: number) {
1963    this.indicatorWidth = width;
1964    if (CommonUtil.getIsRTL()) {
1965      this.indicatorLeftMargin = this.tabsWidth - leftMargin - width;
1966    } else {
1967      this.indicatorLeftMargin = leftMargin;
1968    }
1969  }
1970}
1971```
1972
1973![tabs10](figures/tabs10.gif)
1974
1975### 示例11(预加载子节点)
1976
1977本示例通过preloadItems接口实现了预加载指定子节点。
1978
1979```ts
1980// xxx.ets
1981import { BusinessError } from '@kit.BasicServicesKit';
1982
1983@Entry
1984@Component
1985struct TabsPreloadItems {
1986  @State currentIndex: number = 1;
1987  private tabsController: TabsController = new TabsController();
1988
1989  build() {
1990    Column() {
1991      Tabs({ index: this.currentIndex, controller: this.tabsController }) {
1992        TabContent() {
1993          MyComponent({ color: '#00CB87' })
1994        }.tabBar(SubTabBarStyle.of('green'))
1995
1996        TabContent() {
1997          MyComponent({ color: '#007DFF' })
1998        }.tabBar(SubTabBarStyle.of('blue'))
1999
2000        TabContent() {
2001          MyComponent({ color: '#FFBF00' })
2002        }.tabBar(SubTabBarStyle.of('yellow'))
2003
2004        TabContent() {
2005          MyComponent({ color: '#E67C92' })
2006        }.tabBar(SubTabBarStyle.of('pink'))
2007      }
2008      .width(360)
2009      .height(296)
2010      .backgroundColor('#F1F3F5')
2011      .onChange((index: number) => {
2012        this.currentIndex = index;
2013      })
2014
2015      Button('preload items: [0, 2, 3]')
2016        .margin(5)
2017        .onClick(() => {
2018          // 预加载第0、2、3个子节点,提高滑动或点击切换至这些节点时的性能
2019          this.tabsController.preloadItems([0, 2, 3])
2020            .then(() => {
2021              console.info('preloadItems success.');
2022            })
2023            .catch((error: BusinessError) => {
2024              console.error('preloadItems failed, error code: ' + error.code + ', error message: ' + error.message);
2025            })
2026        })
2027    }
2028  }
2029}
2030
2031@Component
2032struct MyComponent {
2033  private color: string = "";
2034
2035  aboutToAppear(): void {
2036    console.info('aboutToAppear backgroundColor:' + this.color);
2037  }
2038
2039  aboutToDisappear(): void {
2040    console.info('aboutToDisappear backgroundColor:' + this.color);
2041  }
2042
2043  build() {
2044    Column()
2045      .width('100%')
2046      .height('100%')
2047      .backgroundColor(this.color)
2048  }
2049}
2050```
2051
2052### 示例12(设置TabBar平移距离和不透明度)
2053
2054本示例通过setTabBarTranslate、setTabBarOpacity等接口设置了TabBar的平移距离和不透明度。
2055
2056```ts
2057// xxx.ets
2058@Entry
2059@Component
2060struct TabsExample {
2061  private controller: TabsController = new TabsController();
2062
2063  build() {
2064    Column() {
2065      Button('设置TabBar的平移距离').margin({ top: 20 })
2066        .onClick(() => {
2067          this.controller.setTabBarTranslate({ x: -20, y: -20 });
2068        })
2069
2070      Button('设置TabBar的透明度').margin({ top: 20 })
2071        .onClick(() => {
2072          this.controller.setTabBarOpacity(0.5);
2073        })
2074
2075      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
2076        TabContent() {
2077          Column().width('100%').height('100%').backgroundColor('#00CB87')
2078        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'green'))
2079
2080        TabContent() {
2081          Column().width('100%').height('100%').backgroundColor('#007DFF')
2082        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'blue'))
2083
2084        TabContent() {
2085          Column().width('100%').height('100%').backgroundColor('#FFBF00')
2086        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'yellow'))
2087
2088        TabContent() {
2089          Column().width('100%').height('100%').backgroundColor('#E67C92')
2090        }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'pink'))
2091      }
2092      .width(360)
2093      .height(296)
2094      .margin({ top: 20 })
2095      .barBackgroundColor('#F1F3F5')
2096    }
2097    .width('100%')
2098  }
2099}
2100```
2101
2102![tabs12](figures/tabBar_translate_opacity.gif)
2103
2104### 示例13(页面懒加载和释放)
2105
2106本示例通过使用自定义TabBar与Swiper配合LazyForEach实现页面懒加载和释放。
2107
2108```ts
2109// xxx.ets
2110class MyDataSource implements IDataSource {
2111  private list: number[] = [];
2112
2113  constructor(list: number[]) {
2114    this.list = list;
2115  }
2116
2117  totalCount(): number {
2118    return this.list.length;
2119  }
2120
2121  getData(index: number): number {
2122    return this.list[index];
2123  }
2124
2125  registerDataChangeListener(listener: DataChangeListener): void {
2126  }
2127
2128  unregisterDataChangeListener() {
2129  }
2130}
2131
2132@Entry
2133@Component
2134struct TabsSwiperExample {
2135  @State fontColor: string = '#182431';
2136  @State selectedFontColor: string = '#007DFF';
2137  @State currentIndex: number = 0;
2138  private list: number[] = [];
2139  private tabsController: TabsController = new TabsController();
2140  private swiperController: SwiperController = new SwiperController();
2141  private swiperData: MyDataSource = new MyDataSource([]);
2142
2143  aboutToAppear(): void {
2144    for (let i = 0; i <= 9; i++) {
2145      this.list.push(i);
2146    }
2147    this.swiperData = new MyDataSource(this.list);
2148  }
2149
2150  @Builder tabBuilder(index: number, name: string) {
2151    Column() {
2152      Text(name)
2153        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
2154        .fontSize(16)
2155        .fontWeight(this.currentIndex === index ? 500 : 400)
2156        .lineHeight(22)
2157        .margin({ top: 17, bottom: 7 })
2158      Divider()
2159        .strokeWidth(2)
2160        .color('#007DFF')
2161        .opacity(this.currentIndex === index ? 1 : 0)
2162    }.width('20%')
2163  }
2164
2165  build() {
2166    Column() {
2167      Tabs({ barPosition: BarPosition.Start, controller: this.tabsController }) {
2168        ForEach(this.list, (item: number) => {
2169          TabContent().tabBar(this.tabBuilder(item, '页签 ' + this.list[item]))
2170        })
2171      }
2172      .onTabBarClick((index: number) => {
2173        this.currentIndex = index;
2174        this.swiperController.changeIndex(index, true);
2175      })
2176      .barMode(BarMode.Scrollable)
2177      .backgroundColor('#F1F3F5')
2178      .height(56)
2179      .width('100%')
2180
2181      Swiper(this.swiperController) {
2182        LazyForEach(this.swiperData, (item: string) => {
2183          Text(item.toString())
2184            .onAppear(()=>{
2185              console.info('onAppear ' + item.toString());
2186            })
2187            .onDisAppear(()=>{
2188              console.info('onDisAppear ' + item.toString());
2189            })
2190            .width('100%')
2191            .height('100%')
2192            .backgroundColor(0xAFEEEE)
2193            .textAlign(TextAlign.Center)
2194            .fontSize(30)
2195        }, (item: string) => item)
2196      }
2197      .loop(false)
2198      .onChange((index: number) => {
2199        this.currentIndex = index;
2200      })
2201      .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => {
2202        this.currentIndex = targetIndex;
2203        this.tabsController.changeIndex(targetIndex);
2204      })
2205    }
2206  }
2207}
2208```
2209
2210![tabs13](figures/tabs_swiper_lazyForEach.gif)
2211
2212### 示例14(设置翻页动效)
2213
2214本示例通过设置animationMode属性,实现了翻页的动效。
2215
2216```ts
2217// xxx.ets
2218@Entry
2219@Component
2220struct TabsExample {
2221  @State currentIndex: number = 0;
2222  @State currentAnimationMode: AnimationMode = AnimationMode.CONTENT_FIRST;
2223  private controller: TabsController = new TabsController();
2224  private data: number[] = [];
2225
2226  aboutToAppear(): void {
2227    for (let i = 0; i < 10; i++) {
2228      this.data.push(i);
2229    }
2230  }
2231
2232  @Builder
2233  tabBuilder(title: string,targetIndex: number) {
2234    Column(){
2235      Text(title).fontColor(this.currentIndex === targetIndex ? '#FF0000' : '#6B6B6B')
2236    }.width('100%')
2237    .height(50)
2238    .justifyContent(FlexAlign.Center)
2239  }
2240
2241  build() {
2242    Column() {
2243      Tabs({ barPosition: BarPosition.End, controller: this.controller, index: this.currentIndex }) {
2244        ForEach(this.data, (item: string) => {
2245          TabContent() {
2246            Column(){
2247              Text('' + item)
2248            }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
2249          }.tabBar(this.tabBuilder('P' + item, parseInt(item)))
2250        }, (item: string) => item)
2251      }
2252      .barWidth(360)
2253      .barHeight(60)
2254      .animationMode(this.currentAnimationMode)
2255      .animationDuration(4000)
2256      .onChange((index: number) => {
2257        this.currentIndex = index;
2258      })
2259      .width(360)
2260      .height(120)
2261      .backgroundColor('#F1F3F5')
2262
2263      Text('AnimationMode:' + AnimationMode[this.currentAnimationMode])
2264
2265      Button('AnimationMode').width('50%').margin({ top: 1 }).height(25)
2266        .onClick(()=>{
2267          if (this.currentAnimationMode === AnimationMode.CONTENT_FIRST) {
2268            this.currentAnimationMode = AnimationMode.ACTION_FIRST;
2269          } else if (this.currentAnimationMode === AnimationMode.ACTION_FIRST) {
2270            this.currentAnimationMode = AnimationMode.NO_ANIMATION;
2271          } else if (this.currentAnimationMode === AnimationMode.NO_ANIMATION) {
2272            this.currentAnimationMode = AnimationMode.CONTENT_FIRST_WITH_JUMP;
2273          } else if (this.currentAnimationMode === AnimationMode.CONTENT_FIRST_WITH_JUMP) {
2274            this.currentAnimationMode = AnimationMode.ACTION_FIRST_WITH_JUMP;
2275          } else if (this.currentAnimationMode === AnimationMode.ACTION_FIRST_WITH_JUMP) {
2276            this.currentAnimationMode = AnimationMode.CONTENT_FIRST;
2277          }
2278        })
2279    }.width('100%')
2280  }
2281}
2282```
2283
2284![tabs14](figures/tabs_animationMode.gif)
2285
2286### 示例15(页签超出TabBar区域显示)
2287
2288本示例通过使用barModifier设置tabBar的clip属性实现页签超出tabBar区域显示效果。
2289
2290```ts
2291// xxx.ets
2292import { CommonModifier } from '@kit.ArkUI';
2293
2294@Entry
2295@Component
2296struct TabsBarModifierExample {
2297  @State selectedIndex: number = 2;
2298  @State currentIndex: number = 2;
2299  @State isClip: boolean = false;
2300  @State tabBarModifier: CommonModifier = new CommonModifier();
2301  private controller: TabsController = new TabsController();
2302
2303  aboutToAppear(): void {
2304    this.tabBarModifier.clip(this.isClip);
2305  }
2306
2307  @Builder
2308  tabBuilder(title: string, targetIndex: number) {
2309    Column() {
2310      Image($r("app.media.startIcon")).width(30).height(30)
2311      Text(title).fontColor(this.selectedIndex === targetIndex ? '#1698CE' : '#6B6B6B')
2312    }.width('100%')
2313    .height(50)
2314    .justifyContent(FlexAlign.Center)
2315    .offset({ y: this.selectedIndex === targetIndex ? -15 : 0 })
2316  }
2317
2318  build() {
2319    Column() {
2320      Tabs({
2321        barPosition: BarPosition.End,
2322        index: this.currentIndex,
2323        controller: this.controller,
2324        barModifier: this.tabBarModifier
2325      }) {
2326        TabContent() {
2327          Column() {
2328            Text('首页的内容')
2329          }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
2330        }.tabBar(this.tabBuilder('首页', 0))
2331
2332        TabContent() {
2333          Column() {
2334            Text('发现的内容')
2335          }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center)
2336        }.tabBar(this.tabBuilder('发现', 1))
2337
2338        TabContent() {
2339          Column() {
2340            Text('推荐的内容')
2341          }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center)
2342        }.tabBar(this.tabBuilder('推荐', 2))
2343
2344        TabContent() {
2345          Column() {
2346            Text('我的内容')
2347          }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center)
2348        }.tabBar(this.tabBuilder('我的', 3))
2349      }
2350      .vertical(false)
2351      .barMode(BarMode.Fixed)
2352      .barWidth(340)
2353      .barHeight(60)
2354      .onChange((index: number) => {
2355        this.currentIndex = index;
2356        this.selectedIndex = index;
2357      })
2358      .width(340)
2359      .height(400)
2360      .backgroundColor('#F1F3F5')
2361      .scrollable(true)
2362
2363      Button("isClip: " + this.isClip)
2364        .margin({ top: 30 })
2365        .onClick(() => {
2366          this.isClip = !this.isClip;
2367          this.tabBarModifier.clip(this.isClip);
2368        })
2369    }.width('100%')
2370  }
2371}
2372```
2373
2374![tabs15](figures/tabs_barModifier_clip.gif)
2375
2376### 示例16(页签对齐布局)
2377
2378本示例通过使用barModifier设置tabBar的align属性实现页签对齐布局效果。
2379
2380```ts
2381// xxx.ets
2382import { CommonModifier } from '@kit.ArkUI';
2383
2384@Entry
2385@Component
2386struct TabsBarModifierExample {
2387  private controller: TabsController = new TabsController();
2388  @State text: string = "文本";
2389  @State isVertical: boolean = false;
2390  @State tabBarModifier: CommonModifier = new CommonModifier();
2391
2392  build() {
2393    Column() {
2394      Row() {
2395        Button("Alignment.Start ")
2396          .width('47%')
2397          .height(50)
2398          .margin({ top: 5 })
2399          .onClick((event?: ClickEvent) => {
2400            this.tabBarModifier.align(Alignment.Start);
2401          })
2402          .margin({ right: '6%', bottom: '12vp' })
2403        Button("Alignment.End")
2404          .width('47%')
2405          .height(50)
2406          .margin({ top: 5 })
2407          .onClick((event?: ClickEvent) => {
2408            this.tabBarModifier.align(Alignment.End);
2409          })
2410          .margin({ bottom: '12vp' })
2411      }
2412
2413      Row() {
2414        Button("Alignment.Center")
2415          .width('47%')
2416          .height(50)
2417          .margin({ top: 5 })
2418          .onClick((event?: ClickEvent) => {
2419            this.tabBarModifier.align(Alignment.Center);
2420          })
2421          .margin({ right: '6%', bottom: '12vp' })
2422        Button("isVertical: " + this.isVertical)
2423          .width('47%')
2424          .height(50)
2425          .margin({ top: 5 })
2426          .onClick((event?: ClickEvent) => {
2427            this.isVertical = !this.isVertical;
2428          })
2429          .margin({ bottom: '12vp' })
2430      }
2431
2432      Row() {
2433        Button("Alignment.Top")
2434          .width('47%')
2435          .height(50)
2436          .margin({ top: 5 })
2437          .onClick((event?: ClickEvent) => {
2438            this.tabBarModifier.align(Alignment.Top);
2439          })
2440          .margin({ right: '6%', bottom: '12vp' })
2441        Button("Alignment.Bottom")
2442          .width('47%')
2443          .height(50)
2444          .margin({ top: 5 })
2445          .onClick((event?: ClickEvent) => {
2446            this.tabBarModifier.align(Alignment.Bottom);
2447          })
2448          .margin({ bottom: '12vp' })
2449      }
2450
2451      Tabs({ barPosition: BarPosition.End, controller: this.controller, barModifier: this.tabBarModifier }) {
2452        TabContent() {
2453          Column().width('100%').height('100%').backgroundColor(Color.Pink)
2454        }.tabBar(SubTabBarStyle.of(this.text))
2455
2456        TabContent() {
2457          Column().width('100%').height('100%').backgroundColor(Color.Green)
2458        }.tabBar(SubTabBarStyle.of(this.text))
2459
2460        TabContent() {
2461          Column().width('100%').height('100%').backgroundColor(Color.Blue)
2462        }.tabBar(SubTabBarStyle.of(this.text))
2463      }
2464      .vertical(this.isVertical)
2465      .height('60%')
2466      .backgroundColor(0xf1f3f5)
2467      .barMode(BarMode.Scrollable)
2468    }
2469    .width('100%')
2470    .height(500)
2471    .margin({ top: 5 })
2472    .padding('24vp')
2473  }
2474}
2475```
2476
2477![tabs16](figures/tabs_barModifier_align.gif)
2478
2479### 示例17(Tabs与TabBar联动切换)
2480
2481该示例通过onSelected接口,实现了Tabs与TabBar联动切换。
2482
2483```ts
2484// xxx.ets
2485@Entry
2486@Component
2487struct TabsExample {
2488  @State fontColor: string = '#182431';
2489  @State selectedFontColor: string = '#007DFF';
2490  @State currentIndex: number = 0;
2491  @State selectedIndex: number = 0;
2492  private controller: TabsController = new TabsController();
2493
2494  @Builder tabBuilder(index: number, name: string) {
2495    Column() {
2496      Text(name)
2497        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
2498        .fontSize(16)
2499        .fontWeight(this.selectedIndex === index ? 500 : 400)
2500        .lineHeight(22)
2501        .margin({ top: 17, bottom: 7 })
2502      Divider()
2503        .strokeWidth(2)
2504        .color('#007DFF')
2505        .opacity(this.selectedIndex === index ? 1 : 0)
2506    }.width('100%')
2507  }
2508
2509  build() {
2510    Column() {
2511      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
2512        TabContent() {
2513          Column().width('100%').height('100%').backgroundColor('#00CB87')
2514        }.tabBar(this.tabBuilder(0, 'green'))
2515
2516        TabContent() {
2517          Column().width('100%').height('100%').backgroundColor('#007DFF')
2518        }.tabBar(this.tabBuilder(1, 'blue'))
2519
2520        TabContent() {
2521          Column().width('100%').height('100%').backgroundColor('#FFBF00')
2522        }.tabBar(this.tabBuilder(2, 'yellow'))
2523
2524        TabContent() {
2525          Column().width('100%').height('100%').backgroundColor('#E67C92')
2526        }.tabBar(this.tabBuilder(3, 'pink'))
2527      }
2528      .vertical(false)
2529      .barMode(BarMode.Fixed)
2530      .barWidth(360)
2531      .barHeight(56)
2532      .animationDuration(400)
2533      .animationMode(AnimationMode.CONTENT_FIRST)
2534      .onChange((index: number) => {
2535        console.log("onChange index:" + index);
2536        this.currentIndex = index;
2537      })
2538      .onSelected((index: number) => {
2539        console.log("onSelected index:" + index);
2540        this.selectedIndex = index;
2541      })
2542      .onUnselected((index: number) => {
2543        console.log("onUnselected index:" + index);
2544      })
2545      .width('100%')
2546      .height('100%')
2547      .backgroundColor('#F1F3F5')
2548    }.width('100%')
2549  }
2550}
2551```
2552![tabs17](figures/tabs_tarbar.gif)
2553
2554### 示例18(设置TabBar背景模糊效果)
2555
2556该示例分别通过barBackgroundBlurStyle和barBackgroundEffect设置TabsBar页签栏的背景模糊效果。
2557
2558```ts
2559// xxx.ets
2560@Entry
2561@Component
2562struct TabsExample {
2563  build() {
2564    Column() {
2565      // barBackgroundBlurStyle 可以通过枚举值的方式设置模糊参数
2566      Stack() {
2567        Image($r('app.media.startIcon'))
2568        Tabs() {
2569          TabContent() {
2570            Column().width('100%').height('100%').backgroundColor('#00CB87')
2571          }.tabBar('green')
2572
2573          TabContent() {
2574            Column().width('100%').height('100%').backgroundColor('#007DFF')
2575          }.tabBar('blue')
2576
2577          TabContent() {
2578            Column().width('100%').height('100%').backgroundColor('#FFBF00')
2579          }.tabBar('yellow')
2580
2581          TabContent() {
2582            Column().width('100%').height('100%').backgroundColor('#E67C92')
2583          }.tabBar('pink')
2584        }
2585        .barBackgroundBlurStyle(BlurStyle.COMPONENT_THICK,
2586          { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 })
2587      }
2588      .width(300)
2589      .height(300)
2590      .margin(10)
2591
2592      // barBackgroundEffect 可以自定义设置tabBar页签栏的模糊半径、亮度、饱和度等参数
2593      Stack() {
2594        Image($r('app.media.startIcon'))
2595        Tabs() {
2596          TabContent() {
2597            Column().width('100%').height('100%').backgroundColor('#00CB87')
2598          }.tabBar('green')
2599
2600          TabContent() {
2601            Column().width('100%').height('100%').backgroundColor('#007DFF')
2602          }.tabBar('blue')
2603
2604          TabContent() {
2605            Column().width('100%').height('100%').backgroundColor('#FFBF00')
2606          }.tabBar('yellow')
2607
2608          TabContent() {
2609            Column().width('100%').height('100%').backgroundColor('#E67C92')
2610          }.tabBar('pink')
2611        }
2612        .barBackgroundEffect({ radius: 20, brightness: 0.6, saturation: 15 })
2613      }
2614      .width(300)
2615      .height(300)
2616      .margin(10)
2617    }
2618  }
2619}
2620```
2621![tabs18](figures/tabBar_backgroud.png)
2622
2623### 示例19(设置边缘滑动效果)
2624
2625该示例通过edgeEffect实现不同边缘滑动效果。
2626
2627```ts
2628// xxx.ets
2629@Entry
2630@Component
2631struct TabsExample {
2632  @State edgeEffect: EdgeEffect = EdgeEffect.Spring;
2633
2634  build() {
2635    Column() {
2636      Tabs() {
2637        TabContent() {
2638          Column().width('100%').height('100%').backgroundColor('#00CB87')
2639        }.tabBar('green')
2640
2641        TabContent() {
2642          Column().width('100%').height('100%').backgroundColor('#007DFF')
2643        }.tabBar('blue')
2644
2645        TabContent() {
2646          Column().width('100%').height('100%').backgroundColor('#FFBF00')
2647        }.tabBar('yellow')
2648
2649        TabContent() {
2650          Column().width('100%').height('100%').backgroundColor('#E67C92')
2651        }.tabBar('pink')
2652      }
2653      .width(360)
2654      .height(296)
2655      .margin({ top: 52 })
2656      .backgroundColor('#F1F3F5')
2657      .edgeEffect(this.edgeEffect)
2658
2659      Button('EdgeEffect.Spring').width('50%').margin({ top: 20 })
2660        .onClick(() => {
2661          this.edgeEffect = EdgeEffect.Spring;
2662        })
2663
2664      Button('EdgeEffect.Fade').width('50%').margin({ top: 20 })
2665        .onClick(() => {
2666          this.edgeEffect = EdgeEffect.Fade;
2667        })
2668
2669      Button('EdgeEffect.None').width('50%').margin({ top: 20 })
2670        .onClick(() => {
2671          this.edgeEffect = EdgeEffect.None;
2672        })
2673    }.width('100%')
2674  }
2675}
2676```
2677![tabs19](figures/tabs_edges_slide.gif)
2678