当前位置: 首页 > news >正文

鸿蒙ArkUI---基础组件Tabs(Tabbar)

基础页面组件

Tabs

作用:

        快速创建Tabbar

个人理解:

        快速的创建Tabar。

效果图:

代码:interface TabItem {icon: Resource; //未选中activeIcon: Resource; //选中name: string; //文字
}@Entry
@Component
struct Index {// struct Index 数据tabList: TabItem[] = [{icon: $r('XXX'),activeIcon: $r('XXX'),name: 'XXX'},{icon: $r('XXX'),activeIcon: $r('XXX'),name: 'XX'},{icon: $r('XXX'),activeIcon: $r('XXX'),name: 'XX'},{icon: $r('XXX'),activeIcon: $r('XXX'),name: 'XX'}]@StorageProp('bottomHeight') bottomHeight: number = 0@StateactiveIndex: number = 0@BuilderTabbarBuilder(item: TabItem, index: number) {Column({ space: 5 }) {Image(this.activeIndex == index ? item.activeIcon :  item.icon).width(24).aspectRatio(1) // 设置宽高比,保证图片展示一致Text(item.name).fontSize(12).fontColor(this.activeIndex == index ? '#131313' : '#979797')}}build() {Column() {Tabs() {ForEach(this.tabList, (item: TabItem, index: number) => {TabContent() {// 根据不同的下标->渲染对应的组件if (index == 0) {XXX// 第一个按钮对应的内容(创建相应的Page)} else if (index == 1) {XXX// 第二个按钮对应的内容(创建相应的Page)} else if (index == 2) {XXX// 第三个按钮对应的内容(创建相应的Page)} else {XXX// 第四个按钮对应的内容(创建相应的Page)}}.tabBar(this.TabbarBuilder(item, index))})}.barPosition(BarPosition.End) // Tabbar位置在屏幕下方.scrollable(false) // 不开启滑屏效果.onTabBarClick((index) => {this.activeIndex = index})}.width('100%').height('100%').backgroundColor('#ffffff').padding({bottom: this.bottomHeight // 全屏模式下,不占用安全区位置})}
}

官方说明:

Tabs 

更新时间: 2025-06-25 13:58

通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。

说明

该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。

该组件从API version 11开始默认支持安全区避让特性(默认值为:expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])),开发者可以重写该属性覆盖默认行为,API version 11之前的版本需配合expandSafeArea属性实现安全区避让。

子组件

支持设备PhonePC/2in1TabletWearable

不支持自定义组件作为子组件,仅可包含子组件TabContent,以及渲染控制类型if/else和ForEach,并且if/else和ForEach下也仅支持TabContent,不支持自定义组件。

说明

Tabs子组件的visibility属性设置为None,或者visibility属性设置为Hidden时,对应子组件不显示,但依然会在视窗内占位。

Tabs子组件TabContent显示之后不会销毁,若需要页面懒加载和释放,可以参考示例13。

接口

支持设备PhonePC/2in1TabletWearable

Tabs(options?: TabsOptions)

创建Tabs容器。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
optionsTabsOptionsTabs组件参数。

TabsOptions

支持设备PhonePC/2in1TabletWearable

Tabs组件参数,设置Tabs的页签位置,当前显示页签的索引,Tabs控制器和TabBar的通用属性。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型必填说明
barPositionBarPosition

设置Tabs的页签位置。

默认值:BarPosition.Start。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

indexnumber

设置当前显示页签的索引。

默认值:0

说明:

设置为小于0的值时按默认值显示。

可选值为[0, TabContent子节点数量-1]。

直接修改index跳页时,切换动效不生效。 使用TabController的changeIndex时,默认生效切换动效,可以设置animationDuration为0关闭动画。

从API version 10开始,该参数支持$$双向绑定变量。

Tabs重建、系统资源切换(如系统字体切换、系统深浅色切换)或者组件属性变化时,会跳转到index对应的页面。若需要在上述情况下不跳转,建议使用双向绑定。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

controllerTabsController

设置Tabs控制器。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

barModifierCommonModifier

设置TabBar的通用属性。

说明:

动态置为undefined时会保持当前状态不变,不会重置各通用属性。

由一个CommonModifier切换为另一个CommonModifier时,重复属性会进行覆盖,非重复属性会同时生效,不会重置前一个CommonModifier的通用属性。

Tabs的barWidth、barHeight、barBackgroundColor、barBackgroundBlurStyle、barBackgroundEffect属性会覆盖CommonModifier的width、height、backgroundColor、backgroundBlurStyle、backgroundEffect属性。

align属性仅在BarMode.Scrollable模式下生效,且Tabs为横向时还需nonScrollableLayoutStyle未设置或设置为异常值时才能生效。

TabContent组件的tabBar属性为底部页签样式时不支持拖拽功能。

元服务API: 从API version 15开始,该接口支持在元服务中使用。

BarPosition枚举说明

支持设备PhonePC/2in1TabletWearable

Tabs页签位置枚举。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称说明
Startvertical属性方法设置为true时,页签位于容器左侧;vertical属性方法设置为false时,页签位于容器顶部。
Endvertical属性方法设置为true时,页签位于容器右侧;vertical属性方法设置为false时,页签位于容器底部。

属性

支持设备PhonePC/2in1TabletWearable

除支持通用属性外,还支持以下属性:

vertical

支持设备PhonePC/2in1TabletWearable

vertical(value: boolean)

设置是否为纵向Tab。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueboolean

是否为纵向Tab。

默认值:false,横向Tabs,为true时纵向Tabs。

当横向Tabs设置height为auto时,Tabs组件高度自适应子组件高度,即为tabBar高度+divider线宽+TabContent高度+上下padding值+上下border宽度。

当纵向Tabs设置width为auto时,Tabs组件宽度自适应子组件宽度,即为tabBar宽度+divider线宽+TabContent宽度+左右padding值+左右border宽度。

尽量保持每一个页面中的子组件尺寸大小一致,避免滑动页面时出现页面切换动画跳动现象。

scrollable

支持设备PhonePC/2in1TabletWearable

scrollable(value: boolean)

设置是否可以通过滑动页面进行页面切换。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueboolean

是否可以通过滑动页面进行页面切换。

默认值:true,可以通过滑动页面进行页面切换。为false时不可滑动切换页面。

barMode

支持设备PhonePC/2in1TabletWearable

barMode(value: BarMode, options?: ScrollableBarModeOptions)

设置TabBar布局模式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueBarMode

布局模式。

默认值:BarMode.Fixed

optionsScrollableBarModeOptions

Scrollable模式下的TabBar的布局样式。

说明:

仅Scrollable且水平模式下有效。

barMode

支持设备PhonePC/2in1TabletWearable

barMode(value: BarMode.Fixed)

设置TabBar布局模式为BarMode.Fixed。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueBarMode.Fixed所有TabBar会平均分配barWidth宽度(纵向时平均分配barHeight高度)。

barMode

支持设备PhonePC/2in1TabletWearable

barMode(value: BarMode.Scrollable, options: ScrollableBarModeOptions)

设置TabBar布局模式为BarMode.Scrollable。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueBarMode.Scrollable所有TabBar都使用实际布局宽度,超过总宽度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。
optionsScrollableBarModeOptions

Scrollable模式下的TabBar的布局样式。

说明:

仅水平模式下有效。

barWidth

支持设备PhonePC/2in1TabletWearable

barWidth(value: Length)

设置TabBar的宽度值。设置为小于0或大于Tabs宽度值时,按默认值显示。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueLength

TabBar的宽度值。

默认值:

未设置SubTabBarStyle和BottomTabBarStyle的TabBar且vertical属性为false时,默认值为Tabs的宽度。

未设置SubTabBarStyle和BottomTabBarStyle的TabBar且vertical属性为true时,默认值为56vp。

设置SubTabBarStyle样式且vertical属性为false时,默认值为Tabs的宽度。

设置SubTabBarStyle样式且vertical属性为true时,默认值为56vp。

设置BottomTabBarStyle样式且vertical属性为true时,默认值为96vp。

设置BottomTabBarStyle样式且vertical属性为false时,默认值为Tabs的宽度。

barHeight

支持设备PhonePC/2in1TabletWearable

barHeight(value: Length)

设置TabBar的高度值。横向Tabs可以设置height为'auto',让TabBar自适应子组件高度。height设置为小于0或大于Tabs高度值时,按默认值显示。

API version 14之前的版本,若设置barHeight为固定值后,TabBar无法扩展底部安全区。从API version 14开始支持配合safeAreaPadding属性,当safeAreaPadding不设置bottom或者bottom设置为0时,可以实现扩展安全区。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueLength

TabBar的高度值。

默认值:

未设置带样式的TabBar且vertical属性为false时,默认值为56vp。

未设置带样式的TabBar且vertical属性为true时,默认值为Tabs的高度。

设置SubTabBarStyle样式且vertical属性为false时,默认值为56vp。

设置SubTabBarStyle样式且vertical属性为true时,默认值为Tabs的高度。

设置BottomTabBarStyle样式且vertical属性为true时,默认值为Tabs的高度。

设置BottomTabBarStyle样式且vertical属性为false时,默认值为56vp,从API version 12开始,默认值变更为48vp。

barHeight

支持设备PhonePC/2in1TabletWearable

barHeight(height: Length, noMinHeightLimit: boolean)

设置TabBar的高度值。横向Tabs可以设置height为'auto',让TabBar自适应子组件高度,并通过设置noMinHeightLimit为true让自适应高度可以小于TabBar默认高度。height设置为小于0或大于Tabs高度值时,按默认值显示。

元服务API: 从API version 20开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
heightLength

TabBar的高度值。

默认值:

未设置带样式的TabBar且vertical属性为false时,默认值为56vp。

未设置带样式的TabBar且vertical属性为true时,默认值为Tabs的高度。

设置SubTabBarStyle样式且vertical属性为false时,默认值为56vp。

设置SubTabBarStyle样式且vertical属性为true时,默认值为Tabs的高度。

设置BottomTabBarStyle样式且vertical属性为true时,默认值为Tabs的高度。

设置BottomTabBarStyle样式且vertical属性为false时,默认值为48vp。

noMinHeightLimitboolean

height设置为'auto'时,设置是否取消TabBar的最小高度限制。默认值为false。

说明:

值为true表示取消TabBar的最小高度限制,即TabBar的高度值可以小于默认值。

值为false表示限制TabBar的最小高度,即TabBar的最小高度值等于默认值。

animationCurve

支持设备PhonePC/2in1TabletWearable

animationCurve(curve: Curve | ICurve)

设置Tabs翻页动画曲线。常用曲线参考Curve枚举说明,也可以通过插值计算模块提供的接口创建自定义的插值曲线对象。

元服务API: 从API version 20开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
curveCurve | ICurve

Tabs翻页的动画曲线。

默认值:

滑动TabContent翻页时,默认值为interpolatingSpring(-1, 1, 228, 30)。

点击TabBar页签和调用TabsController的changeIndex接口翻页时,默认值为cubicBezierCurve(0.2, 0.0, 0.1, 1.0)。

设置自定义动画曲线时,滑动翻页和点击页签、调用changeIndex翻页都使用设置的动画曲线。

animationDuration

支持设备PhonePC/2in1TabletWearable

animationDuration(value: number)

设置Tabs翻页动画时长。

animationCurve不设置时,由于滑动TabContent翻页动画曲线interpolatingSpring(-1, 1, 228, 30)时长只受曲线自身参数影响,animationDuration只能控制点击TabBar页签和调用TabsController的changeIndex接口切换TabContent的动画时长。

不受animationDuration控制的曲线可以查阅插值计算模块,比如springMotion、responsiveSpringMotion和interpolatingSpring类型的曲线。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valuenumber

Tabs翻页的动画时长。

默认值:

