【HarmonyOS NEXT】Tabs组件实现类微信(可滑动的)tabBar页签切换页面功能
关键词:harmonyOS 鸿蒙开发 ArkTS TabContent
使用场景:类微信底部导航栏,点击/左右滑动切换页面并加载数据
开发环境:ArkTS3.1 API9 Phone设备
HMOS Dev官方文档:文档中心
演示效果:
点击并拖拽以移动编辑
目录
完整Demo已提交至Gitee
搭建页面
自定义TabContent(往后翻有完整代码)
思路
开始
完整自定义tabs代码
页面切换后如何加载新数据
介绍
父子组件解释
开始
页面切换时可加载新数据的完整代码
完整Demo已提交至Gitee,传送门:
鸿蒙ArkTS tabBar页签切换Demo: HarmonyOS鸿蒙ArkTS tabBar页签切换完整项目Demo
搭建页面 我这里用三个页面举例,新建home、info、mine页面,创建components目录存放自定义Tabs组件,目录结构如下,我这里已经准备了6个图标图片存放在了resources/rawfile/tabs
点击并拖拽以移动编辑
自定义Tabs(附完整代码) 思路 index为应用加载的首页,加载自定义Tabs组件,Tabs组件中加载各个页面
开始 HMOS Dev官方文档 TabContent :文档中心
1.首先在index.est中导入自定义Tabs组件,避免与官方组件冲突取名comTabs
点击并拖拽以移动编辑
2.在自定义Tabs组件中导入所建的三个页面[如图3],记得在页面中使用export导出[如图4]
点击并拖拽以移动编辑点击并拖拽以移动编辑
[左图3 | 右图4]
3.设置一个PAGE的枚举,增强可读性,不喜欢用就0123代替,因为页面切换的回调函数返回的数值从0开始,所以给currentIndex默认设置为0即为home页(@State装饰器修饰的属性当状态改变时,UI会发生对应的渲染改变),changePage自己写来用于更新页面数据函数,稍后会用到。别忘了new TabsController()[如图3]
4.官方提供了多种页签样式,我们使用置于底部的,将Tabs中barPosition属性设置为BarPosition.End。Tabs将占用整个页面,所以宽高需设置为100%。
Tabs组件中需要TabContent来加载页面。[如图5]
在tabBar中自定义页签按钮样式,因重复代码太多,我们可以利用@Builder装饰器来自定义构建函数复用代码。[如图6]
注意:自定义页签设置onClick事件用于改变页面索引,Tabs组件需设置onChange事件,不然页面左右滑动页签状态不会改变。
点击并拖拽以移动编辑
[图5]
点击并拖拽以移动编辑
[图6]
完整自定义tabs代码 // tabs.ets
// home页 import Home from '../pages/home/home' // info页 import Info from '../pages/info/info' // mine页 import Mine from '../pages/mine/mine'
enum PAGE{ HOME = 0, INFO = 1, MINE = 2 }
@Preview @Component export default struct compTabs{ @State currentIndex: number = 0; private tabsController: TabsController = new TabsController();
changePage(e){ this.currentIndex = e if (e == PAGE.HOME){ } if (e == PAGE.INFO){ } if (e == PAGE.MINE){ } }
@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) { Column() { Image(this.currentIndex === targetIndex ? selectedImg : normalImg) .size({ width: 20, height: 20 }).objectFit(ImageFit.Fill) Text(title) .fontColor(this.currentIndex === targetIndex ? '#484D54' : '#ff969da9') .fontSize(10).margin({top:3,bottom:3}) } .width('100%') .height(67) .alignItems(HorizontalAlign.Center) .backgroundColor('#fff') .justifyContent(FlexAlign.Center) .onClick(() => { this.currentIndex = targetIndex; this.tabsController.changeIndex(targetIndex); }) }
build() { Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) { TabContent() { Home() }.tabBar(this.TabBuilder('首页', 0, rawfile('tabs/home_a.png'), rawfile('tabs/home.png')))
TabContent() {
Info()
}.tabBar(this.TabBuilder('信息', 1, $rawfile('tabs/service_a.png'), $rawfile('tabs/service.png')))
TabContent() {
Mine()
}.tabBar(this.TabBuilder('我的', 2, $rawfile('tabs/me_a.png'), $rawfile('tabs/me.png')))
}.onChange((index: number) => {
this.changePage(index)
})
.width('100%')
.height('100%')
} } 点击并拖拽以移动 页面切换后如何加载新数据 介绍 需要注意的是,在tabContent中不管有多少个页面,页面打开后只会加载一次,切换页面不会达到页面更新的效果。那么页面切换后,如何加载页面的数据呢,很简单,可以利用官方提供的@Link装饰器(父子双向同步)向子组件传递一个时间戳参数过去,页面中使用@Watch监听这个时间戳属性的变化触发自定义的customShow函数。
或者可以增加 if 判断页面索引使其重新加载
父子组件解释 在上述的tabs讲述中导入了home页面、info页面、mine页面,那这三个页面就相当于是tabs的子组件了
开始 1.给子组件设置@Link修饰的timer属性(@Link修饰不用赋初值)
2.利用@watch监听一个自定义函数customShow,当父组件的这个timer改变时子组件就会触发这个函数[如图9]
3.父组件Tabs设置三个属性HomeTimer、InfoTimer、MineTimer,分别记录每个页面的时间戳,新增timeStamp函数返回当前时间戳,在changePage函数触发时获取最新的时间戳[如图7],TabContent中页面里传参时别忘了$符号[如图8]。
点击并拖拽以移动编辑
[图7]
点击并拖拽以移动编辑
[图8]
点击并拖拽以移动编辑
[图9]
同样可以自定义页面的销毁等等,这是我在鸿蒙开发中最常用最省事最高效的办法了,大家不妨试试。
页面切换时可加载新数据的完整代码 Tabs.est
// Tabs.ets
// home页 import Home from '../pages/home/home' // info页 import Info from '../pages/info/info' // mine页 import Mine from '../pages/mine/mine'
enum PAGE{ HOME = 0, INFO = 1, MINE = 2 }
@Preview @Component export default struct compTabs{ @State currentIndex: number = 0; @State HomeTimer: number = 0; @State InfoTimer: number = 0; @State MineTimer: number = 0; private tabsController: TabsController = new TabsController();
changePage(e){ this.currentIndex = e if (e == PAGE.HOME){ this.HomeTimer = this.timeStamp() } if (e == PAGE.INFO){ this.InfoTimer = this.timeStamp() } if (e == PAGE.MINE){ this.MineTimer = this.timeStamp() } }
timeStamp(){ return new Date().getTime(); }
@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) { Column() { Image(this.currentIndex === targetIndex ? selectedImg : normalImg) .size({ width: 20, height: 20 }).objectFit(ImageFit.Fill) Text(title) .fontColor(this.currentIndex === targetIndex ? '#484D54' : '#ff969da9') .fontSize(10).margin({top:3,bottom:3}) } .width('100%') .height(67) .alignItems(HorizontalAlign.Center) .backgroundColor('#fff') .justifyContent(FlexAlign.Center) .onClick(() => { this.currentIndex = targetIndex; this.tabsController.changeIndex(targetIndex); }) }
build() { Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) { TabContent() { Home({ timer:HomeTimer }) }.tabBar(this.TabBuilder('首页', 0, rawfile('tabs/home_a.png'), $rawfile('tabs/home.png')))
TabContent() {
Info({ timer:$InfoTimer })
}.tabBar(this.TabBuilder('信息', 1, $rawfile('tabs/service_a.png'), $rawfile('tabs/service.png')))
TabContent() {
Mine({ timer:$MineTimer })
}.tabBar(this.TabBuilder('我的', 2, $rawfile('tabs/me_a.png'), $rawfile('tabs/me.png')))
}.onChange((index: number) => {
this.changePage(index)
})
.width('100%')
.height('100%')
} } 点击并拖拽以移动 home.est
import promptAction from '@ohos.promptAction';
@Component export default struct Home { @State message: string = 'home页面' @Link @Watch('customShow') timer: Number
customShow(){ promptAction.showToast({ message: "页面展示" }); }
build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) } .width('100%') } .height('100%') } } 点击并拖拽以移动
- 2回答
- 1粉丝
- 0关注
- 鸿蒙HarmonyOS从零实现类微信app基础界面搭建
- 如何实现上下切换的页面间跳转动画
- 【HarmonyOS NEXT】实现页面水印功能
- HarmonyOS ArkTS中视频播放Video组件实现竖屏到横屏切换
- 带你实现 OpenHarmony 微信聊天 01
- 带你实现OpenHarmony 微信聊天02
- HarmonyOS应用开发实战:半天实现知乎日报项目(三、ArkUI页面底部导航TabBar的实现)
- OpenHarmony: 如何实现跨模块的页面跳转功能
- 【HarmonyOS NEXT】 Audio 实现录音及播放功能
- 【HarmonyOS Next开发】Tabs使用封装
- HarmonyOS NEXT 地图服务中‘我的位置’功能全解析
- HarmonyOS应用开发实战:半天实现知乎日报项目(八、知乎日报详情页的实现)
- 【HarmonyOS NEXT】权限申请及应用设置页跳转
- 【HarmonyOS NEXT】权限申请及应用设置页跳转
- 鸿蒙next boss直聘招聘app 聊天功能实现来