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.Fixed。 124 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.Scrollable。 140 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对象说明) \| 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<EdgeEffect>) 350 351设置边缘回弹效果。 352 353**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 354 355**系统能力:** SystemCapability.ArkUI.ArkUI.Full 356 357**参数:** 358 359| 参数名 | 类型 | 必填 | 说明 | 360| ------ | --------------------------------------------- | ---- | -------------------------------------------- | 361| edgeEffect | Optional<[EdgeEffect](ts-appendix-enums.md#edgeeffect)> | 是 | 边缘滑动效果。<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) \| 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 2678