API version 10及以前,不设置该属性或设置为null时,默认值为0,即Tabs翻页无动画。设置为小于0或undefined时,默认值为300。

API version 11及以后,不设置该属性或设置为异常值,且设置TabBar为BottomTabBarStyle样式时,默认值为0。设置TabBar为其他样式时,默认值为300。

单位:ms

取值范围:[0, +∞)

animationMode

支持设备PhonePC/2in1TabletWearable

animationMode(mode: Optional<AnimationMode>)

设置点击TabBar页签或调用TabsController的changeIndex接口时切换TabContent的动画形式。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
modeOptional<AnimationMode>

点击TabBar页签或调用TabsController的changeIndex接口时切换TabContent的动画形式。

默认值:AnimationMode.CONTENT_FIRST,表示在点击TabBar页签或调用TabsController的changeIndex接口切换TabContent时,先加载目标页内容,再开始切换动画。

barPosition

支持设备PhonePC/2in1TabletWearable

barPosition(value: BarPosition)

设置Tabs的页签位置。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueBarPosition

设置Tabs的页签位置。

默认值:BarPosition.Start

divider

支持设备PhonePC/2in1TabletWearable

divider(value: DividerStyle | null)

设置区分TabBar和TabContent的分割线样式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueDividerStyle | null

分割线样式,默认不显示分割线。

DividerStyle:分割线的样式;

null:不显示分割线。

fadingEdge

支持设备PhonePC/2in1TabletWearable

fadingEdge(value: boolean)

设置页签超过容器宽度时是否渐隐消失。建议配合barBackgroundColor属性一起使用,如果barBackgroundColor属性没有定义,会默认显示页签末端为白色的渐隐效果。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueboolean

页签超过容器宽度时是否渐隐消失。

默认值:true,页签超过容器宽度时会渐隐消失。设置为false时,页签超过容器宽度直接截断显示,不产生任何渐变效果‌。

barOverlap

支持设备PhonePC/2in1TabletWearable

barOverlap(value: boolean)

设置TabBar是否背后变模糊并叠加在TabContent之上。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueboolean

TabBar是否背后变模糊并叠加在TabContent之上。当barOverlap设置为true时,TabBar背后变模糊并叠加在TabContent之上,并且TabBar默认模糊材质的BlurStyle值修改为'BlurStyle.COMPONENT_THICK'。当barOverlap设置为false时,无模糊和叠加效果。

默认值:false

barBackgroundColor

支持设备PhonePC/2in1TabletWearable

barBackgroundColor(value: ResourceColor)

设置TabBar的背景颜色。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueResourceColor

TabBar的背景颜色。

默认值:Color.Transparent,透明

barBackgroundBlurStyle

支持设备PhonePC/2in1TabletWearable

barBackgroundBlurStyle(value: BlurStyle)

设置TabBar的背景模糊材质。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueBlurStyle

TabBar的背景模糊材质。

默认值:BlurStyle.NONE

barBackgroundBlurStyle

支持设备PhonePC/2in1TabletWearable

barBackgroundBlurStyle(style: BlurStyle, options: BackgroundBlurStyleOptions)

为TabBar提供一种在背景和内容之间的模糊能力,通过枚举值的方式封装了不同的模糊半径、蒙版颜色、蒙版透明度、饱和度、亮度。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
styleBlurStyle背景模糊样式。模糊样式中封装了模糊半径、蒙版颜色、蒙版透明度、饱和度、亮度五个参数。
optionsBackgroundBlurStyleOptions背景模糊选项。

barGridAlign

支持设备PhonePC/2in1TabletWearable

barGridAlign(value: BarGridColumnOptions)

以栅格化方式设置TabBar的可见区域。具体参见BarGridColumnOptions对象。仅水平模式下有效,不适用于XS、XL和XXL设备。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valueBarGridColumnOptions以栅格化方式设置TabBar的可见区域。

edgeEffect

支持设备PhonePC/2in1TabletWearable

edgeEffect(edgeEffect: Optional<EdgeEffect>)

设置边缘回弹效果。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
edgeEffectOptional<EdgeEffect>

边缘滑动效果。

默认值:EdgeEffect.Spring

barBackgroundEffect

支持设备PhonePC/2in1TabletWearable

barBackgroundEffect(options: BackgroundEffectOptions)

设置TabBar背景属性,包含背景模糊半径,亮度,饱和度,颜色等参数。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
optionsBackgroundEffectOptions设置TabBar背景属性包括:模糊半径,亮度,饱和度,颜色等。

pageFlipMode

支持设备PhonePC/2in1TabletWearable

pageFlipMode(mode: Optional<PageFlipMode>)

设置鼠标滚轮翻页模式。

元服务API: 从API version 15开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
modeOptional<PageFlipMode>

鼠标滚轮翻页模式。

默认值:PageFlipMode.CONTINUOUS

cachedMaxCount

支持设备PhonePC/2in1TabletWearable

cachedMaxCount(count: number, mode: TabsCacheMode)

设置子组件的最大缓存个数和缓存模式。设置该属性后,不会对缓存范围内的子组件进行预加载,仅对缓存范围外的子组件进行释放。

元服务API: 从API version 19开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
countnumber

子组件的最大缓存个数。默认所有子组件加载后都不再释放。

取值范围:[0, +∞)。

modeTabsCacheMode

子组件的缓存模式。

默认值:TabsCacheMode.CACHE_BOTH_SIDE

DividerStyle对象说明

支持设备PhonePC/2in1TabletWearable

分割线样式对象。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型必填说明
strokeWidthLength

分割线的线宽(不支持百分比设置)。

默认值:0.0

单位:vp

取值范围:[0, +∞)。

colorResourceColor

分割线的颜色。

默认值:#33182431

startMarginLength

分割线与侧边栏顶端的距离(不支持百分比设置)。

默认值:0.0

单位:vp

取值范围:[0, +∞)。

endMarginLength

分割线与侧边栏底端的距离(不支持百分比设置)。

默认值:0.0

单位:vp

取值范围:[0, +∞)。

BarGridColumnOptions对象说明

支持设备PhonePC/2in1TabletWearable

TabBar栅格化方式设置的对象,包括栅格模式下的column边距和间隔,以及小、中、大屏下,页签占用的columns数量。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型必填说明
marginDimension

栅格模式下的column边距(不支持百分比设置)。

默认值:24.0

单位:vp

gutterDimension

栅格模式下的column间隔(不支持百分比设置)。

默认值:24.0

单位:vp

smnumber

小屏下,页签占用的columns数量,必须是非负偶数。小屏为大于等于320vp但小于600vp。

默认值为-1,代表页签占用TabBar全部宽度。

mdnumber

中屏下,页签占用的columns数量,必须是非负偶数。中屏为大于等于600vp但小于800vp。

默认值为-1,代表页签占用TabBar全部宽度。

lgnumber

大屏下,页签占用的columns数量,必须是非负偶数。大屏为大于等于840vp但小于1024vp。

默认值为-1,代表页签占用TabBar全部宽度。

ScrollableBarModeOptions对象说明

支持设备PhonePC/2in1TabletWearable

Scrollable模式下的TabBar的布局样式对象。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型必填说明
marginDimension

Scrollable模式下的TabBar的左右边距(不支持百分比设置)。

默认值:0.0

单位:vp

取值范围:[0, +∞)。

nonScrollableLayoutStyleLayoutStyle

Scrollable模式下不滚动时的页签排布方式。

默认值:LayoutStyle.ALWAYS_CENTER

BarMode枚举说明

支持设备PhonePC/2in1TabletWearable

TabBar布局模式枚举。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称说明
Scrollable0每一个TabBar均使用实际布局宽度,超过总长度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。
Fixed1所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度)。

AnimationMode枚举说明

支持设备PhonePC/2in1TabletWearable

点击TabBar页签时切换TabContent的动画形式枚举。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称说明
CONTENT_FIRST0

先加载目标页内容,再开始切换动画。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

ACTION_FIRST1

先开始切换动画,再加载目标页内容;生效需要同时需要满足:Tabs的height、width没有设置成auto。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

NO_ANIMATION2

关闭默认动画。调用TabsController的changeIndex接口切换TabContent时该枚举值不生效。

可以通过设置animationDuration为0实现调用TabsController的changeIndex接口时不带动画。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

CONTENT_FIRST_WITH_JUMP3

先加载目标页内容,再无动画跳转到目标页附近,最后有动画跳转到目标页。

元服务API: 从API version 15开始,该接口支持在元服务中使用。

ACTION_FIRST_WITH_JUMP4

先无动画跳转到目标页附近,再有动画跳转到目标页,最后加载目标页内容。此项生效需要同时需要满足:Tabs的height、width没有设置成auto。

元服务API: 从API version 15开始,该接口支持在元服务中使用。

LayoutStyle枚举说明

支持设备PhonePC/2in1TabletWearable

Scrollable模式下不滚动时的页签排布方式枚举。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称说明
ALWAYS_CENTER0

当页签内容超过TabBar宽度时,TabBar可滚动。

当页签内容不超过TabBar宽度时,TabBar不可滚动,页签紧凑居中。

ALWAYS_AVERAGE_SPLIT1

当页签内容超过TabBar宽度时,TabBar可滚动。

当页签内容不超过TabBar宽度时,TabBar不可滚动,且所有页签平均分配TabBar宽度。

SPACE_BETWEEN_OR_CENTER2

当页签内容超过TabBar宽度时,TabBar可滚动。

当页签内容不超过TabBar宽度但超过TabBar宽度一半时,TabBar不可滚动,页签紧凑居中。

当页签内容不超过TabBar宽度一半时,TabBar不可滚动,保证页签居中排列在TabBar宽度一半,且间距相同。

CommonModifier

支持设备PhonePC/2in1TabletWearable

type CommonModifier = CommonModifier

作为Tabs组件的参数对象。

元服务API: 从API version 15开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

类型说明
CommonModifier设置TabBar的通用属性。

TabsCacheMode枚举说明

支持设备PhonePC/2in1TabletWearable

子组件的缓存模式。

元服务API: 从API version 19开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称说明
CACHE_BOTH_SIDE0缓存当前显示的子组件和其两侧的子组件。即当设置cachedMaxCount属性的count值为n时,最多缓存2n+1个子组件。
CACHE_LATEST_SWITCHED1缓存当前显示的子组件和最近切换过的子组件。即当设置cachedMaxCount属性的count值为n时,最多缓存n+1个子组件。

事件

支持设备PhonePC/2in1TabletWearable

除支持通用事件外,还支持以下事件:

onChange

支持设备PhonePC/2in1TabletWearable

onChange(event: Callback<number>)

Tab页签切换后触发的事件。

满足以下任一条件,即可触发该事件:

1、滑动页面进行页面切换时,组件滑动动画结束后触发。

2、通过控制器调用changeIndex接口,Tab页签切换后触发。

3、动态修改状态变量构造的index属性值,Tab页签切换后触发。

4、点击TabBar页签,Tab页签切换后触发。

说明

使用自定义页签时,在onChange事件中联动可能会导致滑动页面切换后才执行页签联动,引起自定义页签切换效果延迟。建议在onAnimationStart中监听并刷新当前索引,以确保动效能够及时触发。具体实现可参考示例3。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
eventCallback<number>当前显示的index索引,索引从0开始计算。

onTabBarClick

支持设备PhonePC/2in1TabletWearable

onTabBarClick(event: Callback<number>)

Tab页签点击后触发的事件。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
eventCallback<number>被点击的index索引,索引从0开始计算。

onAnimationStart

支持设备PhonePC/2in1TabletWearable

onAnimationStart(handler: OnTabsAnimationStartCallback)

切换动画开始时触发该回调。当animationDuration为0时动画关闭,不触发该回调。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
handlerOnTabsAnimationStartCallback切换动画开始时触发的回调。

onAnimationEnd

支持设备PhonePC/2in1TabletWearable

