自定义Tabs组件————Bond! 超级无敌具详细,你就看吧烙铁!!! 原创
1. 概述
组件名称: Tabs
描述:
Tabs组件用于在不同的页面或内容块之间进行切换,通常用于底部导航栏或顶部标签栏。它提供了一种直观且用户友好的方式来管理多个相关页面或内容,使得应用界面更加清晰和易于操作。
主要功能:
页面切换: 允许用户在多个相关页面或内容块之间进行快速切换。
自定义动画效果: 支持自定义内容切换时的动画效果,如透明度变化、缩放等,提供更加丰富的视觉体验。
事件监听: 提供事件监听机制(如页面显示、动画开始等),帮助开发者在特定事件发生时执行自定义逻辑。
可配置性: 支持多种配置选项,如标签栏的位置、模式、大小、颜色等,使开发者可以根据应用需求进行灵活定制。
通过使用Tabs组件,开发者可以轻松实现复杂的应用导航结构,并提供一致且易于使用的用户界面。
页面切换。
自定义动画效果。
事件监听(如页面显示、动画开始等)。
2. 使用场景
Tabs组件在多种应用场景中都非常有用,特别是在需要在多个相关页面或内容块之间进行快速切换的情况下。以下是一些典型的使用场景:
2.1 社交媒体应用
底部导航栏: 用于在“首页”、“发现”、“消息”和“个人中心”之间切换。
示例: 用户可以在底部导航栏中点击不同的图标来查看不同的内容。
2.2 电商平台
顶部标签栏: 用于在“首页”、“分类”、“购物车”和“我的”之间切换。
示例: 用户可以在顶部标签栏中选择不同的分类来浏览商品。
2.3 新闻客户端
底部导航栏: 用于在“头条”、“热点”、“本地”和“我的”之间切换。
示例: 用户可以在底部导航栏中点击不同的标签来查看不同类别的新闻。
2.4 个人管理应用
底部导航栏: 用于在“计划”、“任务”、“日程”和“个人资料”之间切换。
示例: 用户可以在底部导航栏中选择不同的标签来管理个人计划和任务。
2.5 多功能工具应用
顶部标签栏: 用于在“工具A”、“工具B”、“工具C”和“设置”之间切换。
示例: 用户可以在顶部导航栏中选择不同的工具来执行特定的功能。
2.6 音乐播放器
底部导航栏: 用于在“播放列表”、“搜索”、“发现”和“我的音乐”之间切换。
2.7 地图应用
顶部标签栏: 用于在“地图”、“导航”、“搜索”和“设置”之间切换。
通过使用Tabs组件,开发者可以为用户提供一种直观且易于操作的导航方式,使得应用界面更加清晰和易于管理。这些场景展示了Tabs组件在不同类型的移动应用中的广泛应用。
3. API说明
3.1 属性:
barPosition: 标签栏的位置,支持BarPosition.Start、BarPosition.End、BarPosition.Top、BarPosition.Bottom。
index: 当前选中的标签页索引。
controller: 控制标签页的控制器。
vertical: 是否垂直排列标签页,默认为false。
barMode: 标签栏的模式,支持BarMode.Fixed、BarMode.Scrollable。
barWidth: 标签栏的宽度。
barHeight: 标签栏的高度。
animationMode: 动画模式,支持AnimationMode.NoAnimation、AnimationMode.BasicAnimation等。
animationDuration: 动画的持续时间。
barBackgroundColor: 标签栏的背景颜色。
3.2 事件:
onChange: 当标签页切换时触发。
onAnimationStart: 当标签页动画开始时触发。
3.3 方法:
TabContent: 用于定义每个标签页的内容。
tabBar: 用于定义标签栏的样式。
customContentTransition: 自定义内容切换的动画效果。
3.4 接口
interface itemType {
text: string,
backgroundColor: Color
}
3.5 类
class TabsController {
setCurrentIndex(index: number): void;
}
3.6 动画配置
TabContentAnimatedTransition
interface TabContentAnimatedTransition {
timeout: number,
transition: (proxy: TabContentTransitionProxy) => void
}
TabContentTransitionProxy
interface TabContentTransitionProxy {
finishTransition(): void;
}
3.7 示例
@Entry
@Component
struct TabsExample {
@State currentIndex: number = 0
@State selectedIndex: number = 0
private controller: TabsController = new TabsController()
@Builder tabBuilder(index: number, name: string, selectIcon: Resource, border_radius_left: number, border_radius_right: number) {
Column() {
Column() {
Image(selectIcon)
.width(28)
.height(26)
.fillColor(this.selectedIndex === index ? $r('app.color.font_color') : '#9C9C9C')
Text(name)
.fontSize(16)
.fontColor(this.currentIndex === index ? $r('app.color.font_color') : "#9C9C9C")
}.width('100%').height('80%')
}.width('100%').height('80%')
.backgroundColor($r('app.color.select_menu_background'))
.borderRadius({topLeft: border_radius_left, topRight: border_radius_right, bottomLeft: border_radius_left, bottomRight: border_radius_right})
.margin({left: border_radius_left, right: border_radius_right, bottom: '10%'})
}
@State opacityList: number[] = []
@State scaleList: number[] = []
private durationList: number[] = []
private timeoutList: number[] = []
private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => {
let tabContentAnimatedTransition = {
timeout: this.timeoutList[from],
transition: (proxy: TabContentTransitionProxy) => {
this.scaleList[from] = 1.0
this.scaleList[to] = 0.5
this.opacityList[from] = 1.0
this.opacityList[to] = 0.5
animateTo({
duration: this.durationList[from],
onFinish: () => {
proxy.finishTransition()
}
}, () => {
this.scaleList[from] = 0.5
this.scaleList[to] = 1.0
this.opacityList[from] = 0.5
this.opacityList[to] = 1.0
})
}
} as TabContentAnimatedTransition
return tabContentAnimatedTransition
}
aboutToAppear(): void {
let duration = 250
let timeout = 250
for (let i = 1; i <= this.data.length; i++) {
this.opacityList.push(1.0)
this.scaleList.push(1.0)
this.durationList.push(duration)
this.timeoutList.push(timeout)
}
}
build() {
Row() {
Column() {
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) {
TabContent() {
Index().width('100%').height('100%')
}.tabBar(this.tabBuilder(0, '探索', $r('app.media.ball'), 25, 0))
.opacity(this.opacityList[0])
.scale({ x: this.scaleList[0], y: this.scaleList[0] })
TabContent() {
Plan().width('100%').height('100%')
}.tabBar(this.tabBuilder(1, '规划', $r('app.media.signSvg'), 0, 0))
.opacity(this.opacityList[1])
.scale({ x: this.scaleList[1], y: this.scaleList[1] })
TabContent() {
MyPage().width('100%').height('100%')
}.tabBar(this.tabBuilder(2, '我的', $r('app.media.chat'), 0, 25))
.opacity(this.opacityList[2])
.scale({ x: this.scaleList[2], y: this.scaleList[2] })
}
.customContentTransition(this.customContentTransition)
.animationMode(AnimationMode.NO_ANIMATION)
.barBackgroundColor($r('app.color.background_color'))
.vertical(false)
.barMode(BarMode.Fixed)
.barWidth("88%")
.barHeight(56)
.animationDuration(200)
.onChange((index: number) => {
this.currentIndex = index
this.selectedIndex = index
})
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
if (index === targetIndex) {
return
}
this.selectedIndex = targetIndex
})
.height('100%')
.width('100%')
}
.width('100%')
.height('100%')
.borderRadius(10)
}
.backgroundColor($r('app.color.background_color'))
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
}
4. 详细说明
提供一些简单的示例代码,展示如何使用Tabs组件。
可以包括一个基础的使用示例,以及一个自定义动画效果的示例。
4.1 属性详细说明
barPosition: 标签栏的位置,可选值为BarPosition.Start、BarPosition.End、BarPosition.Top、BarPosition.Bottom。
示例:
Tabs({ barPosition: BarPosition.End })
index: 当前选中的标签页索引,初始值为0。
示例:
Tabs({ index: this.currentIndex })
controller: 控制标签页的控制器,可以通过该控制器进行程序化控制。
示例:
Tabs({ controller: this.controller })
vertical: 是否垂直排列标签页,默认为false,即水平排列。
示例:
Tabs({ vertical: false })
barMode: 标签栏的模式,可选值为BarMode.Fixed、BarMode.Scrollable。
示例:
Tabs({ barMode: BarMode.Fixed })
barWidth: 标签栏的宽度,默认为"100%"。
示例:
Tabs({ barWidth: "88%" })
barHeight: 标签栏的高度,默认为48。
示例:
Tabs({ barHeight: 56 })
barHeight: 标签栏的高度,默认为48。
示例:
Tabs({ barHeight: 56 })
animationMode: 动画模式,可选值为AnimationMode.NO_ANIMATION、AnimationMode.BASIC_ANIMATION。
示例:
Tabs({ animationMode: AnimationMode.NO_ANIMATION })
animationDuration: 动画的持续时间(单位:毫秒),默认为200。
示例:
Tabs({ animationDuration: 200 })
barBackgroundColor: 标签栏的背景颜色,默认为#FFFFFF。
示例:
Tabs({ barBackgroundColor: $r('app.color.background_color') })
4.2 事件详细说明
onChange: 当标签页切换时触发。
参数: index(新选中的标签页索引)。
示例:
.onChange((index: number) => {
this.currentIndex = index;
this.selectedIndex = index;
})
onAnimationStart: 当标签页动画开始时触发。
参数: index(当前标签页索引),targetIndex(目标标签页索引),event(动画事件对象)。
示例:
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
if (index === targetIndex) {
return;
}
this.selectedIndex = targetIndex;
})
4.3 方法详细说明
TabContent: 定义每个标签页的内容。
示例
TabContent() {
Index().width('100%').height('100%')
}
tabBar: 定义标签栏的样式,包括图片、文字、颜色等。
参数:
index(标签页索引)。
name(标签页名称)。
selectIcon(选中时的图标资源)。
border_radius_left(左上角和左下角的圆角半径)。
border_radius_right(右上角和右下角的圆角半径)。
示例:
.tabBar(this.tabBuilder(0, '探索', $r('app.media.ball'), 25, 0))
customContentTransition: 自定义内容切换时的动画效果。
参数:
from(当前标签页索引)。
to(目标标签页索引)。
返回值: TabContentAnimatedTransition对象。
示例:
private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => {
let tabContentAnimatedTransition = {
timeout: this.timeoutList[from],
transition: (proxy: TabContentTransitionProxy) => {
this.scaleList[from] = 1.0
this.scaleList[to] = 0.5
this.opacityList[from] = 1.0
this.opacityList[to] = 0.5
animateTo({
duration: this.durationList[from],
onFinish: () => {
proxy.finishTransition()
}
}, () => {
this.scaleList[from] = 0.5
this.scaleList[to] = 1.0
this.opacityList[from] = 0.5
this.opacityList[to] = 1.0
})
}
} as TabContentAnimatedTransition
return tabContentAnimatedTransition
}
4.4 接口详细说明
interface itemType {
text: string,
backgroundColor: Color
}
4.5 类详细说明
class TabsController {
setCurrentIndex(index: number): void;
}
4.6 动画配置详细说明
TabContentAnimatedTransition
interface TabContentAnimatedTransition {
timeout: number,
transition: (proxy: TabContentTransitionProxy) => void
}
TabContentTransitionProxy
interface TabContentTransitionProxy {
finishTransition(): void;
}
5. 自定义配置
Tabs组件提供了丰富的自定义选项,使开发者可以根据应用需求调整标签栏的样式和动画效果。以下是具体的自定义配置说明:
5.1 自定义标签栏样式
通过tabBar方法,可以自定义每个标签项的样式,包括图标、文字和颜色。
5.1.1 tabBar 方法
tabBar方法用于定义标签栏的样式。该方法接受多个参数,用于配置标签项的外观。
TabBar样式:
可以通过tabBar方法自定义每个标签页的样式,包括图片、文字、颜色等。
动画效果:
如何通过customContentTransition方法实现自定义的动画效果,包括透明度变化、缩放等。
5.1.2 示例
@Builder tabBuilder(index: number, name: string, selectIcon: Resource, border_radius_left: number, border_radius_right: number) {
Column() {
Column() {
Image(selectIcon)
.width(28)
.height(26)
.fillColor(this.selectedIndex === index ? $r('app.color.font_color') : '#9C9C9C')
Text(name)
.fontSize(16)
.fontColor(this.currentIndex === index ? $r('app.color.font_color') : "#9C9C9C")
}.width('100%').height('80%')
}.width('100%').height('80%')
.backgroundColor($r('app.color.select_menu_background'))
.borderRadius({topLeft: border_radius_left, topRight: border_radius_right, bottomLeft: border_radius_left, bottomRight: border_radius_right})
.margin({left: border_radius_left, right: border_radius_right, bottom: '10%'})
}
5.1.3 使用示例
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller }) {
TabContent() {
Index().width('100%').height('100%')
}.tabBar(this.tabBuilder(0, '探索', $r('app.media.ball'), 25, 0))
TabContent() {
Plan().width('100%').height('100%')
}.tabBar(this.tabBuilder(1, '规划', $r('app.media.signSvg'), 0, 0))
TabContent() {
MyPage().width('100%').height('100%')
}.tabBar(this.tabBuilder(2, '我的', $r('app.media.chat'), 0, 25))
}
5.2 自定义动画效果
通过customContentTransition方法,可以自定义标签页切换时的动画效果,如透明度变化、缩放等。
5.2.1 customContentTransition 方法
参数名 | 类型 | 描述 |
---|---|---|
from | number | 当前标签页索引。 |
to | number | 目标标签页索引。 |
5.2.2 返回值
customContentTransition方法返回一个TabContentAnimatedTransition对象,该对象包含以下字段:
参数名 | 类型 | 描述 |
---|---|---|
timeout | number | 动画开始前的延迟时间(单位:毫秒)。 |
transition | (proxy: TabContentTransitionProxy) => void | 动画过渡方法,用于定义动画逻辑。 |
5.2.3 示例
private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition = (from: number, to: number) => {
let tabContentAnimatedTransition = {
timeout: this.timeoutList[from],
transition: (proxy: TabContentTransitionProxy) => {
this.scaleList[from] = 1.0
this.scaleList[to] = 0.5
this.opacityList[from] = 1.0
this.opacityList[to] = 0.5
animateTo({
duration: this.durationList[from],
onFinish: () => {
proxy.finishTransition()
}
}, () => {
this.scaleList[from] = 0.5
this.scaleList[to] = 1.0
this.opacityList[from] = 0.5
this.opacityList[to] = 1.0
})
}
} as TabContentAnimatedTransition
return tabContentAnimatedTransition
}
5.2.4 使用示例
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller })
.customContentTransition(this.customContentTransition)
.animationMode(AnimationMode.NO_ANIMATION)
.animationDuration(200)
5.3 自定义动画模式和持续时间
除了自定义动画效果,还可以通过animationMode和animationDuration属性来调整动画的模式和持续时间。
5.3.1 animationMode 属性
animationMode属性用于设置动画模式,可选值为AnimationMode.NO_ANIMATION和AnimationMode.BASIC_ANIMATION。
| animationMode | AnimationMode| AnimationMode.NO_ANIMATION | 动画模式,可选值为AnimationMode.NO_ANIMATION、AnimationMode.BASIC_ANIMATION。 |
5.3.2 animationDuration 属性
animationDuration属性用于设置动画的持续时间(单位:毫秒)。
| animationDuration | number | 200 | 动画的持续时间(单位:毫秒)。 |
5.3.3 示例
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller })
.customContentTransition(this.customContentTransition)
.animationMode(AnimationMode.BASIC_ANIMATION)
.animationDuration(300)
5.4 自定义标签栏颜色和背景
通过barBackgroundColor、fontColor和selectedFontColor属性,可以自定义标签栏的背景颜色、未选中标签的文字颜色和选中标签的文字颜色。
5.4.1 barBackgroundColor 属性
| barBackgroundColor| string | #FFFFFF | 标签栏的背景颜色。 |
5.4.2 fontColor 属性
fontColor属性用于设置未选中标签的文字颜色。
| fontColor | string | #182431 | 未选中标签的文字颜色。 |
5.4.3 selectedFontColor 属性
selectedFontColor属性用于设置选中标签的文字颜色。
| selectedFontColor | string | #007DFF | 选中标签的文字颜色。 |
5.4.4 示例
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller })
.barBackgroundColor($r('app.color.background_color'))
.fontColor('#182431')
.selectedFontColor('#007DFF')
5.5 自定义标签栏布局
通过barWidth、barHeight、vertical和barMode属性,可以自定义标签栏的布局和样式。
5.5.1 barWidth 属性
barWidth属性用于设置标签栏的宽度。
| barWidth | string | “100%” | 标签栏的宽度。 |
5.5.2 barHeight 属性
| barHeight | number | 48 | 标签栏的高度。 |
5.5.3 vertical 属性
vertical属性用于设置标签栏是否垂直排列。
| vertical | boolean | false | 是否垂直排列标签页,默认为false,即水平排列。 |
5.5.4 barMode 属性
| barMode | BarMode | BarMode.Fixed | 标签栏的模式,可选值为BarMode.Fixed、BarMode.Scrollable。 |
5.5.5 示例
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller })
.barWidth("88%")
.barHeight(56)
.vertical(false)
.barMode(BarMode.Fixed)
5.6 事件监听
Tabs组件提供了onChange和onAnimationStart事件,方便开发者在标签页切换或动画开始时执行自定义逻辑。
onChange事件在标签页切换时触发。
onAnimationStart事件在标签页动画开始时触发。
5.6.3 示例
Tabs({ barPosition: BarPosition.End, index: this.currentIndex, controller: this.controller })
.onChange((index: number) => {
this.currentIndex = index;
this.selectedIndex = index;
})
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
if (index === targetIndex) {
return;
}
this.selectedIndex = targetIndex;
})
6. 注意事项
使用Tabs组件时,需要注意以下事项,以确保组件正常工作并提供良好的用户体验。
6.1 索引范围
描述: index和selectedIndex属性的值应该在有效范围内(即0到标签页数量-1)。
示例: 如果有3个标签页,index和selectedIndex的值应该在0到2之间。
6.2 资源加载
描述: 确保所有图标资源(selectIcon)已经正确加载,否则将导致显示问题。
示例: 使用$r(‘app.media.ball’)确保资源路径正确。
6.3 动画性能
描述: 自定义动画效果可能会影响性能,特别是在动画逻辑较为复杂的情况下。
建议: 尽量保持动画逻辑简单,并测试不同设备上的性能表现。
6.4 进行触发事件处理
描述: 正确处理onChange和onAnimationStart事件,避免不必要的逻辑执行。
示例:
.onChange((index: number) => {
this.currentIndex = index;
this.selectedIndex = index;
})
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
if (index === targetIndex) {
return;
}
this.selectedIndex = targetIndex;
})
6.5 样式一致性
描述: 确保所有标签页的样式(如字体颜色、背景颜色等)保持一致,以提供统一的视觉效果。
示例:
.onChange((index: number) => {
this.currentIndex = index;
this.selectedIndex = index;
})
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
if (index === targetIndex) {
return;
}
this.selectedIndex = targetIndex;
})
这也太详细了吧