今天我们来看看Tabs这个组件
ArkTs中的Tabs组件我认为和android里的TabLayout的使用场景大体是相同的,但是其子组件和方法属性这些必然是不一样的。
下面我们来看看官方的说明(可以简单看下,如果觉得繁琐可以直接看最后的实例):
简介
通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。
仅可包含子组件TabContent。
接口
Tabs(value?: {barPosition?: BarPosition, index?: number, controller?: TabsController})
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
barPosition | BarPosition | 否 | 设置Tabs的页签位置。默认值:BarPosition.Start |
index | number | 否 | 设置当前显示页签的索引。默认值:0 说明: 设置为小于0的值时按默认值显示。可选值为[0, TabContent子节点数量-1]。设置不同值时,默认生效切换动效,可以设置animationDuration为0关闭动画。 |
controller | TabsController | 否 | 设置Tabs控制器。 |
BarPosition枚举说明
名称 | 描述 |
---|---|
Start | vertical属性方法设置为true时,页签位于容器左侧;vertical属性方法设置为false时,页签位于容器顶部。 |
End | vertical属性方法设置为true时,页签位于容器右侧;vertical属性方法设置为false时,页签位于容器底部。 |
属性
除支持通用属性外,还支持以下属性:
名称 | 参数类型 | 描述 |
---|---|---|
vertical | boolean | 设置为false是为横向Tabs,设置为true时为纵向Tabs。默认值:false |
scrollable | boolean | 设置为true时可以通过滑动页面进行页面切换,为false时不可滑动切换页面。默认值:true |
barMode | BarMode | TabBar布局模式,具体描述见BarMode枚举说明。默认值:BarMode.Fixed |
barWidth | number / Length8+ | TabBar的宽度值。默认值:未设置带样式的TabBar且vertical属性为false时,默认值为Tabs的宽度。未设置带样式的TabBar且vertical属性为true时,默认值为56vp。设置SubTabbarStyle样式且vertical属性为false时,默认值为Tabs的宽度。设置SubTabbarStyle样式且vertical属性为true时,默认值为56vp。设置BottomTabbarStyle样式且vertical属性为true时,默认值为96vp。设置BottomTabbarStyle样式且vertical属性为false时,默认值为Tabs的宽度。 说明: 设置为小于0或大于Tabs宽度值时,按默认值显示。 |
barHeight | number / Length8+ | 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。 说明: 设置为小于0或大于Tabs高度值时,按默认值显示。 |
animationDuration | number | 点击TabBar页签切换TabContent的动画时长。不设置时,点击TabBar页签切换TabContent无动画。默认值:300 说明: 该参数不支持百分比设置;设置为小于0时,按默认值300ms显示。 |
BarMode枚举说明
名称 | 描述 |
---|---|
Scrollable | 每一个TabBar均使用实际布局宽度,超过总长度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。 |
Fixed | 所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度)。 |
事件
除支持通用事件外,还支持以下事件:
名称 | 功能描述 |
---|---|
onChange(event: (index: number) => void) | Tab页签切换后触发的事件。- index:当前显示的index索引,索引从0开始计算。触发该事件的条件:1、TabContent支持滑动时,组件触发滑动时触发。2、通过控制器API接口调用。3、通过状态变量构造的属性值进行修改。4、通过页签处点击触发。 |
TabsController
Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。
导入对象
ini
controller: TabsController = new TabsController()
changeIndex
php
changeIndex(value: number): void
控制Tabs切换到指定页签。
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
value | number | 是 | 页签在Tabs里的索引值,索引值从0开始。 说明: 设置小于0或大于最大数量的值时,该事件失效。 |
实例
可以看到官方文档很详细的说明了其中的属性等信息
下面我会放一个实例这个实例场景就是一个app首页的切换。
由图可以看出这里有两个页面色卡以及色库,点击下方对应的按钮切换到相关页面时按钮的图片和文字颜色也变化。
两个页面分别是Card和Library,页面的编写我这里就不进行说明,图中的效果是使用Stack组件实现的,想了解具体信息可以看我前面的文章。
首先我们先将两个页面导入:
javascript
import { CardPage as Card } from '../pages/CardPage';
import { ColorLibraryPage as Library} from '../pages/ColorLibrary'
然后我们进行初始化相关:
less
@State @Watch('onIndexChange') bottomTabIndex: number = 0;
private controller: TabsController = new TabsController();
其中Watch很重要,简单来说 @Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用
然后是最主要的两个,一个是Tabs的代码另一个是TabBuilder
我们先写tabBar的样式,也就是TabBuilder
css
@Builder TabBuilder(index: number, _name: string){
Column(){
Image(this.bottomTabIndex === index ? BottomTabsList[index].iconSelected : BottomTabsList[index].icon)
.width('40%')
.height('40%')
.objectFit(ImageFit.Contain)
Text(BottomTabsList[index].text)
.fontSize('13fp')
.opacity(0.6)
.fontColor(this.bottomTabIndex === index ? '#d81e06' : '#000000')
}
}
两个参数一个是index一个是tab按钮的文字,Ui部分其中图片在上文字在下,根据判断bottomTabIndex是否等于index来判断图片以及文字的颜色。
然后是Tabs
scss
Tabs({ barPosition: BarPosition.End, index: 0, controller: this.controller }) {
TabContent() {
Card()
}.tabBar(this.TabBuilder(0, '色卡'))
TabContent() {
Library()
}.tabBar(this.TabBuilder(1, '色库'))
}
.width('100%')
.height('100%')
.vertical(false)
.scrollable(false)
.barHeight('10%')
.onChange((index: number) => {
this.bottomTabIndex = index;
})
可以看到子组件只能是TabContent,然后在onChange中监听index并附值给bottonTabIndex。
下面是完整代码:
scss
import { BottomTabsList } from '../viewmodel/BottomTabsModel';
import { CardPage as Card } from '../pages/CardPage';
import { ColorLibraryPage as Library} from '../pages/ColorLibrary'
@Entry
@Component
struct Index {
@State @Watch('onIndexChange') bottomTabIndex: number = 0;
private controller: TabsController = new TabsController();
onIndexChange(){
this.controller.changeIndex(this.bottomTabIndex);
}
@Builder TabBuilder(index: number, _name: string){
Column(){
Image(this.bottomTabIndex === index ? BottomTabsList[index].iconSelected : BottomTabsList[index].icon)
.width('40%')
.height('40%')
.objectFit(ImageFit.Contain)
Text(BottomTabsList[index].text)
.fontSize('13fp')
.opacity(0.6)
.fontColor(this.bottomTabIndex === index ? '#d81e06' : '#000000')
}
}
pageTransition() {
PageTransitionEnter({ duration: 800 })
.slide(SlideEffect.Top)
PageTransitionExit({ delay: 100 })
.opacity(0)
}
build() {
Tabs({ barPosition: BarPosition.End, index: 0, controller: this.controller }) {
TabContent() {
Card()
}.tabBar(this.TabBuilder(0, '色卡'))
TabContent() {
Library()
}.tabBar(this.TabBuilder(1, '色库'))
}
.width('100%')
.height('100%')
.vertical(false)
.scrollable(false)
.barHeight('10%')
.onChange((index: number) => {
this.bottomTabIndex = index;
})
}
}
感谢大家阅读,如有错误欢迎指出,共同进步