onAnimationEnd(handler: OnTabsAnimationEndCallback)

切换动画结束时触发该回调,包括动画过程中手势中断。当animationDuration为0时动画关闭,不触发该回调。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
handlerOnTabsAnimationEndCallback切换动画结束时触发的回调。

onGestureSwipe

支持设备PhonePC/2in1TabletWearable

onGestureSwipe(handler: OnTabsGestureSwipeCallback)

在页面跟手滑动过程中,逐帧触发该回调。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
handlerOnTabsGestureSwipeCallback在页面跟手滑动过程中,逐帧触发的回调。

customContentTransition

支持设备PhonePC/2in1TabletWearable

customContentTransition(delegate: TabsCustomContentTransitionCallback)

自定义Tabs页面切换动画。

使用说明:

1、当使用自定义切换动画时,Tabs组件自带的默认切换动画会被禁用,同时,页面也无法跟手滑动。

2、当设置为undefined时,表示不使用自定义切换动画,仍然使用组件自带的默认切换动画。

3、当前自定义切换动画不支持打断。

4、目前自定义切换动画只支持两种场景触发:点击页签和调用TabsController.changeIndex()接口。

5、当使用自定义切换动画时,Tabs组件支持的事件中,除了onGestureSwipe,其他事件均支持。

6、onChange和onAnimationEnd事件的触发时机需要特殊说明:如果在第一次自定义动画执行过程中,触发了第二次自定义动画,那么在开始第二次自定义动画时,就会触发第一次自定义动画的onChange和onAnimationEnd事件。

7、当使用自定义动画时,参与动画的页面布局方式会改为Stack布局。如果开发者未主动设置相关页面的zIndex属性,那么所有页面的zIndex值是一样的,页面的渲染层级会按照在组件树上的顺序(即页面的index值顺序)确定。因此,开发者需要主动修改页面的zIndex属性,来控制页面的渲染层级。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
delegateTabsCustomContentTransitionCallback自定义Tabs页面切换动画开始时触发的回调。

onContentWillChange

支持设备PhonePC/2in1TabletWearable

onContentWillChange(handler: OnTabsContentWillChangeCallback)

自定义Tabs页面切换拦截事件能力,新页面即将显示时触发该回调。

满足以下任一条件,即可触发该事件:

1、滑动TabContent切换新页面时触发。

2、通过TabsController.changeIndex接口切换新页面时触发。

3、通过动态修改index属性值切换新页面时触发。

4、通过点击TabBar页签切换新页面时触发。

5、TabBar页签获焦后,通过键盘左右方向键等切换新页面时触发。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
handlerOnTabsContentWillChangeCallback自定义Tabs页面切换拦截事件能力,新页面即将显示时触发的回调。

onSelected

支持设备PhonePC/2in1TabletWearable

onSelected(event: Callback<number>)

当选中元素改变时触发该回调,返回值为当前选中的元素的索引值。

满足以下任一条件,即可触发该事件:

  1. 滑动离手时满足翻页阈值,开始切换动画时触发。

  2. 通过TabsController控制器调用changeIndex接口,开始切换动画时触发。

  3. 动态修改状态变量构造的index属性值后触发。

  4. 通过页签处点击触发。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
eventCallback<number>当前选中元素的索引。

说明

onSelected回调中不可通过TabsOptions的index设置当前显示页的索引,不可调用TabsController.changeIndex()方法。

onUnselected

支持设备PhonePC/2in1TabletWearable

onUnselected(event: Callback<number>)

当选中元素改变时触发该回调,返回值为将要隐藏的元素的索引值。

满足以下任一条件,即可触发该事件:

  1. 滑动离手时满足翻页阈值,开始切换动画时触发。

  2. 通过TabsController控制器调用changeIndex接口,开始切换动画时触发。

  3. 动态修改状态变量构造的index属性值后触发。

  4. 通过页签处点击触发。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
eventCallback<number>将要隐藏元素的索引。

说明

onUnselected回调中不可通过TabsOptions的index设置当前显示页的索引,不可调用TabsController.changeIndex()方法。

OnTabsAnimationStartCallback

支持设备PhonePC/2in1TabletWearable

type OnTabsAnimationStartCallback = (index: number, targetIndex: number, extraInfo: TabsAnimationEvent) => void

切换动画开始时触发的回调。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
indexnumber当前显示元素的索引,索引从0开始。
targetIndexnumber切换动画目标元素的索引,索引从0开始。
extraInfoTabsAnimationEvent动画相关信息,包括主轴方向上当前显示元素和目标元素相对Tabs起始位置的位移,以及离手速度。

OnTabsAnimationEndCallback

支持设备PhonePC/2in1TabletWearable

type OnTabsAnimationEndCallback = (index: number, extraInfo: TabsAnimationEvent) => void

切换动画结束时触发的回调。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
indexnumber当前显示元素的索引,索引从0开始。
extraInfoTabsAnimationEvent动画相关信息,只返回主轴方向上当前显示元素相对于Tabs起始位置的位移。

OnTabsGestureSwipeCallback

支持设备PhonePC/2in1TabletWearable

type OnTabsGestureSwipeCallback = (index: number, extraInfo: TabsAnimationEvent) => void

在页面跟手滑动过程中,逐帧触发的回调。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
indexnumber当前显示元素的索引,索引从0开始。
extraInfoTabsAnimationEvent动画相关信息,只返回主轴方向上当前显示元素相对于Tabs起始位置的位移。

TabsCustomContentTransitionCallback

支持设备PhonePC/2in1TabletWearable

type TabsCustomContentTransitionCallback = (from: number, to: number) => TabContentAnimatedTransition | undefined

自定义Tabs页面切换动画开始时触发的回调。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
fromnumber动画开始时,当前页面的index值,索引从0开始。
tonumber动画开始时,目标页面的index值,索引从0开始。

返回值:

类型说明
TabContentAnimatedTransition | undefined自定义切换动画相关信息。

OnTabsContentWillChangeCallback

支持设备PhonePC/2in1TabletWearable

type OnTabsContentWillChangeCallback = (currentIndex: number, comingIndex: number) => boolean

自定义Tabs页面切换拦截事件能力,新页面即将显示时触发的回调。

元服务API: 从API version 18开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
currentIndexnumber当前显示页面的index索引,索引从0开始计算。
comingIndexnumber将要显示的新页面的index索引。

返回值:

类型说明
boolean

当回调函数handler的返回值为true时,Tabs可以切换到新页面。

当回调函数handler的返回值为false时,Tabs无法切换到新页面,仍然显示原来页面内容。

TabsAnimationEvent对象说明

支持设备PhonePC/2in1TabletWearable

Tabs组件动画相关信息集合。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型只读可选说明
currentOffsetnumberTabs当前显示元素在主轴方向上,相对于Tabs起始位置的位移。单位vp,默认值为0。
targetOffsetnumberTabs动画目标元素在主轴方向上,相对于Tabs起始位置的位移。单位vp,默认值为0。
velocitynumberTabs离手动画开始时的离手速度。单位vp/s,默认值为0。

TabContentAnimatedTransition

支持设备PhonePC/2in1TabletWearable

Tabs自定义切换动画相关信息。

卡片能力: 从API version 11开始,该接口支持在ArkTS卡片中使用。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

名称类型必填说明
timeoutnumber

Tabs自定义切换动画超时时间。从自定义动画开始切换计时,如果到达该时间后,开发者仍未调用TabContentTransitionProxy的finishTransition接口通知Tabs组件自定义动画结束,那么组件就会认为此次自定义动画已结束,直接执行后续操作。

默认值:1000

单位:ms

取值范围:[0, +∞)。

transitionCallback<TabContentTransitionProxy>自定义切换动画具体内容。

TabContentTransitionProxy

支持设备PhonePC/2in1TabletWearable

Tabs自定义切换动画执行过程中,返回给开发者的proxy对象。开发者可通过该对象获取自定义动画的起始和目标页面信息,同时,也可以通过调用该对象的finishTransition接口通知Tabs组件自定义动画已结束。

卡片能力: 从API version 11开始,该接口支持在ArkTS卡片中使用。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

属性

名称类型只读可选说明
fromnumber自定义动画起始页面对应的index值,索引从0开始。
tonumber自定义动画目标页面对应的index值,索引从0开始。

finishTransition

支持设备PhonePC/2in1TabletWearable

finishTransition(): void

通知Tabs组件,此页面的自定义动画已结束。

卡片能力: 从API version 11开始,该接口支持在ArkTS卡片中使用。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

TabsController

支持设备PhonePC/2in1TabletWearable

Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

constructor

支持设备PhonePC/2in1TabletWearable

constructor()

TabsController的构造函数。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

changeIndex

支持设备PhonePC/2in1TabletWearable

changeIndex(value: number): void

控制Tabs切换到指定页签。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
valuenumber

页签在Tabs里的索引值,索引值从0开始。

说明:

设置小于0或大于最大数量的值时,取默认值0。

preloadItems

支持设备PhonePC/2in1TabletWearable

preloadItems(indices: Optional<Array<number>>): Promise<void>

控制Tabs预加载指定子节点。调用该接口后会一次性加载所有指定的子节点,因此为了性能考虑,建议分批加载子节点。

元服务API: 从API version 12开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
indicesOptional<Array<number>>

需预加载的子节点的下标数组。

默认值:空数组。

返回值:

类型说明
Promise<void>预加载完成后触发的回调。

错误码:

以下错误码的详细介绍请参见通用错误码。

错误码ID错误信息
401Parameter 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.

setTabBarTranslate

支持设备PhonePC/2in1TabletWearable

setTabBarTranslate(translate: TranslateOptions): void

设置TabBar的平移距离。

说明

当使用bindTabsToScrollable或bindTabsToNestedScrollable等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效,调用setTabBarTranslate接口设置的TabBar平移距离会失效。因此不建议同时使用bindTabsToScrollable、bindTabsToNestedScrollable和setTabBarTranslate接口。

元服务API: 从API version 13开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
translateTranslateOptions设置TabBar的平移距离。

setTabBarOpacity

支持设备PhonePC/2in1TabletWearable

setTabBarOpacity(opacity: number): void

设置TabBar的不透明度。

说明

当使用bindTabsToScrollable或bindTabsToNestedScrollable等接口绑定了Tabs组件和可滚动容器组件后,在滑动可滚动容器组件时,会触发所有与其绑定的Tabs组件的TabBar的显示和隐藏动效,调用setTabBarOpacity接口设置的TabBar不透明度会失效。因此不建议同时使用bindTabsToScrollable、bindTabsToNestedScrollable和setTabBarOpacity接口。

元服务API: 从API version 13开始,该接口支持在元服务中使用。

系统能力: SystemCapability.ArkUI.ArkUI.Full

参数:

参数名类型必填说明
opacitynumber设置TabBar的不透明度,取值范围为[0.0, 1.0]。

示例

支持设备PhonePC/2in1TabletWearable

示例1(设置TabBar的布局模式)

