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](../../../quick-start/arkts-rendering-control-ifelse.md)和[ForEach](../../../quick-start/arkts-rendering-control-foreach.md), 并且if/else和ForEach下也仅支持TabContent, 不支持自定义组件。 15 16> **说明:** 17> 18> Tabs子组件的visibility属性设置为None,或者visibility属性设置为Hidden时,对应子组件不显示,但依然会在视窗内占位。 19 20 21## 接口 22 23Tabs(value?: {barPosition?: BarPosition, index?: number, controller?: TabsController}) 24 25**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 26 27**系统能力:** SystemCapability.ArkUI.ArkUI.Full 28 29**参数:** 30 31| 参数名 | 类型 | 必填 | 说明 | 32| ----------- | --------------------------------- | ---- | ---------------------------------------- | 33| barPosition | [BarPosition](#barposition枚举说明)| 否 | 设置Tabs的页签位置。<br/>默认值:BarPosition.Start | 34| index | number | 否 | 设置当前显示页签的索引。<br/>默认值:0<br/>**说明:** <br/>设置为小于0的值时按默认值显示。<br/>可选值为[0, TabContent子节点数量-1]。<br/>直接修改index跳页时,切换动效不生效。 使用TabController的changeIndex时,默认生效切换动效,可以设置animationDuration为0关闭动画。<br />从API version 10开始,该参数支持[$$](../../../quick-start/arkts-two-way-sync.md)双向绑定变量。 | 35| controller | [TabsController](#tabscontroller) | 否 | 设置Tabs控制器。 | 36 37## BarPosition枚举说明 38 39Tabs页签位置枚举。 40 41**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 42 43**系统能力:** SystemCapability.ArkUI.ArkUI.Full 44 45| 名称 | 说明 | 46| ----- | ------------------------------------------------------------ | 47| Start | vertical属性方法设置为true时,页签位于容器左侧;vertical属性方法设置为false时,页签位于容器顶部。 | 48| End | vertical属性方法设置为true时,页签位于容器右侧;vertical属性方法设置为false时,页签位于容器底部。 | 49 50 51## 属性 52 53除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性: 54 55### vertical 56 57vertical(value: boolean) 58 59设置是否为纵向Tab。 60 61**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 62 63**系统能力:** SystemCapability.ArkUI.ArkUI.Full 64 65**参数:** 66 67| 参数名 | 类型 | 必填 | 说明 | 68| ------ | ------- | ---- | ------------------------------------------------------------ | 69| 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/>尽量保持每一个页面中的子组件尺寸大小一致,避免滑动页面时出现页面切换动画跳动现象。 | 70 71### scrollable 72 73scrollable(value: boolean) 74 75设置是否可以通过滑动页面进行页面切换。 76 77**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 78 79**系统能力:** SystemCapability.ArkUI.ArkUI.Full 80 81**参数:** 82 83| 参数名 | 类型 | 必填 | 说明 | 84| ------ | ------- | ---- | ------------------------------------------------------------ | 85| value | boolean | 是 | 是否可以通过滑动页面进行页面切换。<br/>默认值:true,可以通过滑动页面进行页面切换。为false时不可滑动切换页面。 | 86 87### barMode 88 89barMode(value: BarMode, options?: ScrollableBarModeOptions) 90 91设置TabBar布局模式。 92 93**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 94 95**系统能力:** SystemCapability.ArkUI.ArkUI.Full 96 97**参数:** 98 99| 参数名 | 类型 | 必填 | 说明 | 100| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 101| value | [BarMode](#barmode枚举说明) | 是 | 布局模式。<br/>默认值:BarMode.Fixed | 102| options<sup>10+</sup> | [ScrollableBarModeOptions](#scrollablebarmodeoptions10对象说明) | 否 | Scrollable模式下的TabBar的布局样式。<br/>**说明:** <br/>仅Scrollable且水平模式下有效。 | 103 104### barMode<sup>10+</sup> 105 106barMode(value: BarMode.Fixed) 107 108设置TabBar布局模式为BarMode.Fixed。 109 110**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 111 112**系统能力:** SystemCapability.ArkUI.ArkUI.Full 113 114**参数:** 115 116| 参数名 | 类型 | 必填 | 说明 | 117| -------- | -------------------------------- | ---- | ------------------------------------ | 118| value | [BarMode.Fixed](#barmode枚举说明) | 是 | 所有TabBar会平均分配barWidth宽度(纵向时平均分配barHeight高度)。 | 119 120### barMode<sup>10+</sup> 121 122barMode(value: BarMode.Scrollable, options: ScrollableBarModeOptions) 123 124设置TabBar布局模式为BarMode.Scrollable。 125 126**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 127 128**系统能力:** SystemCapability.ArkUI.ArkUI.Full 129 130**参数:** 131 132| 参数名 | 类型 | 必填 | 说明 | 133| -------- | --------------------------------- | ---- | ------------------------------------- | 134| value | [BarMode.Scrollable](#barmode枚举说明) | 是 | 所有TabBar都使用实际布局宽度,超过总宽度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。 | 135| options | [ScrollableBarModeOptions](#scrollablebarmodeoptions10对象说明) | 是 | Scrollable模式下的TabBar的布局样式。<br/>**说明:** <br/>仅水平模式下有效。 | 136 137### barWidth 138 139barWidth(value: Length) 140 141设置TabBar的宽度值。设置为小于0或大于Tabs宽度值时,按默认值显示。 142 143**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 144 145**系统能力:** SystemCapability.ArkUI.ArkUI.Full 146 147**参数:** 148 149| 参数名 | 类型 | 必填 | 说明 | 150| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ | 151| 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的宽度。 | 152 153### barHeight 154 155barHeight(value: Length) 156 157设置TabBar的高度值。设置为'auto'时,TabBar自适应子组件高度,仅在水平模式下有效。设置为小于0或大于Tabs高度值时,按默认值显示。若设置barHeight为固定值后,TabBar无法扩展底部安全区。 158 159**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 160 161**系统能力:** SystemCapability.ArkUI.ArkUI.Full 162 163**参数:** 164 165| 参数名 | 类型 | 必填 | 说明 | 166| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ | 167| 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开始,默认值变更为52vp。 | 168 169### animationDuration 170 171animationDuration(value: number) 172 173设置点击TabBar页签和调用TabsController的changeIndex接口切换TabContent的动画时长。该参数不支持百分比设置。 174 175**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 176 177**系统能力:** SystemCapability.ArkUI.ArkUI.Full 178 179**参数:** 180 181| 参数名 | 类型 | 必填 | 说明 | 182| ------ | ------ | ---- | ------------------------------------------------------------ | 183| 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 | 184 185### animationMode<sup>12+</sup> 186 187animationMode(mode: Optional\<AnimationMode\>) 188 189设置点击TabBar页签时切换TabContent的动画形式。 190 191**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 192 193**系统能力:** SystemCapability.ArkUI.ArkUI.Full 194 195**参数:** 196 197| 参数名 | 类型 | 必填 | 说明 | 198| ------ | ------ | ---- | ------------------------------------------------------------ | 199| mode | Optional\<[AnimationMode](#animationmode12枚举说明)\> | 是 | 点击TabBar页签时切换TabContent的动画形式。<br/>默认值:<br/>默认值是AnimationMode.CONTENT_FIRST,表示在点击TabBar切换TabContent时,先加载目标页内容,再开始切换动画。| 200 201### barPosition<sup>9+</sup> 202 203barPosition(value: BarPosition) 204 205设置Tabs的页签位置。 206 207**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 208 209**系统能力:** SystemCapability.ArkUI.ArkUI.Full 210 211**参数:** 212 213| 参数名 | 类型 | 必填 | 说明 | 214| ----- | ---------------------------------- | ---- | -------------------- | 215| value | [BarPosition](#barposition枚举说明)| 是 | 设置Tabs的页签位置。<br/>默认值:BarPosition.Start | 216 217### divider<sup>10+</sup> 218 219divider(value: DividerStyle | null) 220 221设置区分TabBar和TabContent的分割线样式。 222 223**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 224 225**系统能力:** SystemCapability.ArkUI.ArkUI.Full 226 227**参数:** 228 229| 参数名 | 类型 | 必填 | 说明 | 230| ------ | --------------------------------------------------------- | ---- | ------------------------------------------------------------ | 231| value | [DividerStyle](#dividerstyle10对象说明) \| null | 是 | 分割线样式,默认不显示分割线。<br/>DividerStyle: 分割线的样式;<br/>null: 不显示分割线。 | 232 233### fadingEdge<sup>10+</sup> 234 235fadingEdge(value: boolean) 236 237设置页签超过容器宽度时是否渐隐消失。建议配合barBackgroundColor属性一起使用,如果barBackgroundColor属性没有定义,会默认显示页签末端为白色的渐隐效果。 238 239**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 240 241**系统能力:** SystemCapability.ArkUI.ArkUI.Full 242 243**参数:** 244 245| 参数名 | 类型 | 必填 | 说明 | 246| ------ | ------- | ---- | -------------------------------------------------- | 247| value | boolean | 是 | 页签超过容器宽度时是否渐隐消失。<br />默认值:true | 248 249### barOverlap<sup>10+</sup> 250 251barOverlap(value: boolean) 252 253设置TabBar是否背后变模糊并叠加在TabContent之上。若设置barOverlap为true,TabBar默认背景色修改为'#F2F1F3F5'并添加模糊效果。 254 255**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 256 257**系统能力:** SystemCapability.ArkUI.ArkUI.Full 258 259**参数:** 260 261| 参数名 | 类型 | 必填 | 说明 | 262| ------ | ------- | ---- | ------------------------------------------------------------ | 263| value | boolean | 是 | TabBar是否背后变模糊并叠加在TabContent之上。<br />默认值:false | 264 265### barBackgroundColor<sup>10+</sup> 266 267barBackgroundColor(value: ResourceColor) 268 269设置TabBar的背景颜色。 270 271**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 272 273**系统能力:** SystemCapability.ArkUI.ArkUI.Full 274 275**参数:** 276 277| 参数名 | 类型 | 必填 | 说明 | 278| ------ | ------------------------------------------ | ---- | ------------------------------------ | 279| value | [ResourceColor](ts-types.md#resourcecolor) | 是 | TabBar的背景颜色。<br />默认值:Color.Transparent,透明 | 280 281### barBackgroundBlurStyle<sup>11+</sup> 282 283barBackgroundBlurStyle(value: BlurStyle) 284 285设置TabBar的背景模糊材质。 286 287**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 288 289**系统能力:** SystemCapability.ArkUI.ArkUI.Full 290 291**参数:** 292 293| 参数名 | 类型 | 必填 | 说明 | 294| ------ | -------------------------------------------- | ---- | ---------------------------------------- | 295| value | [BlurStyle](ts-universal-attributes-background.md#blurstyle9) | 是 | TabBar的背景模糊材质。<br />默认值:BlurStyle.NONE | 296 297### barBackgroundBlurStyle<sup>14+</sup> 298 299barBackgroundBlurStyle(value: BlurStyle, options: BackgroundBlurStyleOptions) 300 301为TabBar提供一种在背景和内容之间的模糊能力,通过枚举值的方式封装了不同的模糊半径、蒙版颜色、蒙版透明度、饱和度、亮度。 302 303**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。 304 305**系统能力:** SystemCapability.ArkUI.ArkUI.Full 306 307**参数:** 308 309| 参数名 | 类型 | 必填 | 说明 | 310| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 311| value | [BlurStyle](ts-universal-attributes-background.md#blurstyle9) | 是 | 背景模糊样式。模糊样式中封装了模糊半径、蒙版颜色、蒙版透明度、饱和度、亮度五个参数。 | 312| options | [BackgroundBlurStyleOptions](ts-universal-attributes-background.md#backgroundblurstyleoptions10对象说明) | 是 | 背景模糊选项。 313 314### barGridAlign<sup>10+</sup> 315 316barGridAlign(value: BarGridColumnOptions) 317 318以栅格化方式设置TabBar的可见区域。具体参见BarGridColumnOptions对象。仅水平模式下有效,[不适用于XS、XL和XXL设备](../../../ui/arkts-layout-development-grid-layout.md#栅格系统断点)。 319 320**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 321 322**系统能力:** SystemCapability.ArkUI.ArkUI.Full 323 324**参数:** 325 326| 参数名 | 类型 | 必填 | 说明 | 327| ------ | ------------------------------------------------------- | ---- | ---------------------------------- | 328| value | [BarGridColumnOptions](#bargridcolumnoptions10对象说明) | 是 | 以栅格化方式设置TabBar的可见区域。 | 329 330### edgeEffect<sup>12+</sup> 331 332edgeEffect(edgeEffect: Optional<EdgeEffect>) 333 334设置边缘回弹效果。 335 336**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 337 338**系统能力:** SystemCapability.ArkUI.ArkUI.Full 339 340**参数:** 341 342| 参数名 | 类型 | 必填 | 说明 | 343| ------ | --------------------------------------------- | ---- | -------------------------------------------- | 344| edgeEffect | Optional<[EdgeEffect](ts-appendix-enums.md#edgeeffect)> | 是 | 边缘滑动效果。<br/>默认值:EdgeEffect.Spring | 345 346### barBackgroundEffect<sup>14+</sup> 347 348barBackgroundEffect(options: BackgroundEffectOptions) 349 350设置TabBar背景属性,包含背景模糊半径,亮度,饱和度,颜色等参数。 351 352**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。 353 354**系统能力:** SystemCapability.ArkUI.ArkUI.Full 355 356**参数:** 357 358| 参数名 | 类型 | 必填 | 说明 | 359| ------- | ------------------------------------------------------------ | ---- | ------------------------------------------ | 360| options | [BackgroundEffectOptions](ts-universal-attributes-background.md#backgroundeffectoptions11) | 是 | 设置TabBar背景属性包括:模糊半径,亮度,饱和度,颜色等。 | 361 362## DividerStyle<sup>10+</sup>对象说明 363 364分割线样式对象。 365 366**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 367 368**系统能力:** SystemCapability.ArkUI.ArkUI.Full 369 370| 名称 | 类型 | 必填 | 说明 | 371| ----------- | ---------------------------------------- | ---- | ---------------------------------------- | 372| strokeWidth | [Length](ts-types.md#length) | 是 | 分割线的线宽(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp | 373| color | [ResourceColor](ts-types.md#resourcecolor) | 否 | 分割线的颜色。<br/>默认值:#33182431 | 374| startMargin | [Length](ts-types.md#length) | 否 | 分割线与侧边栏顶端的距离(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp | 375| endMargin | [Length](ts-types.md#length) | 否 | 分割线与侧边栏底端的距离(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp | 376 377## BarGridColumnOptions<sup>10+</sup>对象说明 378 379TabBar栅格化方式设置的对象,包括栅格模式下的column边距和间隔,以及小、中、大屏下,页签占用的columns数量。 380 381**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 382 383**系统能力:** SystemCapability.ArkUI.ArkUI.Full 384 385| 名称 | 类型 | 必填 | 说明 | 386| ----------- | ---------------------------------------- | ---- | ---------------------------------------- | 387| margin | [Dimension](ts-types.md#dimension10) | 否 | 栅格模式下的column边距(不支持百分比设置)。<br/>默认值:24.0<br/>单位:vp | 388| gutter | [Dimension](ts-types.md#dimension10) | 否 | 栅格模式下的column间隔(不支持百分比设置)。<br/>默认值:24.0<br/>单位:vp | 389| sm | number | 否 | 小屏下,页签占用的columns数量,必须是非负偶数。小屏为大于等于320vp但小于600vp。<br/>默认值为-1,代表页签占用TabBar全部宽度。 | 390| md | number | 否 | 中屏下,页签占用的columns数量,必须是非负偶数。中屏为大于等于600vp但小于800vp。<br/>默认值为-1,代表页签占用TabBar全部宽度。 | 391| lg | number | 否 | 大屏下,页签占用的columns数量,必须是非负偶数。大屏为大于等于840vp但小于1024vp。<br/>默认值为-1,代表页签占用TabBar全部宽度。 | 392 393## ScrollableBarModeOptions<sup>10+</sup>对象说明 394 395Scrollable模式下的TabBar的布局样式对象。 396 397**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 398 399**系统能力:** SystemCapability.ArkUI.ArkUI.Full 400 401| 名称 | 类型 | 必填 | 说明 | 402| ----------- | ---------------------------------------- | ---- | ---------------------------------------- | 403| margin | [Dimension](ts-types.md#dimension10) | 否 | Scrollable模式下的TabBar的左右边距(不支持百分比设置)。<br/>默认值:0.0<br/>单位:vp | 404| nonScrollableLayoutStyle | [LayoutStyle](#layoutstyle10枚举说明) | 否 | Scrollable模式下不滚动时的页签排布方式。<br/>默认值:LayoutStyle.ALWAYS_CENTER | 405 406## BarMode枚举说明 407 408TabBar布局模式枚举。 409 410**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 411 412**系统能力:** SystemCapability.ArkUI.ArkUI.Full 413 414| 名称 | 值 | 说明 | 415| ---------- | -- | ---------------------------------------- | 416| Scrollable | 0 | 每一个TabBar均使用实际布局宽度,超过总长度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。 | 417| Fixed | 1 | 所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度)。 | 418 419## AnimationMode<sup>12+</sup>枚举说明 420 421点击TabBar页签时切换TabContent的动画形式枚举。 422 423**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 424 425**系统能力:** SystemCapability.ArkUI.ArkUI.Full 426 427| 名称 | 值 | 说明 | 428| ------------- | ---- | ------------------------------------------------------------ | 429| CONTENT_FIRST | 0 | 先加载目标页内容,再开始切换动画 | 430| ACTION_FIRST | 1 | 先开始切换动画,再加载目标页内容;生效需要同时需要满足:Tabs的height、width没有设置成auto | 431| NO_ANIMATION | 2 | 关闭默认动画 | 432 433## LayoutStyle<sup>10+</sup>枚举说明 434 435Scrollable模式下不滚动时的页签排布方式枚举。 436 437**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 438 439**系统能力:** SystemCapability.ArkUI.ArkUI.Full 440 441| 名称 | 值 | 说明 | 442| ---------- | -- | ---------------------------------------- | 443| ALWAYS_CENTER | 0 | 当页签内容超过TabBar宽度时,TabBar可滚动。<br/>当页签内容不超过TabBar宽度时,TabBar不可滚动,页签紧凑居中。| 444| ALWAYS_AVERAGE_SPLIT | 1 | 当页签内容超过TabBar宽度时,TabBar可滚动。<br/>当页签内容不超过TabBar宽度时,TabBar不可滚动,且所有页签平均分配TabBar宽度。| 445| SPACE_BETWEEN_OR_CENTER | 2 | 当页签内容超过TabBar宽度时,TabBar可滚动。<br/>当页签内容不超过TabBar宽度但超过TabBar宽度一半时,TabBar不可滚动,页签紧凑居中。<br/>当页签内容不超过TabBar宽度一半时,TabBar不可滚动,保证页签居中排列在TabBar宽度一半,且间距相同。| 446 447## 事件 448 449除支持[通用事件](ts-universal-events-click.md)外,还支持以下事件: 450 451### onChange 452 453onChange(event: (index: number) => void) 454 455Tab页签切换后触发的事件。 456 457触发该事件的条件: 458 4591、TabContent支持滑动时,组件触发滑动时触发。 460 4612、通过[控制器](#tabscontroller)API接口调用。 462 4633、通过[状态变量](../../../quick-start/arkts-state.md)构造的属性值进行修改。 464 4654、通过页签处点击触发。 466 467**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 468 469**系统能力:** SystemCapability.ArkUI.ArkUI.Full 470 471**参数:** 472 473| 参数名 | 类型 | 必填 | 说明 | 474| ------ | ------ | ---- | -------------------------------------- | 475| index | number | 是 | 当前显示的index索引,索引从0开始计算。 | 476 477### onTabBarClick<sup>10+</sup> 478 479onTabBarClick(event: (index: number) => void) 480 481Tab页签点击后触发的事件。 482 483**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 484 485**系统能力:** SystemCapability.ArkUI.ArkUI.Full 486 487**参数:** 488 489| 参数名 | 类型 | 必填 | 说明 | 490| ------ | ------ | ---- | ------------------------------------ | 491| index | number | 是 | 被点击的index索引,索引从0开始计算。 | 492 493### onAnimationStart<sup>11+</sup> 494 495onAnimationStart(handler: (index: number, targetIndex: number, event: TabsAnimationEvent) => void) 496 497切换动画开始时触发该回调。参数为动画开始前的index值(不是最终结束动画的index值)。当animationDuration为0时动画关闭,不触发该回调。 498 499**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 500 501**系统能力:** SystemCapability.ArkUI.ArkUI.Full 502 503**参数:** 504 505| 参数名 | 类型 | 必填 | 说明 | 506| ----------- | ------------------------------------------------------ | ---- | ------------------------------------------------------------ | 507| index | number | 是 | 当前显示元素的索引。 | 508| targetIndex | number | 是 | 切换动画目标元素的索引。 | 509| event | [TabsAnimationEvent](#tabsanimationevent11对象说明) | 是 | 动画相关信息,包括主轴方向上当前显示元素和目标元素相对Tabs起始位置的位移,以及离手速度。 | 510 511### onAnimationEnd<sup>11+</sup> 512 513onAnimationEnd(handler: (index: number, event: TabsAnimationEvent) => void) 514 515切换动画结束时触发该回调。当Tabs切换动效结束时触发,包括动画过程中手势中断。参数为动画结束后的index值。当animationDuration为0时动画关闭,不触发该回调。 516 517**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 518 519**系统能力:** SystemCapability.ArkUI.ArkUI.Full 520 521**参数:** 522 523| 参数名 | 类型 | 必填 | 说明 | 524| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ | 525| index | number | 是 | 当前显示元素的索引。 | 526| event | [TabsAnimationEvent](#tabsanimationevent11对象说明) | 是 | 动画相关信息,只返回主轴方向上当前显示元素相对于Tabs起始位置的位移。 | 527 528### onGestureSwipe<sup>11+</sup> 529 530onGestureSwipe(handler: (index: number, event: TabsAnimationEvent) => void) 531 532在页面跟手滑动过程中,逐帧触发该回调。 533 534**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 535 536**系统能力:** SystemCapability.ArkUI.ArkUI.Full 537 538**参数:** 539 540| 参数名 | 类型 | 必填 | 说明 | 541| ------ | ------------------------------------------------------ | ---- | ------------------------------------------------------------ | 542| index | number | 是 | 当前显示元素的索引。 | 543| event | [TabsAnimationEvent](#tabsanimationevent11对象说明) | 是 | 动画相关信息,只返回主轴方向上当前显示元素相对于Tabs起始位置的位移。 | 544 545### customContentTransition<sup>11+</sup> 546 547customContentTransition(delegate: (from: number, to: number) => TabContentAnimatedTransition \| undefined) 548 549自定义Tabs页面切换动画。 550 551使用说明: 552 5531、当使用自定义切换动画时,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属性,来控制页面的渲染层级。 554 555**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。 556 557**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 558 559**系统能力:** SystemCapability.ArkUI.ArkUI.Full 560 561**参数:** 562 563| 参数名 | 类型 | 必填 | 说明 | 564| ------ | ------ | ---- | ------------------------------- | 565| from | number | 是 | 动画开始时,当前页面的index值。 | 566| to | number | 是 | 动画开始时,目标页面的index值。 | 567 568**返回值:** 569 570| 类型 | 说明 | 571| ------------------------------------------------------------ | ------------------------ | 572| [TabContentAnimatedTransition](#tabcontentanimatedtransition11对象说明) \| undefined | 自定义切换动画相关信息。 | 573 574### onContentWillChange<sup>12+</sup> 575 576onContentWillChange(handler: (currentIndex: number, comingIndex: number) => boolean) 577 578自定义Tabs页面切换拦截事件能力,新页面即将显示时触发该回调。 579 580触发该回调的条件: 581 5821、TabContent支持滑动时,滑动组件切换新页面时触发。 583 5842、通过TabsController.changeIndex接口切换新页面时触发。 585 5863、通过动态修改index属性值切换新页面时触发。 587 5884、通过点击TabBar页签切换新页面时触发。 589 5905、TabBar页签获焦后,通过键盘左右方向键等切换新页面时触发。 591 592**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 593 594**系统能力:** SystemCapability.ArkUI.ArkUI.Full 595 596**参数:** 597 598| 参数名 | 类型 | 必填 | 说明 | 599| ------------ | ------ | ---- | ------------------------------------------ | 600| currentIndex | number | 是 | 当前显示页面的index索引,索引从0开始计算。 | 601| comingIndex | number | 是 | 将要显示的新页面的index索引。 | 602 603**返回值:** 604 605| 类型 | 说明 | 606| ------- | ------------------------------------------------------------ | 607| boolean | 当回调函数handler的返回值为true时,Tabs可以切换到新页面。<br/>当回调函数handler的返回值为false时,Tabs无法切换到新页面,仍然显示原来页面内容。 | 608 609## TabsAnimationEvent<sup>11+</sup>对象说明 610 611Tabs组件动画相关信息集合。 612 613**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 614 615**系统能力:** SystemCapability.ArkUI.ArkUI.Full 616 617| 名称 | 类型 | 只读 | 可选 | 说明 | 618| ------------- | ---------- | ---- | ---- | ------------------------ | 619| currentOffset | number | 否 | 否 | Tabs当前显示元素在主轴方向上,相对于Tabs起始位置的位移。单位VP,默认值为0。| 620| targetOffset | number | 否 | 否 | Tabs动画目标元素在主轴方向上,相对于Tabs起始位置的位移。单位VP,默认值为0。| 621| velocity | number | 否 | 否 | Tabs离手动画开始时的离手速度。单位VP/S,默认值为0。| 622 623## TabContentAnimatedTransition<sup>11+</sup>对象说明 624 625Tabs自定义切换动画相关信息。 626 627**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。 628 629**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 630 631**系统能力:** SystemCapability.ArkUI.ArkUI.Full 632 633| 名称 | 类型 | 必填 | 说明 | 634| ------------- | ---------------------- | ---- |---------------------- | 635| timeout | number | 否 | Tabs自定义切换动画超时时间。从自定义动画开始切换计时,如果到达该时间后,开发者仍未调用[TabContentTransitionProxy](#tabcontenttransitionproxy11对象说明)的finishTransition接口通知Tabs组件自定义动画结束,那么组件就会认为此次自定义动画已结束,直接执行后续操作。单位ms,默认值为1000.| 636| transition | (proxy: [TabContentTransitionProxy](#tabcontenttransitionproxy11对象说明)) => void | 是 | 自定义切换动画具体内容。| 637 638## TabContentTransitionProxy<sup>11+</sup>对象说明 639 640Tabs自定义切换动画执行过程中,返回给开发者的proxy对象。开发者可通过该对象获取自定义动画的起始和目标页面信息,同时,也可以通过调用该对象的finishTransition接口通知Tabs组件自定义动画已结束。 641 642**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。 643 644**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 645 646**系统能力:** SystemCapability.ArkUI.ArkUI.Full 647 648### 属性 649 650| 名称 | 类型 | 只读 | 可选 | 说明 | 651| ----- | ------- | ---- | ---- | --------------------------- | 652| from | number | 否 | 否 | 自定义动画起始页面对应的index值。| 653| to | number | 否 | 否 | 自定义动画目标页面对应的index值。| 654 655### finishTransition 656 657finishTransition(): void 658 659通知Tabs组件,此页面的自定义动画已结束。 660 661**卡片能力:** 从API version 11开始,该接口支持在ArkTS卡片中使用。 662 663**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 664 665**系统能力:** SystemCapability.ArkUI.ArkUI.Full 666 667## TabsController 668 669Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。 670 671**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 672 673**系统能力:** SystemCapability.ArkUI.ArkUI.Full 674 675### 导入对象 676 677```ts 678let controller: TabsController = new TabsController() 679``` 680 681### constructor 682 683constructor() 684 685TabsController的构造函数。 686 687**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 688 689**系统能力:** SystemCapability.ArkUI.ArkUI.Full 690 691### changeIndex 692 693changeIndex(value: number): void 694 695控制Tabs切换到指定页签。 696 697**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 698 699**系统能力:** SystemCapability.ArkUI.ArkUI.Full 700 701**参数:** 702 703| 参数名 | 类型 | 必填 | 说明 | 704| ----- | ------ | ---- | ---------------------------------------- | 705| value | number | 是 | 页签在Tabs里的索引值,索引值从0开始。<br/>**说明:** <br/>设置小于0或大于最大数量的值时,取默认值0。 | 706 707### preloadItems<sup>12+</sup> 708 709preloadItems(indices: Optional\<Array\<number>>): Promise\<void> 710 711控制Tabs预加载指定子节点。调用该接口后会一次性加载所有指定的子节点,因此为了性能考虑,建议分批加载子节点。 712 713**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 714 715**系统能力:** SystemCapability.ArkUI.ArkUI.Full 716 717**参数:** 718 719| 参数名 | 类型 | 必填 | 说明 | 720| ----- | ------ | ---- | ---------------------------------------- | 721| indices | Optional\<Array\<number>> | 是 | 需预加载的子节点的下标数组。<br/>默认值:空数组。 | 722 723**返回值:** 724 725| 类型 | 说明 | 726| ------------------------------------------------------------ | ------------------------ | 727| Promise\<void> | 预加载完成后触发的回调。 | 728 729**错误码:** 730 731以下错误码的详细介绍请参见[通用错误码](../../errorcode-universal.md)错误码。 732 733| 错误码ID | 错误信息 | 734| -------- | -------------------------------------------- | 735| 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. | 736 737### setTabBarTranslate<sup>14+</sup> 738 739setTabBarTranslate(translate: TranslateOptions): void 740 741设置TabBar的平移距离。 742 743> **说明:** 744> 745> 当使用bindTabsToScrollable或bindTabsToNestedScrollable等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效,调用setTabBarTranslate接口设置的TabBar平移距离会失效。因此不建议同时使用bindTabsToScrollable、bindTabsToNestedScrollable和setTabBarTranslate接口。 746> 747 748**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。 749 750**系统能力:** SystemCapability.ArkUI.ArkUI.Full 751 752**参数:** 753 754| 参数名 | 类型 | 必填 | 说明 | 755| ----- | ------ | ---- | ---------------------------------------- | 756| translate | [TranslateOptions](ts-universal-attributes-transformation.md#translateoptions对象说明) | 是 | 设置TabBar的平移距离。 | 757 758### setTabBarOpacity<sup>14+</sup> 759 760setTabBarOpacity(opacity: number): void 761 762设置TabBar的不透明度。 763 764> **说明:** 765> 766> 当使用bindTabsToScrollable或bindTabsToNestedScrollable等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效,调用setTabBarOpacity接口设置的TabBar不透明度会失效。因此不建议同时使用bindTabsToScrollable、bindTabsToNestedScrollable和setTabBarOpacity接口。 767> 768 769**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。 770 771**系统能力:** SystemCapability.ArkUI.ArkUI.Full 772 773**参数:** 774 775| 参数名 | 类型 | 必填 | 说明 | 776| ----- | ------ | ---- | ---------------------------------------- | 777| opacity | number | 是 | 设置TabBar的不透明度,取值范围为[0.0, 1.0]。 | 778 779## 示例 780 781### 示例1 782 783本示例通过onChange实现切换时自定义tabBar和TabContent的联动。 784 785```ts 786// xxx.ets 787@Entry 788@Component 789struct TabsExample { 790 @State fontColor: string = '#182431' 791 @State selectedFontColor: string = '#007DFF' 792 @State currentIndex: number = 0 793 @State selectedIndex: number = 0 794 private controller: TabsController = new TabsController() 795 796 @Builder tabBuilder(index: number, name: string) { 797 Column() { 798 Text(name) 799 .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor) 800 .fontSize(16) 801 .fontWeight(this.selectedIndex === index ? 500 : 400) 802 .lineHeight(22) 803 .margin({ top: 17, bottom: 7 }) 804 Divider() 805 .strokeWidth(2) 806 .color('#007DFF') 807 .opacity(this.selectedIndex === index ? 1 : 0) 808 }.width('100%') 809 } 810 811 build() { 812 Column() { 813 Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) { 814 TabContent() { 815 Column().width('100%').height('100%').backgroundColor('#00CB87') 816 }.tabBar(this.tabBuilder(0, 'green')) 817 818 TabContent() { 819 Column().width('100%').height('100%').backgroundColor('#007DFF') 820 }.tabBar(this.tabBuilder(1, 'blue')) 821 822 TabContent() { 823 Column().width('100%').height('100%').backgroundColor('#FFBF00') 824 }.tabBar(this.tabBuilder(2, 'yellow')) 825 826 TabContent() { 827 Column().width('100%').height('100%').backgroundColor('#E67C92') 828 }.tabBar(this.tabBuilder(3, 'pink')) 829 } 830 .vertical(false) 831 .barMode(BarMode.Fixed) 832 .barWidth(360) 833 .barHeight(56) 834 .animationDuration(400) 835 .onChange((index: number) => { 836 // currentIndex控制TabContent显示页签 837 this.currentIndex = index 838 }) 839 .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => { 840 if (index === targetIndex) { 841 return 842 } 843 // selectedIndex控制自定义TabBar内Image和Text颜色切换 844 this.selectedIndex = targetIndex 845 }) 846 .width(360) 847 .height(296) 848 .margin({ top: 52 }) 849 .backgroundColor('#F1F3F5') 850 }.width('100%') 851 } 852} 853``` 854 855 856 857### 示例2 858 859本示例通过divider实现了分割线各种属性的展示。 860 861```ts 862// xxx.ets 863@Entry 864@Component 865struct TabsDivider1 { 866 private controller1: TabsController = new TabsController() 867 @State dividerColor: string = 'red' 868 @State strokeWidth: number = 2 869 @State startMargin: number = 0 870 @State endMargin: number = 0 871 @State nullFlag: boolean = false 872 873 build() { 874 Column() { 875 Tabs({ controller: this.controller1 }) { 876 TabContent() { 877 Column().width('100%').height('100%').backgroundColor(Color.Pink) 878 }.tabBar('pink') 879 880 TabContent() { 881 Column().width('100%').height('100%').backgroundColor(Color.Yellow) 882 }.tabBar('yellow') 883 884 TabContent() { 885 Column().width('100%').height('100%').backgroundColor(Color.Blue) 886 }.tabBar('blue') 887 888 TabContent() { 889 Column().width('100%').height('100%').backgroundColor(Color.Green) 890 }.tabBar('green') 891 892 TabContent() { 893 Column().width('100%').height('100%').backgroundColor(Color.Red) 894 }.tabBar('red') 895 } 896 .vertical(true) 897 .scrollable(true) 898 .barMode(BarMode.Fixed) 899 .barWidth(70) 900 .barHeight(200) 901 .animationDuration(400) 902 .onChange((index: number) => { 903 console.info(index.toString()) 904 }) 905 .height('200vp') 906 .margin({ bottom: '12vp' }) 907 .divider(this.nullFlag ? null : { 908 strokeWidth: this.strokeWidth, 909 color: this.dividerColor, 910 startMargin: this.startMargin, 911 endMargin: this.endMargin 912 }) 913 914 Button('常规Divider').width('100%').margin({ bottom: '12vp' }) 915 .onClick(() => { 916 this.nullFlag = false; 917 this.strokeWidth = 2; 918 this.dividerColor = 'red'; 919 this.startMargin = 0; 920 this.endMargin = 0; 921 }) 922 Button('空Divider').width('100%').margin({ bottom: '12vp' }) 923 .onClick(() => { 924 this.nullFlag = true 925 }) 926 Button('颜色变为蓝色').width('100%').margin({ bottom: '12vp' }) 927 .onClick(() => { 928 this.dividerColor = 'blue' 929 }) 930 Button('宽度增加').width('100%').margin({ bottom: '12vp' }) 931 .onClick(() => { 932 this.strokeWidth += 2 933 }) 934 Button('宽度减小').width('100%').margin({ bottom: '12vp' }) 935 .onClick(() => { 936 if (this.strokeWidth > 2) { 937 this.strokeWidth -= 2 938 } 939 }) 940 Button('上边距增加').width('100%').margin({ bottom: '12vp' }) 941 .onClick(() => { 942 this.startMargin += 2 943 }) 944 Button('上边距减少').width('100%').margin({ bottom: '12vp' }) 945 .onClick(() => { 946 if (this.startMargin > 2) { 947 this.startMargin -= 2 948 } 949 }) 950 Button('下边距增加').width('100%').margin({ bottom: '12vp' }) 951 .onClick(() => { 952 this.endMargin += 2 953 }) 954 Button('下边距减少').width('100%').margin({ bottom: '12vp' }) 955 .onClick(() => { 956 if (this.endMargin > 2) { 957 this.endMargin -= 2 958 } 959 }) 960 }.padding({ top: '24vp', left: '24vp', right: '24vp' }) 961 } 962} 963``` 964 965 966 967### 示例3 968 969本示例通过fadingEdge实现了切换子页签渐隐和不渐隐。 970 971```ts 972// xxx.ets 973@Entry 974@Component 975struct TabsOpaque { 976 @State message: string = 'Hello World' 977 private controller: TabsController = new TabsController() 978 private controller1: TabsController = new TabsController() 979 @State selfFadingFade: boolean = true; 980 981 build() { 982 Column() { 983 Button('子页签设置渐隐').width('100%').margin({ bottom: '12vp' }) 984 .onClick((event?: ClickEvent) => { 985 this.selfFadingFade = true; 986 }) 987 Button('子页签设置不渐隐').width('100%').margin({ bottom: '12vp' }) 988 .onClick((event?: ClickEvent) => { 989 this.selfFadingFade = false; 990 }) 991 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 992 TabContent() { 993 Column().width('100%').height('100%').backgroundColor(Color.Pink) 994 }.tabBar('pink') 995 996 TabContent() { 997 Column().width('100%').height('100%').backgroundColor(Color.Yellow) 998 }.tabBar('yellow') 999 1000 TabContent() { 1001 Column().width('100%').height('100%').backgroundColor(Color.Blue) 1002 }.tabBar('blue') 1003 1004 TabContent() { 1005 Column().width('100%').height('100%').backgroundColor(Color.Green) 1006 }.tabBar('green') 1007 1008 TabContent() { 1009 Column().width('100%').height('100%').backgroundColor(Color.Green) 1010 }.tabBar('green') 1011 1012 TabContent() { 1013 Column().width('100%').height('100%').backgroundColor(Color.Green) 1014 }.tabBar('green') 1015 1016 TabContent() { 1017 Column().width('100%').height('100%').backgroundColor(Color.Green) 1018 }.tabBar('green') 1019 1020 TabContent() { 1021 Column().width('100%').height('100%').backgroundColor(Color.Green) 1022 }.tabBar('green') 1023 } 1024 .vertical(false) 1025 .scrollable(true) 1026 .barMode(BarMode.Scrollable) 1027 .barHeight(80) 1028 .animationDuration(400) 1029 .onChange((index: number) => { 1030 console.info(index.toString()) 1031 }) 1032 .fadingEdge(this.selfFadingFade) 1033 .height('30%') 1034 .width('100%') 1035 1036 Tabs({ barPosition: BarPosition.Start, controller: this.controller1 }) { 1037 TabContent() { 1038 Column().width('100%').height('100%').backgroundColor(Color.Pink) 1039 }.tabBar('pink') 1040 1041 TabContent() { 1042 Column().width('100%').height('100%').backgroundColor(Color.Yellow) 1043 }.tabBar('yellow') 1044 1045 TabContent() { 1046 Column().width('100%').height('100%').backgroundColor(Color.Blue) 1047 }.tabBar('blue') 1048 1049 TabContent() { 1050 Column().width('100%').height('100%').backgroundColor(Color.Green) 1051 }.tabBar('green') 1052 1053 TabContent() { 1054 Column().width('100%').height('100%').backgroundColor(Color.Green) 1055 }.tabBar('green') 1056 1057 TabContent() { 1058 Column().width('100%').height('100%').backgroundColor(Color.Green) 1059 }.tabBar('green') 1060 } 1061 .vertical(true) 1062 .scrollable(true) 1063 .barMode(BarMode.Scrollable) 1064 .barHeight(200) 1065 .barWidth(80) 1066 .animationDuration(400) 1067 .onChange((index: number) => { 1068 console.info(index.toString()) 1069 }) 1070 .fadingEdge(this.selfFadingFade) 1071 .height('30%') 1072 .width('100%') 1073 } 1074 .padding({ top: '24vp', left: '24vp', right: '24vp' }) 1075 } 1076} 1077``` 1078 1079 1080 1081### 示例4 1082 1083本示例通过barOverlap实现了TabBar是否背后变模糊并叠加在TabContent之上。 1084 1085```ts 1086// xxx.ets 1087@Entry 1088@Component 1089struct barBackgroundColorTest { 1090 private controller: TabsController = new TabsController() 1091 @State barOverlap: boolean = true; 1092 @State barBackgroundColor: string = '#88888888'; 1093 1094 build() { 1095 Column() { 1096 Button("barOverlap变化").width('100%').margin({ bottom: '12vp' }) 1097 .onClick((event?: ClickEvent) => { 1098 if (this.barOverlap) { 1099 this.barOverlap = false; 1100 } else { 1101 this.barOverlap = true; 1102 } 1103 }) 1104 1105 Tabs({ barPosition: BarPosition.Start, index: 0, controller: this.controller }) { 1106 TabContent() { 1107 Column() { 1108 Text(`barOverlap ${this.barOverlap}`).fontSize(16).margin({ top: this.barOverlap ? '56vp' : 0 }) 1109 Text(`barBackgroundColor ${this.barBackgroundColor}`).fontSize(16) 1110 }.width('100%').width('100%').height('100%') 1111 .backgroundColor(Color.Pink) 1112 } 1113 .tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), "1")) 1114 1115 TabContent() { 1116 Column() { 1117 Text(`barOverlap ${this.barOverlap}`).fontSize(16).margin({ top: this.barOverlap ? '56vp' : 0 }) 1118 Text(`barBackgroundColor ${this.barBackgroundColor}`).fontSize(16) 1119 }.width('100%').width('100%').height('100%') 1120 .backgroundColor(Color.Yellow) 1121 } 1122 .tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), "2")) 1123 1124 TabContent() { 1125 Column() { 1126 Text(`barOverlap ${this.barOverlap}`).fontSize(16).margin({ top: this.barOverlap ? '56vp' : 0 }) 1127 Text(`barBackgroundColor ${this.barBackgroundColor}`).fontSize(16) 1128 }.width('100%').width('100%').height('100%') 1129 .backgroundColor(Color.Green) 1130 } 1131 .tabBar(new BottomTabBarStyle($r('sys.media.ohos_app_icon'), "3")) 1132 } 1133 .vertical(false) 1134 .barMode(BarMode.Fixed) 1135 .height('60%') 1136 .barOverlap(this.barOverlap) 1137 .scrollable(true) 1138 .animationDuration(10) 1139 .barBackgroundColor(this.barBackgroundColor) 1140 } 1141 .height(500) 1142 .padding({ top: '24vp', left: '24vp', right: '24vp' }) 1143 } 1144} 1145``` 1146 1147 1148 1149### 示例5 1150 1151本示例通过barGridAlign实现了以栅格化方式设置TabBar的可见区域。 1152 1153```ts 1154// xxx.ets 1155@Entry 1156@Component 1157struct TabsExample5 { 1158 private controller: TabsController = new TabsController() 1159 @State gridMargin: number = 10 1160 @State gridGutter: number = 10 1161 @State sm: number = -2 1162 @State clickedContent: string = ""; 1163 1164 build() { 1165 Column() { 1166 Row() { 1167 Button("gridMargin+10 " + this.gridMargin) 1168 .width('47%') 1169 .height(50) 1170 .margin({ top: 5 }) 1171 .onClick((event?: ClickEvent) => { 1172 this.gridMargin += 10 1173 }) 1174 .margin({ right: '6%', bottom: '12vp' }) 1175 Button("gridMargin-10 " + this.gridMargin) 1176 .width('47%') 1177 .height(50) 1178 .margin({ top: 5 }) 1179 .onClick((event?: ClickEvent) => { 1180 this.gridMargin -= 10 1181 }) 1182 .margin({ bottom: '12vp' }) 1183 } 1184 1185 Row() { 1186 Button("gridGutter+10 " + this.gridGutter) 1187 .width('47%') 1188 .height(50) 1189 .margin({ top: 5 }) 1190 .onClick((event?: ClickEvent) => { 1191 this.gridGutter += 10 1192 }) 1193 .margin({ right: '6%', bottom: '12vp' }) 1194 Button("gridGutter-10 " + this.gridGutter) 1195 .width('47%') 1196 .height(50) 1197 .margin({ top: 5 }) 1198 .onClick((event?: ClickEvent) => { 1199 this.gridGutter -= 10 1200 }) 1201 .margin({ bottom: '12vp' }) 1202 } 1203 1204 Row() { 1205 Button("sm+2 " + this.sm) 1206 .width('47%') 1207 .height(50) 1208 .margin({ top: 5 }) 1209 .onClick((event?: ClickEvent) => { 1210 this.sm += 2 1211 }) 1212 .margin({ right: '6%' }) 1213 Button("sm-2 " + this.sm).width('47%').height(50).margin({ top: 5 }) 1214 .onClick((event?: ClickEvent) => { 1215 this.sm -= 2 1216 }) 1217 } 1218 1219 Text("点击内容:" + this.clickedContent).width('100%').height(200).margin({ top: 5 }) 1220 1221 1222 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 1223 TabContent() { 1224 Column().width('100%').height('100%').backgroundColor(Color.Pink) 1225 }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "1")) 1226 1227 TabContent() { 1228 Column().width('100%').height('100%').backgroundColor(Color.Green) 1229 }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "2")) 1230 1231 TabContent() { 1232 Column().width('100%').height('100%').backgroundColor(Color.Blue) 1233 }.tabBar(BottomTabBarStyle.of($r("sys.media.ohos_app_icon"), "3")) 1234 } 1235 .width('350vp') 1236 .animationDuration(300) 1237 .height('60%') 1238 .barGridAlign({ sm: this.sm, margin: this.gridMargin, gutter: this.gridGutter }) 1239 .backgroundColor(0xf1f3f5) 1240 .onTabBarClick((index: number) => { 1241 this.clickedContent += "now index " + index + " is clicked\n"; 1242 }) 1243 } 1244 .width('100%') 1245 .height(500) 1246 .margin({ top: 5 }) 1247 .padding('10vp') 1248 } 1249} 1250``` 1251 1252 1253 1254### 示例6 1255 1256本示例实现了barMode的ScrollableBarModeOptions参数,该参数仅在Scrollable模式下有效。 1257 1258```ts 1259// xxx.ets 1260@Entry 1261@Component 1262struct TabsExample6 { 1263 private controller: TabsController = new TabsController() 1264 @State scrollMargin: number = 0 1265 @State layoutStyle: LayoutStyle = LayoutStyle.ALWAYS_CENTER 1266 @State text: string = "文本" 1267 1268 build() { 1269 Column() { 1270 Row() { 1271 Button("scrollMargin+10 " + this.scrollMargin) 1272 .width('47%') 1273 .height(50) 1274 .margin({ top: 5 }) 1275 .onClick((event?: ClickEvent) => { 1276 this.scrollMargin += 10 1277 }) 1278 .margin({ right: '6%', bottom: '12vp' }) 1279 Button("scrollMargin-10 " + this.scrollMargin) 1280 .width('47%') 1281 .height(50) 1282 .margin({ top: 5 }) 1283 .onClick((event?: ClickEvent) => { 1284 this.scrollMargin -= 10 1285 }) 1286 .margin({ bottom: '12vp' }) 1287 } 1288 1289 Row() { 1290 Button("文本增加 ") 1291 .width('47%') 1292 .height(50) 1293 .margin({ top: 5 }) 1294 .onClick((event?: ClickEvent) => { 1295 this.text += '文本增加' 1296 }) 1297 .margin({ right: '6%', bottom: '12vp' }) 1298 Button("文本重置") 1299 .width('47%') 1300 .height(50) 1301 .margin({ top: 5 }) 1302 .onClick((event?: ClickEvent) => { 1303 this.text = "文本" 1304 }) 1305 .margin({ bottom: '12vp' }) 1306 } 1307 1308 Row() { 1309 Button("layoutStyle.ALWAYS_CENTER") 1310 .width('100%') 1311 .height(50) 1312 .margin({ top: 5 }) 1313 .fontSize(15) 1314 .onClick((event?: ClickEvent) => { 1315 this.layoutStyle = LayoutStyle.ALWAYS_CENTER; 1316 }) 1317 .margin({ bottom: '12vp' }) 1318 } 1319 1320 Row() { 1321 Button("layoutStyle.ALWAYS_AVERAGE_SPLIT") 1322 .width('100%') 1323 .height(50) 1324 .margin({ top: 5 }) 1325 .fontSize(15) 1326 .onClick((event?: ClickEvent) => { 1327 this.layoutStyle = LayoutStyle.ALWAYS_AVERAGE_SPLIT; 1328 }) 1329 .margin({ bottom: '12vp' }) 1330 } 1331 1332 Row() { 1333 Button("layoutStyle.SPACE_BETWEEN_OR_CENTER") 1334 .width('100%') 1335 .height(50) 1336 .margin({ top: 5 }) 1337 .fontSize(15) 1338 .onClick((event?: ClickEvent) => { 1339 this.layoutStyle = LayoutStyle.SPACE_BETWEEN_OR_CENTER; 1340 }) 1341 .margin({ bottom: '12vp' }) 1342 } 1343 1344 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 1345 TabContent() { 1346 Column().width('100%').height('100%').backgroundColor(Color.Pink) 1347 }.tabBar(SubTabBarStyle.of(this.text)) 1348 1349 TabContent() { 1350 Column().width('100%').height('100%').backgroundColor(Color.Green) 1351 }.tabBar(SubTabBarStyle.of(this.text)) 1352 1353 TabContent() { 1354 Column().width('100%').height('100%').backgroundColor(Color.Blue) 1355 }.tabBar(SubTabBarStyle.of(this.text)) 1356 } 1357 .animationDuration(300) 1358 .height('60%') 1359 .backgroundColor(0xf1f3f5) 1360 .barMode(BarMode.Scrollable, { margin: this.scrollMargin, nonScrollableLayoutStyle: this.layoutStyle }) 1361 } 1362 .width('100%') 1363 .height(500) 1364 .margin({ top: 5 }) 1365 .padding('24vp') 1366 } 1367} 1368``` 1369 1370 1371 1372### 示例7 1373 1374本示例通过customContentTransition实现了自定义Tabs页面的切换动画。 1375 1376```ts 1377// xxx.ets 1378interface itemType { 1379 text: string, 1380 backgroundColor: Color 1381} 1382 1383@Entry 1384@Component 1385struct TabsCustomAnimationExample { 1386 @State data: itemType[] = [ 1387 { 1388 text: 'Red', 1389 backgroundColor: Color.Red 1390 }, 1391 { 1392 text: 'Yellow', 1393 backgroundColor: Color.Yellow 1394 }, 1395 { 1396 text: 'Blue', 1397 backgroundColor: Color.Blue 1398 }] 1399 @State opacityList: number[] = [] 1400 @State scaleList: number[] = [] 1401 1402 private durationList: number[] = [] 1403 private timeoutList: number[] = [] 1404 private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => { 1405 let tabContentAnimatedTransition = { 1406 timeout: this.timeoutList[from], 1407 transition: (proxy: TabContentTransitionProxy) => { 1408 this.scaleList[from] = 1.0 1409 this.scaleList[to] = 0.5 1410 this.opacityList[from] = 1.0 1411 this.opacityList[to] = 0.5 1412 animateTo({ 1413 duration: this.durationList[from], 1414 onFinish: () => { 1415 proxy.finishTransition() 1416 } 1417 }, () => { 1418 this.scaleList[from] = 0.5 1419 this.scaleList[to] = 1.0 1420 this.opacityList[from] = 0.5 1421 this.opacityList[to] = 1.0 1422 }) 1423 } 1424 } as TabContentAnimatedTransition 1425 return tabContentAnimatedTransition 1426 } 1427 1428 aboutToAppear(): void { 1429 let duration = 1000 1430 let timeout = 1000 1431 for (let i = 1; i <= this.data.length; i++) { 1432 this.opacityList.push(1.0) 1433 this.scaleList.push(1.0) 1434 this.durationList.push(duration * i) 1435 this.timeoutList.push(timeout * i) 1436 } 1437 } 1438 1439 build() { 1440 Column() { 1441 Tabs() { 1442 ForEach(this.data, (item: itemType, index: number) => { 1443 TabContent() {} 1444 .tabBar(item.text) 1445 .backgroundColor(item.backgroundColor) 1446 // 自定义动画变化透明度、缩放页面等 1447 .opacity(this.opacityList[index]) 1448 .scale({ x: this.scaleList[index], y: this.scaleList[index] }) 1449 }) 1450 } 1451 .backgroundColor(0xf1f3f5) 1452 .width('100%') 1453 .height(500) 1454 .customContentTransition(this.customContentTransition) 1455 } 1456 } 1457} 1458``` 1459 1460 1461### 示例8 1462 1463本示例通过onContentWillChange实现了自定义页面手势滑动切换拦截。 1464 1465```ts 1466//xxx.ets 1467@Entry 1468@Component 1469struct TabsExample { 1470 @State currentIndex: number = 2 1471 private controller: TabsController = new TabsController() 1472 @Builder tabBuilder(title: string,targetIndex: number) { 1473 Column(){ 1474 Text(title).fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B') 1475 }.width('100%') 1476 .height(50) 1477 .justifyContent(FlexAlign.Center) 1478 } 1479 build() { 1480 Column() { 1481 Tabs({ barPosition: BarPosition.End, controller: this.controller, index: this.currentIndex }) { 1482 TabContent() { 1483 Column(){ 1484 Text('首页的内容') 1485 }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center) 1486 }.tabBar(this.tabBuilder('首页',0)) 1487 1488 TabContent() { 1489 Column(){ 1490 Text('发现的内容') 1491 }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center) 1492 }.tabBar(this.tabBuilder('发现',1)) 1493 1494 TabContent() { 1495 Column(){ 1496 Text('推荐的内容') 1497 }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center) 1498 }.tabBar(this.tabBuilder('推荐',2)) 1499 1500 TabContent() { 1501 Column(){ 1502 Text('我的内容') 1503 }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center) 1504 }.tabBar(this.tabBuilder('我的',3)) 1505 } 1506 .vertical(false) 1507 .barMode(BarMode.Fixed) 1508 .barWidth(360) 1509 .barHeight(60) 1510 .animationDuration(0) 1511 .onChange((index: number) => { 1512 this.currentIndex = index 1513 }) 1514 .width(360) 1515 .height(600) 1516 .backgroundColor('#F1F3F5') 1517 .scrollable(true) 1518 .onContentWillChange((currentIndex, comingIndex) => { 1519 if (comingIndex == 2) { 1520 return false 1521 } 1522 return true 1523 }) 1524 1525 Button('动态修改index').width('50%').margin({ top: 20 }) 1526 .onClick(()=>{ 1527 this.currentIndex = (this.currentIndex + 1) % 4 1528 }) 1529 1530 Button('changeIndex').width('50%').margin({ top: 20 }) 1531 .onClick(()=>{ 1532 this.currentIndex = (this.currentIndex + 1) % 4 1533 this.controller.changeIndex(this.currentIndex) 1534 }) 1535 }.width('100%') 1536 } 1537} 1538``` 1539 1540 1541### 示例9 1542 1543本示例通过onChange、onAnimationStart、onAnimationEnd、onGestureSwipe等接口实现了自定义TabBar的切换动画。 1544 1545```ts 1546// xxx.ets 1547@Entry 1548@Component 1549struct TabsExample { 1550 @State currentIndex: number = 0 1551 @State animationDuration: number = 300 1552 @State indicatorLeftMargin: number = 0 1553 @State indicatorWidth: number = 0 1554 private tabsWidth: number = 0 1555 private textInfos: [number, number][] = [] 1556 private isStartAnimateTo: boolean = false 1557 1558 @Builder 1559 tabBuilder(index: number, name: string) { 1560 Column() { 1561 Text(name) 1562 .fontSize(16) 1563 .fontColor(this.currentIndex === index ? '#007DFF' : '#182431') 1564 .fontWeight(this.currentIndex === index ? 500 : 400) 1565 .id(index.toString()) 1566 .onAreaChange((oldValue: Area, newValue: Area) => { 1567 this.textInfos[index] = [newValue.globalPosition.x as number, newValue.width as number] 1568 if (this.currentIndex === index && !this.isStartAnimateTo) { 1569 this.indicatorLeftMargin = this.textInfos[index][0] 1570 this.indicatorWidth = this.textInfos[index][1] 1571 } 1572 }) 1573 }.width('100%') 1574 } 1575 1576 build() { 1577 Stack({ alignContent: Alignment.TopStart }) { 1578 Tabs({ barPosition: BarPosition.Start }) { 1579 TabContent() { 1580 Column().width('100%').height('100%').backgroundColor('#00CB87') 1581 }.tabBar(this.tabBuilder(0, 'green')) 1582 1583 TabContent() { 1584 Column().width('100%').height('100%').backgroundColor('#007DFF') 1585 }.tabBar(this.tabBuilder(1, 'blue')) 1586 1587 TabContent() { 1588 Column().width('100%').height('100%').backgroundColor('#FFBF00') 1589 }.tabBar(this.tabBuilder(2, 'yellow')) 1590 1591 TabContent() { 1592 Column().width('100%').height('100%').backgroundColor('#E67C92') 1593 }.tabBar(this.tabBuilder(3, 'pink')) 1594 } 1595 .onAreaChange((oldValue: Area, newValue: Area)=> { 1596 this.tabsWidth = newValue.width as number 1597 }) 1598 .barWidth('100%') 1599 .barHeight(56) 1600 .width('100%') 1601 .height(296) 1602 .backgroundColor('#F1F3F5') 1603 .animationDuration(this.animationDuration) 1604 .onChange((index: number) => { 1605 this.currentIndex = index // 监听索引index的变化,实现页签内容的切换。 1606 }) 1607 .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => { 1608 // 切换动画开始时触发该回调。下划线跟着页面一起滑动,同时宽度渐变。 1609 this.currentIndex = targetIndex 1610 this.startAnimateTo(this.animationDuration, this.textInfos[targetIndex][0], this.textInfos[targetIndex][1]) 1611 }) 1612 .onAnimationEnd((index: number, event: TabsAnimationEvent) => { 1613 // 切换动画结束时触发该回调。下划线动画停止。 1614 let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event) 1615 this.startAnimateTo(0, currentIndicatorInfo.left, currentIndicatorInfo.width) 1616 }) 1617 .onGestureSwipe((index: number, event: TabsAnimationEvent) => { 1618 // 在页面跟手滑动过程中,逐帧触发该回调。 1619 let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event) 1620 this.currentIndex = currentIndicatorInfo.index 1621 this.indicatorLeftMargin = currentIndicatorInfo.left 1622 this.indicatorWidth = currentIndicatorInfo.width 1623 }) 1624 1625 Column() 1626 .height(2) 1627 .width(this.indicatorWidth) 1628 .margin({ left: this.indicatorLeftMargin, top:48}) 1629 .backgroundColor('#007DFF') 1630 }.width('100%') 1631 } 1632 1633 private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> { 1634 let nextIndex = index 1635 if (index > 0 && event.currentOffset > 0) { 1636 nextIndex-- 1637 } else if (index < 3 && event.currentOffset < 0) { 1638 nextIndex++ 1639 } 1640 let indexInfo = this.textInfos[index] 1641 let nextIndexInfo = this.textInfos[nextIndex] 1642 let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth) 1643 let currentIndex = swipeRatio > 0.5 ? nextIndex : index // 页面滑动超过一半,tabBar切换到下一页。 1644 let currentLeft = indexInfo[0] + (nextIndexInfo[0] - indexInfo[0]) * swipeRatio 1645 let currentWidth = indexInfo[1] + (nextIndexInfo[1] - indexInfo[1]) * swipeRatio 1646 return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth } 1647 } 1648 1649 private startAnimateTo(duration: number, leftMargin: number, width: number) { 1650 this.isStartAnimateTo = true 1651 animateTo({ 1652 duration: duration, // 动画时长 1653 curve: Curve.Linear, // 动画曲线 1654 iterations: 1, // 播放次数 1655 playMode: PlayMode.Normal, // 动画模式 1656 onFinish: () => { 1657 this.isStartAnimateTo = false 1658 console.info('play end') 1659 } 1660 }, () => { 1661 this.indicatorLeftMargin = leftMargin 1662 this.indicatorWidth = width 1663 }) 1664 } 1665} 1666``` 1667 1668 1669 1670### 示例10 1671 1672本示例通过preloadItems接口实现了预加载指定子节点。 1673 1674```ts 1675// xxx.ets 1676import { BusinessError } from '@kit.BasicServicesKit' 1677 1678@Entry 1679@Component 1680struct TabsPreloadItems { 1681 @State currentIndex: number = 1 1682 private tabsController: TabsController = new TabsController() 1683 1684 build() { 1685 Column() { 1686 Tabs({ index: this.currentIndex, controller: this.tabsController }) { 1687 TabContent() { 1688 MyComponent({ color: '#00CB87' }) 1689 }.tabBar(SubTabBarStyle.of('green')) 1690 1691 TabContent() { 1692 MyComponent({ color: '#007DFF' }) 1693 }.tabBar(SubTabBarStyle.of('blue')) 1694 1695 TabContent() { 1696 MyComponent({ color: '#FFBF00' }) 1697 }.tabBar(SubTabBarStyle.of('yellow')) 1698 1699 TabContent() { 1700 MyComponent({ color: '#E67C92' }) 1701 }.tabBar(SubTabBarStyle.of('pink')) 1702 } 1703 .width(360) 1704 .height(296) 1705 .backgroundColor('#F1F3F5') 1706 .onChange((index: number) => { 1707 this.currentIndex = index 1708 }) 1709 1710 Button('preload items: [0, 2, 3]') 1711 .margin(5) 1712 .onClick(() => { 1713 // 预加载第0、2、3个子节点,提高滑动或点击切换至这些节点时的性能 1714 this.tabsController.preloadItems([0, 2, 3]) 1715 .then(() => { 1716 console.info('preloadItems success.') 1717 }) 1718 .catch((error: BusinessError) => { 1719 console.error('preloadItems failed, error code: ' + error.code + ', error message: ' + error.message) 1720 }) 1721 }) 1722 } 1723 } 1724} 1725 1726@Component 1727struct MyComponent { 1728 private color: string = "" 1729 1730 aboutToAppear(): void { 1731 console.info('aboutToAppear backgroundColor:' + this.color) 1732 } 1733 1734 aboutToDisappear(): void { 1735 console.info('aboutToDisappear backgroundColor:' + this.color) 1736 } 1737 1738 build() { 1739 Column() 1740 .width('100%') 1741 .height('100%') 1742 .backgroundColor(this.color) 1743 } 1744} 1745``` 1746 1747### 示例11 1748 1749本示例通过setTabBarTranslate、setTabBarOpacity等接口设置了TabBar的平移距离和不透明度。 1750 1751```ts 1752// xxx.ets 1753@Entry 1754@Component 1755struct TabsExample { 1756 private controller: TabsController = new TabsController() 1757 1758 build() { 1759 Column() { 1760 Button('设置TabBar的平移距离').margin({ top: 20 }) 1761 .onClick(() => { 1762 this.controller.setTabBarTranslate({ x: -20, y: -20 }) 1763 }) 1764 1765 Button('设置TabBar的透明度').margin({ top: 20 }) 1766 .onClick(() => { 1767 this.controller.setTabBarOpacity(0.5) 1768 }) 1769 1770 Tabs({ barPosition: BarPosition.End, controller: this.controller }) { 1771 TabContent() { 1772 Column().width('100%').height('100%').backgroundColor('#00CB87') 1773 }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'green')) 1774 1775 TabContent() { 1776 Column().width('100%').height('100%').backgroundColor('#007DFF') 1777 }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'blue')) 1778 1779 TabContent() { 1780 Column().width('100%').height('100%').backgroundColor('#FFBF00') 1781 }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'yellow')) 1782 1783 TabContent() { 1784 Column().width('100%').height('100%').backgroundColor('#E67C92') 1785 }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'pink')) 1786 } 1787 .width(360) 1788 .height(296) 1789 .margin({ top: 20 }) 1790 .barBackgroundColor('#F1F3F5') 1791 } 1792 .width('100%') 1793 } 1794} 1795``` 1796 1797