本示例通过barMode分别实现了页签均分布局和以实际长度布局,且展示了当页签布局长度之和超过了TabBar总长度后可滑动的效果。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. @State text: string = '文本';
  6. @State barMode: BarMode = BarMode.Fixed;
  7. build() {
  8. Column() {
  9. Row() {
  10. Button('文本增加 ')
  11. .width('47%')
  12. .height(50)
  13. .onClick((event?: ClickEvent) => {
  14. this.text += '文本增加';
  15. })
  16. .margin({ right: '6%', bottom: '12vp' })
  17. Button('文本重置')
  18. .width('47%')
  19. .height(50)
  20. .onClick((event?: ClickEvent) => {
  21. this.text = '文本';
  22. })
  23. .margin({ bottom: '12vp' })
  24. }
  25. Row() {
  26. Button('BarMode.Fixed')
  27. .width('47%')
  28. .height(50)
  29. .onClick((event?: ClickEvent) => {
  30. this.barMode = BarMode.Fixed;
  31. })
  32. .margin({ right: '6%', bottom: '12vp' })
  33. Button('BarMode.Scrollable')
  34. .width('47%')
  35. .height(50)
  36. .onClick((event?: ClickEvent) => {
  37. this.barMode = BarMode.Scrollable;
  38. })
  39. .margin({ bottom: '12vp' })
  40. }
  41. Tabs() {
  42. TabContent() {
  43. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  44. }.tabBar(SubTabBarStyle.of(this.text))
  45. TabContent() {
  46. Column().width('100%').height('100%').backgroundColor(Color.Green)
  47. }.tabBar(SubTabBarStyle.of(this.text))
  48. TabContent() {
  49. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  50. }.tabBar(SubTabBarStyle.of(this.text))
  51. }
  52. .height('60%')
  53. .backgroundColor(0xf1f3f5)
  54. .barMode(this.barMode)
  55. }
  56. .width('100%')
  57. .height(500)
  58. .padding('24vp')
  59. }
  60. }

示例2(设置Scrollable模式下的TabBar的布局样式)

本示例实现了barMode的ScrollableBarModeOptions参数,该参数仅在Scrollable模式下有效。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample6 {
  5. private controller: TabsController = new TabsController();
  6. @State scrollMargin: number = 0;
  7. @State layoutStyle: LayoutStyle = LayoutStyle.ALWAYS_CENTER;
  8. @State text: string = '文本';
  9. build() {
  10. Column() {
  11. Row() {
  12. Button('scrollMargin+10 ' + this.scrollMargin)
  13. .width('47%')
  14. .height(50)
  15. .margin({ top: 5 })
  16. .onClick((event?: ClickEvent) => {
  17. this.scrollMargin += 10;
  18. })
  19. .margin({ right: '6%', bottom: '12vp' })
  20. Button('scrollMargin-10 ' + this.scrollMargin)
  21. .width('47%')
  22. .height(50)
  23. .margin({ top: 5 })
  24. .onClick((event?: ClickEvent) => {
  25. this.scrollMargin -= 10;
  26. })
  27. .margin({ bottom: '12vp' })
  28. }
  29. Row() {
  30. Button('文本增加 ')
  31. .width('47%')
  32. .height(50)
  33. .margin({ top: 5 })
  34. .onClick((event?: ClickEvent) => {
  35. this.text += '文本增加';
  36. })
  37. .margin({ right: '6%', bottom: '12vp' })
  38. Button('文本重置')
  39. .width('47%')
  40. .height(50)
  41. .margin({ top: 5 })
  42. .onClick((event?: ClickEvent) => {
  43. this.text = '文本';
  44. })
  45. .margin({ bottom: '12vp' })
  46. }
  47. Row() {
  48. Button('layoutStyle.ALWAYS_CENTER')
  49. .width('100%')
  50. .height(50)
  51. .margin({ top: 5 })
  52. .fontSize(15)
  53. .onClick((event?: ClickEvent) => {
  54. this.layoutStyle = LayoutStyle.ALWAYS_CENTER;
  55. })
  56. .margin({ bottom: '12vp' })
  57. }
  58. Row() {
  59. Button('layoutStyle.ALWAYS_AVERAGE_SPLIT')
  60. .width('100%')
  61. .height(50)
  62. .margin({ top: 5 })
  63. .fontSize(15)
  64. .onClick((event?: ClickEvent) => {
  65. this.layoutStyle = LayoutStyle.ALWAYS_AVERAGE_SPLIT;
  66. })
  67. .margin({ bottom: '12vp' })
  68. }
  69. Row() {
  70. Button('layoutStyle.SPACE_BETWEEN_OR_CENTER')
  71. .width('100%')
  72. .height(50)
  73. .margin({ top: 5 })
  74. .fontSize(15)
  75. .onClick((event?: ClickEvent) => {
  76. this.layoutStyle = LayoutStyle.SPACE_BETWEEN_OR_CENTER;
  77. })
  78. .margin({ bottom: '12vp' })
  79. }
  80. Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
  81. TabContent() {
  82. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  83. }.tabBar(SubTabBarStyle.of(this.text))
  84. TabContent() {
  85. Column().width('100%').height('100%').backgroundColor(Color.Green)
  86. }.tabBar(SubTabBarStyle.of(this.text))
  87. TabContent() {
  88. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  89. }.tabBar(SubTabBarStyle.of(this.text))
  90. }
  91. .animationDuration(300)
  92. .height('60%')
  93. .backgroundColor(0xf1f3f5)
  94. .barMode(BarMode.Scrollable, { margin: this.scrollMargin, nonScrollableLayoutStyle: this.layoutStyle })
  95. }
  96. .width('100%')
  97. .height(500)
  98. .margin({ top: 5 })
  99. .padding('24vp')
  100. }
  101. }

示例3(自定义页签切换联动)

本示例通过onAnimationStart、onChange实现切换时自定义tabBar和TabContent的联动。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. @State fontColor: string = '#182431';
  6. @State selectedFontColor: string = '#007DFF';
  7. @State currentIndex: number = 0;
  8. @State selectedIndex: number = 0;
  9. private controller: TabsController = new TabsController();
  10. @Builder tabBuilder(index: number, name: string) {
  11. Column() {
  12. Text(name)
  13. .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
  14. .fontSize(16)
  15. .fontWeight(this.selectedIndex === index ? 500 : 400)
  16. .lineHeight(22)
  17. .margin({ top: 17, bottom: 7 })
  18. Divider()
  19. .strokeWidth(2)
  20. .color('#007DFF')
  21. .opacity(this.selectedIndex === index ? 1 : 0)
  22. }.width('100%')
  23. }
  24. build() {
  25. Column() {
  26. Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
  27. TabContent() {
  28. Column().width('100%').height('100%').backgroundColor('#00CB87')
  29. }.tabBar(this.tabBuilder(0, 'green'))
  30. TabContent() {
  31. Column().width('100%').height('100%').backgroundColor('#007DFF')
  32. }.tabBar(this.tabBuilder(1, 'blue'))
  33. TabContent() {
  34. Column().width('100%').height('100%').backgroundColor('#FFBF00')
  35. }.tabBar(this.tabBuilder(2, 'yellow'))
  36. TabContent() {
  37. Column().width('100%').height('100%').backgroundColor('#E67C92')
  38. }.tabBar(this.tabBuilder(3, 'pink'))
  39. }
  40. .vertical(false)
  41. .barMode(BarMode.Fixed)
  42. .barWidth(360)
  43. .barHeight(56)
  44. .animationDuration(400)
  45. .onChange((index: number) => {
  46. // currentIndex控制TabContent显示页签
  47. this.currentIndex = index;
  48. this.selectedIndex = index;
  49. })
  50. .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
  51. if (index === targetIndex) {
  52. return;
  53. }
  54. // selectedIndex控制自定义TabBar内Image和Text颜色切换
  55. this.selectedIndex = targetIndex;
  56. })
  57. .width(360)
  58. .height(296)
  59. .margin({ top: 52 })
  60. .backgroundColor('#F1F3F5')
  61. }.width('100%')
  62. }
  63. }

示例4(分割线基本属性)

本示例通过divider实现了分割线各种属性的展示。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsDivider1 {
  5. private controller1: TabsController = new TabsController();
  6. @State dividerColor: string = 'red';
  7. @State strokeWidth: number = 2;
  8. @State startMargin: number = 0;
  9. @State endMargin: number = 0;
  10. @State nullFlag: boolean = false;
  11. build() {
  12. Column() {
  13. Tabs({ controller: this.controller1 }) {
  14. TabContent() {
  15. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  16. }.tabBar('pink')
  17. TabContent() {
  18. Column().width('100%').height('100%').backgroundColor(Color.Yellow)
  19. }.tabBar('yellow')
  20. TabContent() {
  21. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  22. }.tabBar('blue')
  23. TabContent() {
  24. Column().width('100%').height('100%').backgroundColor(Color.Green)
  25. }.tabBar('green')
  26. TabContent() {
  27. Column().width('100%').height('100%').backgroundColor(Color.Red)
  28. }.tabBar('red')
  29. }
  30. .vertical(true)
  31. .scrollable(true)
  32. .barMode(BarMode.Fixed)
  33. .barWidth(70)
  34. .barHeight(200)
  35. .animationDuration(400)
  36. .onChange((index: number) => {
  37. console.info(index.toString());
  38. })
  39. .height('200vp')
  40. .margin({ bottom: '12vp' })
  41. .divider(this.nullFlag ? null : {
  42. strokeWidth: this.strokeWidth,
  43. color: this.dividerColor,
  44. startMargin: this.startMargin,
  45. endMargin: this.endMargin
  46. })
  47. Button('常规Divider').width('100%').margin({ bottom: '12vp' })
  48. .onClick(() => {
  49. this.nullFlag = false;
  50. this.strokeWidth = 2;
  51. this.dividerColor = 'red';
  52. this.startMargin = 0;
  53. this.endMargin = 0;
  54. })
  55. Button('空Divider').width('100%').margin({ bottom: '12vp' })
  56. .onClick(() => {
  57. this.nullFlag = true;
  58. })
  59. Button('颜色变为蓝色').width('100%').margin({ bottom: '12vp' })
  60. .onClick(() => {
  61. this.dividerColor = 'blue';
  62. })
  63. Button('宽度增加').width('100%').margin({ bottom: '12vp' })
  64. .onClick(() => {
  65. this.strokeWidth += 2;
  66. })
  67. Button('宽度减小').width('100%').margin({ bottom: '12vp' })
  68. .onClick(() => {
  69. if (this.strokeWidth > 2) {
  70. this.strokeWidth -= 2;
  71. }
  72. })
  73. Button('上边距增加').width('100%').margin({ bottom: '12vp' })
  74. .onClick(() => {
  75. this.startMargin += 2;
  76. })
  77. Button('上边距减少').width('100%').margin({ bottom: '12vp' })
  78. .onClick(() => {
  79. if (this.startMargin > 2) {
  80. this.startMargin -= 2;
  81. }
  82. })
  83. Button('下边距增加').width('100%').margin({ bottom: '12vp' })
  84. .onClick(() => {
  85. this.endMargin += 2;
  86. })
  87. Button('下边距减少').width('100%').margin({ bottom: '12vp' })
  88. .onClick(() => {
  89. if (this.endMargin > 2) {
  90. this.endMargin -= 2;
  91. }
  92. })
  93. }.padding({ top: '24vp', left: '24vp', right: '24vp' })
  94. }
  95. }

示例5(设置TabBar渐隐)

本示例通过fadingEdge实现了切换子页签渐隐和不渐隐。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsOpaque {
  5. @State message: string = 'Hello World';
  6. private controller: TabsController = new TabsController();
  7. private controller1: TabsController = new TabsController();
  8. @State selfFadingFade: boolean = true;
  9. build() {
  10. Column() {
  11. Button('子页签设置渐隐').width('100%').margin({ bottom: '12vp' })
  12. .onClick((event?: ClickEvent) => {
  13. this.selfFadingFade = true;
  14. })
  15. Button('子页签设置不渐隐').width('100%').margin({ bottom: '12vp' })
  16. .onClick((event?: ClickEvent) => {
  17. this.selfFadingFade = false;
  18. })
  19. Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
  20. TabContent() {
  21. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  22. }.tabBar('pink')
  23. TabContent() {
  24. Column().width('100%').height('100%').backgroundColor(Color.Yellow)
  25. }.tabBar('yellow')
  26. TabContent() {
  27. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  28. }.tabBar('blue')
  29. TabContent() {
  30. Column().width('100%').height('100%').backgroundColor(Color.Green)
  31. }.tabBar('green')
  32. TabContent() {
  33. Column().width('100%').height('100%').backgroundColor(Color.Green)
  34. }.tabBar('green')
  35. TabContent() {
  36. Column().width('100%').height('100%').backgroundColor(Color.Green)
  37. }.tabBar('green')
  38. TabContent() {
  39. Column().width('100%').height('100%').backgroundColor(Color.Green)
  40. }.tabBar('green')
  41. TabContent() {
  42. Column().width('100%').height('100%').backgroundColor(Color.Green)
  43. }.tabBar('green')
  44. }
  45. .vertical(false)
  46. .scrollable(true)
  47. .barMode(BarMode.Scrollable)
  48. .barHeight(80)
  49. .animationDuration(400)
  50. .onChange((index: number) => {
  51. console.info(index.toString());
  52. })
  53. .fadingEdge(this.selfFadingFade)
  54. .height('30%')
  55. .width('100%')
  56. Tabs({ barPosition: BarPosition.Start, controller: this.controller1 }) {
  57. TabContent() {
  58. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  59. }.tabBar('pink')
  60. TabContent() {
  61. Column().width('100%').height('100%').backgroundColor(Color.Yellow)
  62. }.tabBar('yellow')
  63. TabContent() {
  64. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  65. }.tabBar('blue')
  66. TabContent() {
  67. Column().width('100%').height('100%').backgroundColor(Color.Green)
  68. }.tabBar('green')
  69. TabContent() {
  70. Column().width('100%').height('100%').backgroundColor(Color.Green)
  71. }.tabBar('green')
  72. TabContent() {
  73. Column().width('100%').height('100%').backgroundColor(Color.Green)
  74. }.tabBar('green')
  75. }
  76. .vertical(true)
  77. .scrollable(true)
  78. .barMode(BarMode.Scrollable)
  79. .barHeight(200)
  80. .barWidth(80)
  81. .animationDuration(400)
  82. .onChange((index: number) => {
  83. console.info(index.toString());
  84. })
  85. .fadingEdge(this.selfFadingFade)
  86. .height('30%')
  87. .width('100%')
  88. }
  89. .padding({ top: '24vp', left: '24vp', right: '24vp' })
  90. }
  91. }

示例6(设置TabBar叠加在TabContent内容上)

本示例通过barOverlap实现了TabBar是否背后变模糊并叠加在TabContent之上。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct barHeightTest {
  5. @State arr: number[] = [0, 1, 2, 3];
  6. @State barOverlap: boolean = true;
  7. build() {
  8. Column() {
  9. Text(`barOverlap ${this.barOverlap}`).fontSize(16)
  10. Button('barOverlap变化').width('100%').margin({ bottom: '12vp' })
  11. .onClick((event?: ClickEvent) => {
  12. if (this.barOverlap) {
  13. this.barOverlap = false;
  14. } else {
  15. this.barOverlap = true;
  16. }
  17. })
  18. Tabs({ barPosition: BarPosition.End }) {
  19. TabContent() {
  20. Column() {
  21. List({ space: 10 }) {
  22. ForEach(this.arr, (item: number) => {
  23. ListItem() {
  24. Text('item' + item).width('80%').height(200).fontSize(16).textAlign(TextAlign.Center).backgroundColor('#fff8b81e')
  25. }
  26. }, (item: string) => item)
  27. }.width('100%').height('100%')
  28. .lanes(2).alignListItem(ListItemAlign.Center)
  29. }.width('100%').height('100%')
  30. .backgroundColor(Color.Pink)
  31. }
  32. .tabBar(new BottomTabBarStyle($r('sys.media.ohos_icon_mask_svg'), '测试0'))
  33. }
  34. .scrollable(false)
  35. .height('60%')
  36. .barOverlap(this.barOverlap)
  37. }
  38. .height(500)
  39. .padding({ top: '24vp', left: '24vp', right: '24vp' })
  40. }
  41. }

示例7(设置TabBar栅格化可见区域)

本示例通过barGridAlign实现了以栅格化方式设置TabBar的可见区域。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample5 {
  5. private controller: TabsController = new TabsController();
  6. @State gridMargin: number = 10;
  7. @State gridGutter: number = 10;
  8. @State sm: number = -2;
  9. @State clickedContent: string = '';
  10. build() {
  11. Column() {
  12. Row() {
  13. Button('gridMargin+10 ' + this.gridMargin)
  14. .width('47%')
  15. .height(50)
  16. .margin({ top: 5 })
  17. .onClick((event?: ClickEvent) => {
  18. this.gridMargin += 10;
  19. })
  20. .margin({ right: '6%', bottom: '12vp' })
  21. Button('gridMargin-10 ' + this.gridMargin)
  22. .width('47%')
  23. .height(50)
  24. .margin({ top: 5 })
  25. .onClick((event?: ClickEvent) => {
  26. this.gridMargin -= 10;
  27. })
  28. .margin({ bottom: '12vp' })
  29. }
  30. Row() {
  31. Button('gridGutter+10 ' + this.gridGutter)
  32. .width('47%')
  33. .height(50)
  34. .margin({ top: 5 })
  35. .onClick((event?: ClickEvent) => {
  36. this.gridGutter += 10;
  37. })
  38. .margin({ right: '6%', bottom: '12vp' })
  39. Button('gridGutter-10 ' + this.gridGutter)
  40. .width('47%')
  41. .height(50)
  42. .margin({ top: 5 })
  43. .onClick((event?: ClickEvent) => {
  44. this.gridGutter -= 10;
  45. })
  46. .margin({ bottom: '12vp' })
  47. }
  48. Row() {
  49. Button('sm+2 ' + this.sm)
  50. .width('47%')
  51. .height(50)
  52. .margin({ top: 5 })
  53. .onClick((event?: ClickEvent) => {
  54. this.sm += 2;
  55. })
  56. .margin({ right: '6%' })
  57. Button('sm-2 ' + this.sm).width('47%').height(50).margin({ top: 5 })
  58. .onClick((event?: ClickEvent) => {
  59. this.sm -= 2;
  60. })
  61. }
  62. Text('点击内容:' + this.clickedContent).width('100%').height(200).margin({ top: 5 })
  63. Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
  64. TabContent() {
  65. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  66. }.tabBar(BottomTabBarStyle.of($r('sys.media.ohos_app_icon'), '1'))
  67. TabContent() {
  68. Column().width('100%').height('100%').backgroundColor(Color.Green)
  69. }.tabBar(BottomTabBarStyle.of($r('sys.media.ohos_app_icon'), '2'))
  70. TabContent() {
  71. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  72. }.tabBar(BottomTabBarStyle.of($r('sys.media.ohos_app_icon'), '3'))
  73. }
  74. .width('350vp')
  75. .animationDuration(300)
  76. .height('60%')
  77. .barGridAlign({ sm: this.sm, margin: this.gridMargin, gutter: this.gridGutter })
  78. .backgroundColor(0xf1f3f5)
  79. .onTabBarClick((index: number) => {
  80. this.clickedContent += 'now index ' + index + ' is clicked\n';
  81. })
  82. }
  83. .width('100%')
  84. .height(500)
  85. .margin({ top: 5 })
  86. .padding('10vp')
  87. }
  88. }

示例8(自定义Tabs页面切换动画)

本示例通过customContentTransition实现了自定义Tabs页面的切换动画。

 
  1. // xxx.ets
  2. interface itemType {
  3. text: string,
  4. backgroundColor: Color
  5. }
  6. @Entry
  7. @Component
  8. struct TabsCustomAnimationExample {
  9. @State data: itemType[] = [
  10. {
  11. text: 'Red',
  12. backgroundColor: Color.Red
  13. },
  14. {
  15. text: 'Yellow',
  16. backgroundColor: Color.Yellow
  17. },
  18. {
  19. text: 'Blue',
  20. backgroundColor: Color.Blue
  21. }];
  22. @State opacityList: number[] = [];
  23. @State scaleList: number[] = [];
  24. private durationList: number[] = [];
  25. private timeoutList: number[] = [];
  26. private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => {
  27. let tabContentAnimatedTransition = {
  28. timeout: this.timeoutList[from],
  29. transition: (proxy: TabContentTransitionProxy) => {
  30. this.scaleList[from] = 1.0;
  31. this.scaleList[to] = 0.5;
  32. this.opacityList[from] = 1.0;
  33. this.opacityList[to] = 0.5;
  34. this.getUIContext()?.animateTo({
  35. duration: this.durationList[from],
  36. onFinish: () => {
  37. proxy.finishTransition();
  38. }
  39. }, () => {
  40. this.scaleList[from] = 0.5;
  41. this.scaleList[to] = 1.0;
  42. this.opacityList[from] = 0.5;
  43. this.opacityList[to] = 1.0;
  44. });
  45. }
  46. } as TabContentAnimatedTransition;
  47. return tabContentAnimatedTransition;
  48. };
  49. aboutToAppear(): void {
  50. let duration = 1000;
  51. let timeout = 1000;
  52. for (let i = 1; i <= this.data.length; i++) {
  53. this.opacityList.push(1.0);
  54. this.scaleList.push(1.0);
  55. this.durationList.push(duration * i);
  56. this.timeoutList.push(timeout * i);
  57. }
  58. }
  59. build() {
  60. Column() {
  61. Tabs() {
  62. ForEach(this.data, (item: itemType, index: number) => {
  63. TabContent() {}
  64. .tabBar(item.text)
  65. .backgroundColor(item.backgroundColor)
  66. // 自定义动画变化透明度、缩放页面等
  67. .opacity(this.opacityList[index])
  68. .scale({ x: this.scaleList[index], y: this.scaleList[index] })
  69. })
  70. }
  71. .backgroundColor(0xf1f3f5)
  72. .width('100%')
  73. .height(500)
  74. .customContentTransition(this.customContentTransition)
  75. }
  76. }
  77. }

示例9(页面切换拦截)

本示例通过onContentWillChange实现了自定义页面手势滑动切换拦截。

 
  1. //xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. @State selectedIndex: number = 2;
  6. @State currentIndex: number = 2;
  7. private controller: TabsController = new TabsController();
  8. @Builder tabBuilder(title: string,targetIndex: number) {
  9. Column(){
  10. Image(this.selectedIndex === targetIndex ? $r('app.media.star_fill') : $r('app.media.star'))
  11. .width(24)
  12. .height(24)
  13. .margin({ bottom: 4 })
  14. .objectFit(ImageFit.Contain)
  15. Text(title).fontColor(this.selectedIndex === targetIndex ? '#1698CE' : '#6B6B6B')
  16. }.width('100%')
  17. .height(50)
  18. .justifyContent(FlexAlign.Center)
  19. }
  20. build() {
  21. Column() {
  22. Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) {
  23. TabContent() {
  24. Column(){
  25. Text('首页的内容')
  26. }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
  27. }.tabBar(this.tabBuilder('首页',0))
  28. TabContent() {
  29. Column(){
  30. Text('发现的内容')
  31. }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center)
  32. }.tabBar(this.tabBuilder('发现',1))
  33. TabContent() {
  34. Column(){
  35. Text('推荐的内容')
  36. }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center)
  37. }.tabBar(this.tabBuilder('推荐',2))
  38. TabContent() {
  39. Column(){
  40. Text('我的内容')
  41. }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center)
  42. }.tabBar(this.tabBuilder('我的',3))
  43. }
  44. .vertical(false)
  45. .barMode(BarMode.Fixed)
  46. .barWidth(360)
  47. .barHeight(60)
  48. .animationDuration(0)
  49. .onChange((index: number) => {
  50. this.currentIndex = index;
  51. this.selectedIndex = index;
  52. })
  53. .width(360)
  54. .height(600)
  55. .backgroundColor('#F1F3F5')
  56. .scrollable(true)
  57. .onContentWillChange((currentIndex, comingIndex) => {
  58. if (comingIndex == 2) {
  59. return false;
  60. }
  61. return true;
  62. })
  63. Button('动态修改index').width('50%').margin({ top: 20 })
  64. .onClick(()=>{
  65. this.currentIndex = (this.currentIndex + 1) % 4;
  66. })
  67. Button('changeIndex').width('50%').margin({ top: 20 })
  68. .onClick(()=>{
  69. this.currentIndex = (this.currentIndex + 1) % 4;
  70. this.controller.changeIndex(this.currentIndex);
  71. })
  72. }.width('100%')
  73. }
  74. }

示例10(自定义TabBar切换动画)

本示例通过onChange、onAnimationStart、onAnimationEnd、onGestureSwipe等接口实现了自定义TabBar的切换动画。

 
  1. // EntryAbility.ets
  2. import { Configuration, UIAbility } from '@kit.AbilityKit';
  3. import { i18n } from '@kit.LocalizationKit';
  4. import { CommonUtil } from '../common/CommonUtil';
  5. export default class EntryAbility extends UIAbility {
  6. onConfigurationUpdate(newConfig: Configuration): void {
  7. // 监听系统配置变化
  8. if (newConfig.language) {
  9. CommonUtil.setIsRTL(i18n.isRTL(newConfig.language));
  10. }
  11. }
  12. }
 
  1. // CommonUtil.ets
  2. import { i18n, intl } from '@kit.LocalizationKit';
  3. export class CommonUtil {
  4. private static isRTL: boolean = i18n.isRTL((new intl.Locale()).language);
  5. public static setIsRTL(isRTL: boolean): void {
  6. CommonUtil.isRTL = isRTL;
  7. }
  8. public static getIsRTL(): boolean {
  9. return CommonUtil.isRTL;
  10. }
  11. }
 
  1. // xxx.ets
  2. import { LengthMetrics } from '@kit.ArkUI';
  3. import { CommonUtil } from '../common/CommonUtil';
  4. @Entry
  5. @Component
  6. struct TabsExample {
  7. @State colorArray: [string, string][] =
  8. [['green', '#00CB87'], ['blue', '#007DFF'], ['yellow', '#FFBF00'], ['pink', '#E67C92']];
  9. @State currentIndex: number = 0;
  10. @State animationDuration: number = 300;
  11. @State indicatorLeftMargin: number = 0;
  12. @State indicatorWidth: number = 0;
  13. private tabsWidth: number = 0;
  14. private textInfos: [number, number][] = [];
  15. private isStartAnimateTo: boolean = false;
  16. aboutToAppear():void {
  17. for (let i = 0; i < this.colorArray.length; i++) {
  18. this.textInfos.push([0, 0]);
  19. }
  20. }
  21. @Builder
  22. tabBuilder(index: number, name: string) {
  23. Column() {
  24. Text(name)
  25. .fontSize(16)
  26. .fontColor(this.currentIndex === index ? '#007DFF' : '#182431')
  27. .fontWeight(this.currentIndex === index ? 500 : 400)
  28. .id(index.toString())
  29. .onAreaChange((oldValue: Area, newValue: Area) => {
  30. this.textInfos[index] = [newValue.globalPosition.x as number, newValue.width as number];
  31. if (!this.isStartAnimateTo && this.currentIndex === index && this.tabsWidth > 0) {
  32. this.setIndicatorAttr(this.textInfos[this.currentIndex][0], this.textInfos[this.currentIndex][1]);
  33. }
  34. })
  35. }.width('100%')
  36. }
  37. build() {
  38. Stack({ alignContent: Alignment.TopStart }) {
  39. Tabs({ barPosition: BarPosition.Start }) {
  40. ForEach(this.colorArray, (item: [string, string], index:number) => {
  41. TabContent() {
  42. Column().width('100%').height('100%').backgroundColor(item[1])
  43. }.tabBar(this.tabBuilder(index, item[0]))
  44. })
  45. }
  46. .onAreaChange((oldValue: Area, newValue: Area)=> {
  47. this.tabsWidth = newValue.width as number;
  48. if (!this.isStartAnimateTo) {
  49. this.setIndicatorAttr(this.textInfos[this.currentIndex][0], this.textInfos[this.currentIndex][1]);
  50. }
  51. })
  52. .barWidth('100%')
  53. .barHeight(56)
  54. .width('100%')
  55. .height(296)
  56. .backgroundColor('#F1F3F5')
  57. .animationDuration(this.animationDuration)
  58. .onChange((index: number) => {
  59. this.currentIndex = index; // 监听索引index的变化,实现页签内容的切换。
  60. })
  61. .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
  62. // 切换动画开始时触发该回调。下划线跟着页面一起滑动,同时宽度渐变。
  63. this.currentIndex = targetIndex;
  64. this.startAnimateTo(this.animationDuration, this.textInfos[targetIndex][0], this.textInfos[targetIndex][1]);
  65. })
  66. .onAnimationEnd((index: number, event: TabsAnimationEvent) => {
  67. // 切换动画结束时触发该回调。下划线动画停止。
  68. let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event);
  69. this.startAnimateTo(0, currentIndicatorInfo.left, currentIndicatorInfo.width);
  70. })
  71. .onGestureSwipe((index: number, event: TabsAnimationEvent) => {
  72. // 在页面跟手滑动过程中,逐帧触发该回调。
  73. let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event);
  74. this.currentIndex = currentIndicatorInfo.index;
  75. this.setIndicatorAttr(currentIndicatorInfo.left, currentIndicatorInfo.width);
  76. })
  77. Column()
  78. .height(2)
  79. .width(this.indicatorWidth)
  80. .margin({ start: LengthMetrics.vp(this.indicatorLeftMargin), top: LengthMetrics.vp(48) })
  81. .backgroundColor('#007DFF')
  82. }.width('100%')
  83. }
  84. private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
  85. let nextIndex = index;
  86. if (index > 0 && (CommonUtil.getIsRTL() ? event.currentOffset < 0 : event.currentOffset > 0)) {
  87. nextIndex--;
  88. } else if (index < this.textInfos.length - 1 &&
  89. (CommonUtil.getIsRTL() ? event.currentOffset > 0 : event.currentOffset < 0)) {
  90. nextIndex++;
  91. }
  92. let indexInfo = this.textInfos[index];
  93. let nextIndexInfo = this.textInfos[nextIndex];
  94. let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth);
  95. let currentIndex = swipeRatio > 0.5 ? nextIndex : index; // 页面滑动超过一半,tabBar切换到下一页。
  96. let currentLeft = indexInfo[0] + (nextIndexInfo[0] - indexInfo[0]) * swipeRatio;
  97. let currentWidth = indexInfo[1] + (nextIndexInfo[1] - indexInfo[1]) * swipeRatio;
  98. return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth };
  99. }
  100. private startAnimateTo(duration: number, leftMargin: number, width: number) {
  101. this.isStartAnimateTo = true;
  102. this.getUIContext()?.animateTo({
  103. duration: duration, // 动画时长
  104. curve: Curve.Linear, // 动画曲线
  105. iterations: 1, // 播放次数
  106. playMode: PlayMode.Normal, // 动画模式
  107. onFinish: () => {
  108. this.isStartAnimateTo = false;
  109. console.info('play end');
  110. }
  111. }, () => {
  112. this.setIndicatorAttr(leftMargin, width);
  113. });
  114. }
  115. private setIndicatorAttr(leftMargin: number, width: number) {
  116. this.indicatorWidth = width;
  117. if (CommonUtil.getIsRTL()) {
  118. this.indicatorLeftMargin = this.tabsWidth - leftMargin - width;
  119. } else {
  120. this.indicatorLeftMargin = leftMargin;
  121. }
  122. }
  123. }

示例11(预加载子节点)

本示例通过preloadItems接口实现了预加载指定子节点。

 
  1. // xxx.ets
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. @Entry
  4. @Component
  5. struct TabsPreloadItems {
  6. @State currentIndex: number = 1;
  7. private tabsController: TabsController = new TabsController();
  8. build() {
  9. Column() {
  10. Tabs({ index: this.currentIndex, controller: this.tabsController }) {
  11. TabContent() {
  12. MyComponent({ color: '#00CB87' })
  13. }.tabBar(SubTabBarStyle.of('green'))
  14. TabContent() {
  15. MyComponent({ color: '#007DFF' })
  16. }.tabBar(SubTabBarStyle.of('blue'))
  17. TabContent() {
  18. MyComponent({ color: '#FFBF00' })
  19. }.tabBar(SubTabBarStyle.of('yellow'))
  20. TabContent() {
  21. MyComponent({ color: '#E67C92' })
  22. }.tabBar(SubTabBarStyle.of('pink'))
  23. }
  24. .width(360)
  25. .height(296)
  26. .backgroundColor('#F1F3F5')
  27. .onChange((index: number) => {
  28. this.currentIndex = index;
  29. })
  30. Button('preload items: [0, 2, 3]')
  31. .margin(5)
  32. .onClick(() => {
  33. // 预加载第0、2、3个子节点,提高滑动或点击切换至这些节点时的性能
  34. this.tabsController.preloadItems([0, 2, 3])
  35. .then(() => {
  36. console.info('preloadItems success.');
  37. })
  38. .catch((error: BusinessError) => {
  39. console.error('preloadItems failed, error code: ' + error.code + ', error message: ' + error.message);
  40. })
  41. })
  42. }
  43. }
  44. }
  45. @Component
  46. struct MyComponent {
  47. private color: string = '';
  48. aboutToAppear(): void {
  49. console.info('aboutToAppear backgroundColor:' + this.color);
  50. }
  51. aboutToDisappear(): void {
  52. console.info('aboutToDisappear backgroundColor:' + this.color);
  53. }
  54. build() {
  55. Column()
  56. .width('100%')
  57. .height('100%')
  58. .backgroundColor(this.color)
  59. }
  60. }

示例12(设置TabBar平移距离和不透明度)

本示例通过setTabBarTranslate、setTabBarOpacity等接口设置了TabBar的平移距离和不透明度。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. private controller: TabsController = new TabsController();
  6. build() {
  7. Column() {
  8. Button('设置TabBar的平移距离').margin({ top: 20 })
  9. .onClick(() => {
  10. this.controller.setTabBarTranslate({ x: -20, y: -20 });
  11. })
  12. Button('设置TabBar的透明度').margin({ top: 20 })
  13. .onClick(() => {
  14. this.controller.setTabBarOpacity(0.5);
  15. })
  16. Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
  17. TabContent() {
  18. Column().width('100%').height('100%').backgroundColor('#00CB87')
  19. }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'green'))
  20. TabContent() {
  21. Column().width('100%').height('100%').backgroundColor('#007DFF')
  22. }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'blue'))
  23. TabContent() {
  24. Column().width('100%').height('100%').backgroundColor('#FFBF00')
  25. }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'yellow'))
  26. TabContent() {
  27. Column().width('100%').height('100%').backgroundColor('#E67C92')
  28. }.tabBar(BottomTabBarStyle.of($r('app.media.startIcon'), 'pink'))
  29. }
  30. .width(360)
  31. .height(296)
  32. .margin({ top: 20 })
  33. .barBackgroundColor('#F1F3F5')
  34. }
  35. .width('100%')
  36. }
  37. }

示例13(页面懒加载和释放)

本示例通过使用自定义TabBar与Swiper配合LazyForEach实现页面懒加载和释放。

 
  1. // xxx.ets
  2. class MyDataSource implements IDataSource {
  3. private list: number[] = [];
  4. constructor(list: number[]) {
  5. this.list = list;
  6. }
  7. totalCount(): number {
  8. return this.list.length;
  9. }
  10. getData(index: number): number {
  11. return this.list[index];
  12. }
  13. registerDataChangeListener(listener: DataChangeListener): void {
  14. }
  15. unregisterDataChangeListener() {
  16. }
  17. }
  18. @Entry
  19. @Component
  20. struct TabsSwiperExample {
  21. @State fontColor: string = '#182431';
  22. @State selectedFontColor: string = '#007DFF';
  23. @State currentIndex: number = 0;
  24. private list: number[] = [];
  25. private tabsController: TabsController = new TabsController();
  26. private swiperController: SwiperController = new SwiperController();
  27. private swiperData: MyDataSource = new MyDataSource([]);
  28. aboutToAppear(): void {
  29. for (let i = 0; i <= 9; i++) {
  30. this.list.push(i);
  31. }
  32. this.swiperData = new MyDataSource(this.list);
  33. }
  34. @Builder tabBuilder(index: number, name: string) {
  35. Column() {
  36. Text(name)
  37. .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
  38. .fontSize(16)
  39. .fontWeight(this.currentIndex === index ? 500 : 400)
  40. .lineHeight(22)
  41. .margin({ top: 17, bottom: 7 })
  42. Divider()
  43. .strokeWidth(2)
  44. .color('#007DFF')
  45. .opacity(this.currentIndex === index ? 1 : 0)
  46. }.width('20%')
  47. }
  48. build() {
  49. Column() {
  50. Tabs({ barPosition: BarPosition.Start, controller: this.tabsController }) {
  51. ForEach(this.list, (item: number) => {
  52. TabContent().tabBar(this.tabBuilder(item, '页签 ' + this.list[item]))
  53. })
  54. }
  55. .onTabBarClick((index: number) => {
  56. this.currentIndex = index;
  57. this.swiperController.changeIndex(index, true);
  58. })
  59. .barMode(BarMode.Scrollable)
  60. .backgroundColor('#F1F3F5')
  61. .height(56)
  62. .width('100%')
  63. Swiper(this.swiperController) {
  64. LazyForEach(this.swiperData, (item: string) => {
  65. Text(item.toString())
  66. .onAppear(()=>{
  67. console.info('onAppear ' + item.toString());
  68. })
  69. .onDisAppear(()=>{
  70. console.info('onDisAppear ' + item.toString());
  71. })
  72. .width('100%')
  73. .height('100%')
  74. .backgroundColor(0xAFEEEE)
  75. .textAlign(TextAlign.Center)
  76. .fontSize(30)
  77. }, (item: string) => item)
  78. }
  79. .loop(false)
  80. .onChange((index: number) => {
  81. this.currentIndex = index;
  82. })
  83. .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => {
  84. this.currentIndex = targetIndex;
  85. this.tabsController.changeIndex(targetIndex);
  86. })
  87. }
  88. }
  89. }

示例14(设置翻页动效)

本示例通过设置animationMode属性,实现了翻页的动效。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. @State currentIndex: number = 0;
  6. @State currentAnimationMode: AnimationMode = AnimationMode.CONTENT_FIRST;
  7. private controller: TabsController = new TabsController();
  8. private data: number[] = [];
  9. aboutToAppear(): void {
  10. for (let i = 0; i < 10; i++) {
  11. this.data.push(i);
  12. }
  13. }
  14. @Builder
  15. tabBuilder(title: string,targetIndex: number) {
  16. Column(){
  17. Text(title).fontColor(this.currentIndex === targetIndex ? '#FF0000' : '#6B6B6B')
  18. }.width('100%')
  19. .height(50)
  20. .justifyContent(FlexAlign.Center)
  21. }
  22. build() {
  23. Column() {
  24. Tabs({ barPosition: BarPosition.End, controller: this.controller, index: this.currentIndex }) {
  25. ForEach(this.data, (item: string) => {
  26. TabContent() {
  27. Column(){
  28. Text('' + item)
  29. }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
  30. }.tabBar(this.tabBuilder('P' + item, parseInt(item)))
  31. }, (item: string) => item)
  32. }
  33. .barWidth(360)
  34. .barHeight(60)
  35. .animationMode(this.currentAnimationMode)
  36. .animationDuration(4000)
  37. .onChange((index: number) => {
  38. this.currentIndex = index;
  39. })
  40. .width(360)
  41. .height(120)
  42. .backgroundColor('#F1F3F5')
  43. Text('AnimationMode:' + AnimationMode[this.currentAnimationMode])
  44. Button('AnimationMode').width('50%').margin({ top: 1 }).height(25)
  45. .onClick(()=>{
  46. if (this.currentAnimationMode === AnimationMode.CONTENT_FIRST) {
  47. this.currentAnimationMode = AnimationMode.ACTION_FIRST;
  48. } else if (this.currentAnimationMode === AnimationMode.ACTION_FIRST) {
  49. this.currentAnimationMode = AnimationMode.NO_ANIMATION;
  50. } else if (this.currentAnimationMode === AnimationMode.NO_ANIMATION) {
  51. this.currentAnimationMode = AnimationMode.CONTENT_FIRST_WITH_JUMP;
  52. } else if (this.currentAnimationMode === AnimationMode.CONTENT_FIRST_WITH_JUMP) {
  53. this.currentAnimationMode = AnimationMode.ACTION_FIRST_WITH_JUMP;
  54. } else if (this.currentAnimationMode === AnimationMode.ACTION_FIRST_WITH_JUMP) {
  55. this.currentAnimationMode = AnimationMode.CONTENT_FIRST;
  56. }
  57. })
  58. }.width('100%')
  59. }
  60. }

示例15(页签超出TabBar区域显示)

本示例通过使用barModifier设置tabBar的clip属性实现页签超出tabBar区域显示效果。

 
  1. // xxx.ets
  2. import { CommonModifier } from '@kit.ArkUI';
  3. @Entry
  4. @Component
  5. struct TabsBarModifierExample {
  6. @State selectedIndex: number = 2;
  7. @State currentIndex: number = 2;
  8. @State isClip: boolean = false;
  9. @State tabBarModifier: CommonModifier = new CommonModifier();
  10. private controller: TabsController = new TabsController();
  11. aboutToAppear(): void {
  12. this.tabBarModifier.clip(this.isClip);
  13. }
  14. @Builder
  15. tabBuilder(title: string, targetIndex: number) {
  16. Column() {
  17. Image($r('app.media.startIcon')).width(30).height(30)
  18. Text(title).fontColor(this.selectedIndex === targetIndex ? '#1698CE' : '#6B6B6B')
  19. }.width('100%')
  20. .height(50)
  21. .justifyContent(FlexAlign.Center)
  22. .offset({ y: this.selectedIndex === targetIndex ? -15 : 0 })
  23. }
  24. build() {
  25. Column() {
  26. Tabs({
  27. barPosition: BarPosition.End,
  28. index: this.currentIndex,
  29. controller: this.controller,
  30. barModifier: this.tabBarModifier
  31. }) {
  32. TabContent() {
  33. Column() {
  34. Text('首页的内容')
  35. }.width('100%').height('100%').backgroundColor('#00CB87').justifyContent(FlexAlign.Center)
  36. }.tabBar(this.tabBuilder('首页', 0))
  37. TabContent() {
  38. Column() {
  39. Text('发现的内容')
  40. }.width('100%').height('100%').backgroundColor('#007DFF').justifyContent(FlexAlign.Center)
  41. }.tabBar(this.tabBuilder('发现', 1))
  42. TabContent() {
  43. Column() {
  44. Text('推荐的内容')
  45. }.width('100%').height('100%').backgroundColor('#FFBF00').justifyContent(FlexAlign.Center)
  46. }.tabBar(this.tabBuilder('推荐', 2))
  47. TabContent() {
  48. Column() {
  49. Text('我的内容')
  50. }.width('100%').height('100%').backgroundColor('#E67C92').justifyContent(FlexAlign.Center)
  51. }.tabBar(this.tabBuilder('我的', 3))
  52. }
  53. .vertical(false)
  54. .barMode(BarMode.Fixed)
  55. .barWidth(340)
  56. .barHeight(60)
  57. .onChange((index: number) => {
  58. this.currentIndex = index;
  59. this.selectedIndex = index;
  60. })
  61. .width(340)
  62. .height(400)
  63. .backgroundColor('#F1F3F5')
  64. .scrollable(true)
  65. Button('isClip: ' + this.isClip)
  66. .margin({ top: 30 })
  67. .onClick(() => {
  68. this.isClip = !this.isClip;
  69. this.tabBarModifier.clip(this.isClip);
  70. })
  71. }.width('100%')
  72. }
  73. }

示例16(页签对齐布局)

本示例通过使用barModifier设置tabBar的align属性实现页签对齐布局效果。

 
  1. // xxx.ets
  2. import { CommonModifier } from '@kit.ArkUI';
  3. @Entry
  4. @Component
  5. struct TabsBarModifierExample {
  6. private controller: TabsController = new TabsController();
  7. @State text: string = '文本';
  8. @State isVertical: boolean = false;
  9. @State tabBarModifier: CommonModifier = new CommonModifier();
  10. build() {
  11. Column() {
  12. Row() {
  13. Button('Alignment.Start ')
  14. .width('47%')
  15. .height(50)
  16. .margin({ top: 5 })
  17. .onClick((event?: ClickEvent) => {
  18. this.tabBarModifier.align(Alignment.Start);
  19. })
  20. .margin({ right: '6%', bottom: '12vp' })
  21. Button('Alignment.End')
  22. .width('47%')
  23. .height(50)
  24. .margin({ top: 5 })
  25. .onClick((event?: ClickEvent) => {
  26. this.tabBarModifier.align(Alignment.End);
  27. })
  28. .margin({ bottom: '12vp' })
  29. }
  30. Row() {
  31. Button('Alignment.Center')
  32. .width('47%')
  33. .height(50)
  34. .margin({ top: 5 })
  35. .onClick((event?: ClickEvent) => {
  36. this.tabBarModifier.align(Alignment.Center);
  37. })
  38. .margin({ right: '6%', bottom: '12vp' })
  39. Button('isVertical: ' + this.isVertical)
  40. .width('47%')
  41. .height(50)
  42. .margin({ top: 5 })
  43. .onClick((event?: ClickEvent) => {
  44. this.isVertical = !this.isVertical;
  45. })
  46. .margin({ bottom: '12vp' })
  47. }
  48. Row() {
  49. Button('Alignment.Top')
  50. .width('47%')
  51. .height(50)
  52. .margin({ top: 5 })
  53. .onClick((event?: ClickEvent) => {
  54. this.tabBarModifier.align(Alignment.Top);
  55. })
  56. .margin({ right: '6%', bottom: '12vp' })
  57. Button('Alignment.Bottom')
  58. .width('47%')
  59. .height(50)
  60. .margin({ top: 5 })
  61. .onClick((event?: ClickEvent) => {
  62. this.tabBarModifier.align(Alignment.Bottom);
  63. })
  64. .margin({ bottom: '12vp' })
  65. }
  66. Tabs({ barPosition: BarPosition.End, controller: this.controller, barModifier: this.tabBarModifier }) {
  67. TabContent() {
  68. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  69. }.tabBar(SubTabBarStyle.of(this.text))
  70. TabContent() {
  71. Column().width('100%').height('100%').backgroundColor(Color.Green)
  72. }.tabBar(SubTabBarStyle.of(this.text))
  73. TabContent() {
  74. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  75. }.tabBar(SubTabBarStyle.of(this.text))
  76. }
  77. .vertical(this.isVertical)
  78. .height('60%')
  79. .backgroundColor(0xf1f3f5)
  80. .barMode(BarMode.Scrollable)
  81. }
  82. .width('100%')
  83. .height(500)
  84. .margin({ top: 5 })
  85. .padding('24vp')
  86. }
  87. }

示例17(Tabs与TabBar联动切换)

该示例通过onSelected接口,实现了Tabs与TabBar联动切换。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. @State fontColor: string = '#182431';
  6. @State selectedFontColor: string = '#007DFF';
  7. @State currentIndex: number = 0;
  8. @State selectedIndex: number = 0;
  9. private controller: TabsController = new TabsController();
  10. @Builder tabBuilder(index: number, name: string) {
  11. Column() {
  12. Text(name)
  13. .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
  14. .fontSize(16)
  15. .fontWeight(this.selectedIndex === index ? 500 : 400)
  16. .lineHeight(22)
  17. .margin({ top: 17, bottom: 7 })
  18. Divider()
  19. .strokeWidth(2)
  20. .color('#007DFF')
  21. .opacity(this.selectedIndex === index ? 1 : 0)
  22. }.width('100%')
  23. }
  24. build() {
  25. Column() {
  26. Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
  27. TabContent() {
  28. Column().width('100%').height('100%').backgroundColor('#00CB87')
  29. }.tabBar(this.tabBuilder(0, 'green'))
  30. TabContent() {
  31. Column().width('100%').height('100%').backgroundColor('#007DFF')
  32. }.tabBar(this.tabBuilder(1, 'blue'))
  33. TabContent() {
  34. Column().width('100%').height('100%').backgroundColor('#FFBF00')
  35. }.tabBar(this.tabBuilder(2, 'yellow'))
  36. TabContent() {
  37. Column().width('100%').height('100%').backgroundColor('#E67C92')
  38. }.tabBar(this.tabBuilder(3, 'pink'))
  39. }
  40. .vertical(false)
  41. .barMode(BarMode.Fixed)
  42. .barWidth(360)
  43. .barHeight(56)
  44. .animationDuration(400)
  45. .animationMode(AnimationMode.CONTENT_FIRST)
  46. .onChange((index: number) => {
  47. console.log('onChange index:' + index);
  48. this.currentIndex = index;
  49. })
  50. .onSelected((index: number) => {
  51. console.log('onSelected index:' + index);
  52. this.selectedIndex = index;
  53. })
  54. .onUnselected((index: number) => {
  55. console.log('onUnselected index:' + index);
  56. })
  57. .width('100%')
  58. .height('100%')
  59. .backgroundColor('#F1F3F5')
  60. }.width('100%')
  61. }
  62. }

示例18(释放Tabs子组件)

该示例通过设置cachedMaxCount属性,实现了Tabs子组件的释放。

 
  1. @Entry
  2. @Component
  3. struct TabsExample {
  4. build() {
  5. Tabs() {
  6. TabContent() {
  7. MyComponent({ color: '#00CB87' })
  8. }.tabBar(SubTabBarStyle.of('green'))
  9. TabContent() {
  10. MyComponent({ color: '#007DFF' })
  11. }.tabBar(SubTabBarStyle.of('blue'))
  12. TabContent() {
  13. MyComponent({ color: '#FFBF00' })
  14. }.tabBar(SubTabBarStyle.of('yellow'))
  15. TabContent() {
  16. MyComponent({ color: '#E67C92' })
  17. }.tabBar(SubTabBarStyle.of('pink'))
  18. }
  19. .width(360)
  20. .height(296)
  21. .backgroundColor('#F1F3F5')
  22. .cachedMaxCount(1, TabsCacheMode.CACHE_BOTH_SIDE)
  23. }
  24. }
  25. @Component
  26. struct MyComponent {
  27. private color: string = '';
  28. aboutToAppear(): void {
  29. console.info('aboutToAppear backgroundColor:' + this.color);
  30. }
  31. aboutToDisappear(): void {
  32. console.info('aboutToDisappear backgroundColor:' + this.color);
  33. }
  34. build() {
  35. Column()
  36. .width('100%')
  37. .height('100%')
  38. .backgroundColor(this.color)
  39. }
  40. }

示例19(设置TabBar背景模糊效果)

该示例分别通过barBackgroundBlurStyle和barBackgroundEffect设置TabsBar页签栏的背景模糊效果。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. build() {
  6. Column() {
  7. // barBackgroundBlurStyle 可以通过枚举值的方式设置模糊参数
  8. Stack() {
  9. Image($r('app.media.startIcon'))
  10. Tabs() {
  11. TabContent() {
  12. Column().width('100%').height('100%').backgroundColor('#00CB87')
  13. }.tabBar('green')
  14. TabContent() {
  15. Column().width('100%').height('100%').backgroundColor('#007DFF')
  16. }.tabBar('blue')
  17. TabContent() {
  18. Column().width('100%').height('100%').backgroundColor('#FFBF00')
  19. }.tabBar('yellow')
  20. TabContent() {
  21. Column().width('100%').height('100%').backgroundColor('#E67C92')
  22. }.tabBar('pink')
  23. }
  24. .barBackgroundBlurStyle(BlurStyle.COMPONENT_THICK,
  25. { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 })
  26. }
  27. .width(300)
  28. .height(300)
  29. .margin(10)
  30. // barBackgroundEffect 可以自定义设置tabBar页签栏的模糊半径、亮度、饱和度等参数
  31. Stack() {
  32. Image($r('app.media.startIcon'))
  33. Tabs() {
  34. TabContent() {
  35. Column().width('100%').height('100%').backgroundColor('#00CB87')
  36. }.tabBar('green')
  37. TabContent() {
  38. Column().width('100%').height('100%').backgroundColor('#007DFF')
  39. }.tabBar('blue')
  40. TabContent() {
  41. Column().width('100%').height('100%').backgroundColor('#FFBF00')
  42. }.tabBar('yellow')
  43. TabContent() {
  44. Column().width('100%').height('100%').backgroundColor('#E67C92')
  45. }.tabBar('pink')
  46. }
  47. .barBackgroundEffect({ radius: 20, brightness: 0.6, saturation: 15 })
  48. }
  49. .width(300)
  50. .height(300)
  51. .margin(10)
  52. }
  53. }
  54. }

示例20(设置边缘滑动效果)

该示例通过edgeEffect实现不同边缘滑动效果。

 
  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct TabsExample {
  5. @State edgeEffect: EdgeEffect = EdgeEffect.Spring;
  6. build() {
  7. Column() {
  8. Tabs() {
  9. TabContent() {
  10. Column().width('100%').height('100%').backgroundColor('#00CB87')
  11. }.tabBar('green')
  12. TabContent() {
  13. Column().width('100%').height('100%').backgroundColor('#007DFF')
  14. }.tabBar('blue')
  15. TabContent() {
  16. Column().width('100%').height('100%').backgroundColor('#FFBF00')
  17. }.tabBar('yellow')
  18. TabContent() {
  19. Column().width('100%').height('100%').backgroundColor('#E67C92')
  20. }.tabBar('pink')
  21. }
  22. .width(360)
  23. .height(296)
  24. .margin({ top: 52 })
  25. .backgroundColor('#F1F3F5')
  26. .edgeEffect(this.edgeEffect)
  27. Button('EdgeEffect.Spring').width('50%').margin({ top: 20 })
  28. .onClick(() => {
  29. this.edgeEffect = EdgeEffect.Spring;
  30. })
  31. Button('EdgeEffect.Fade').width('50%').margin({ top: 20 })
  32. .onClick(() => {
  33. this.edgeEffect = EdgeEffect.Fade;
  34. })
  35. Button('EdgeEffect.None').width('50%').margin({ top: 20 })
  36. .onClick(() => {
  37. this.edgeEffect = EdgeEffect.None;
  38. })
  39. }.width('100%')
  40. }
  41. }

示例21(Tabs设置翻页动画曲线)

该示例展示了如何通过animationCurve接口设置Tabs翻页动画曲线,并结合animationDuration设置翻页动画的时长。

 
  1. import { curves } from '@kit.ArkUI';
  2. interface TabsItemType { text: string, backgroundColor: ResourceColor }
  3. @Entry
  4. @Component
  5. struct TabsExample {
  6. private tabsController: TabsController = new TabsController();
  7. private curves: (Curve | ICurve) [] = [
  8. curves.interpolatingSpring(-1, 1, 328, 34),
  9. curves.springCurve(10, 1, 228, 30),
  10. curves.cubicBezierCurve(0.25, 0.1, 0.25, 1.0),
  11. ];
  12. @State curveIndex: number = 0;
  13. private datas: TabsItemType[] = [
  14. { text: '1', backgroundColor: '#004AAF' },
  15. { text: '2', backgroundColor: '#2787D9' },
  16. { text: '3', backgroundColor: '#D5D5D5' },
  17. { text: '4', backgroundColor: '#707070' },
  18. { text: '5', backgroundColor: '#F7F7F7' },
  19. ];
  20. @State duration: number = 0;
  21. build() {
  22. Column({ space:2 }) {
  23. Tabs({ controller: this.tabsController }) {
  24. ForEach(this.datas, (item: TabsItemType, index: number) => {
  25. TabContent() {}
  26. .tabBar(item.text)
  27. .backgroundColor(item.backgroundColor)
  28. })
  29. }
  30. .backgroundColor(0xf1f3f5)
  31. .width('100%')
  32. .height(500)
  33. .animationCurve(this.curves[this.curveIndex])
  34. .animationDuration(this.duration)
  35. Row({ space:2 }) {
  36. Text('Curve:' + this.curveIndex)
  37. Button('++').onClick(() => { this.curveIndex = (this.curveIndex + 1) % this.curves.length; })
  38. Button('reset').onClick(() => { this.curveIndex = 0; })
  39. }
  40. .margin({ left: '10vp' })
  41. .width('100%')
  42. Row({ space:2 }) {
  43. Text('Duration:' + this.duration)
  44. Button('+100').onClick(() => { this.duration = (this.duration + 100) % 10000; })
  45. Button('+1000').onClick(() => { this.duration = (this.duration + 1000) % 10000; })
  46. Button('reset').onClick(() => { this.duration = 0; })
  47. }
  48. .margin({ left: '10vp' })
  49. .width('100%')
  50. }
  51. .margin('10vp')
  52. }
  53. }

http://www.lqws.cn/news/513649.html

相关文章:

  • ASR1606 LTE Cat.1 与 MK SD NAND–––T-BOX 智能基座的通信存储双擎
  • x86-64安装编译Apollo 9.0 aarch64版本
  • ZArchiver×亚矩云手机:云端文件管理的“超维解压”革命
  • B树和B+树的区别
  • SpringBoot项目快速开发框架JeecgBoot——数据访问!
  • 从零开始的云计算生活——第二十三天,稍作休息,Tomcat
  • pycharm基础操作备忘记录
  • 国芯思辰|同步降压转换器CN2020A替换LMR33620应用于分布式电源系统
  • Jenkins X + AI:重塑云原生时代的持续交付范式
  • Docker部署Flask应用
  • Android14音频子系统-Linux音频子系统ALSA
  • 微信小程序 / UNIAPP --- 阻止小程序返回(顶部导航栏返回、左 / 右滑手势、安卓物理返回键和调用 navigateBack 接口)
  • 服务器性能优化通用方案
  • 文档处理控件Aspose.Words教程:在.NET中将多页文档转换为单个图像
  • 【开源解析】基于PyQt5的智能费用报销管理系统开发全解:附完整源码
  • Golang单例实现
  • LVS-NAT负载均衡群集实战:原理、部署与问题排查
  • 小程序快速获取url link方法,短信里面快速打开链接
  • Spark Streaming 与 Flink 实时数据处理方案对比与选型指南
  • Flink2.0 配置 historyserver
  • 15个AI模拟面试平台 和 简历修改 / 真人面试平台
  • 云计算产业链
  • 用wordpress建日语外贸网站的优势
  • C# Avalonia 绑定模式 Mode 的区别,它们的应用场景
  • spring中的@Cacheable缓存
  • MicroPython网络编程:AP模式与STA模式详解
  • 【笔记——李沐动手学深度学习】2.3 线性代数
  • 【Python练习】012. 使用字符串的upper()方法将字符串转换为大写
  • 基于开源AI大模型、AI智能名片与S2B2C商城小程序的美食菜单社交化营销创新研究
  • 音频转换芯片DP7344兼容CS4344双通道24位DA转换器技术资料