HarmonyOS应用开发实战:半天实现知乎日报项目(三、ArkUI页面底部导航TabBar的实现)
在开发HarmonyOS NEXT应用时,TabBar是用户界面设计中不可或缺的一部分。本文将通过代码示例,带领大家一同实现一个常用的TabBar,涵盖三个主要的内容页:首页、知乎日报和我的页面。以模仿知乎日报的项目为背景驱动,设定一个小目标,最终实现知乎日报app项目。
1. 项目结构
在我们的代码中,首先需要导入需要使用的页面组件:
import Home from "../pages/home/Home"
import ZhiHu from "../pages/zhihu/Zhihu"
import Mine from "../pages/mine/Mine"
这三条语句确保我们可以在TabBar中使用这些页面,分别是首页,知乎日报页和个人中心页。
关于Tabs组件的官方文档:文档中心-Tabs导航组件
编辑
2. 代码实现
接下来,我们将实现一个名为Index
的组件,这是整个TabBar的核心。在此组件中,我们定义了三个主要功能:
- 页面显示的生命周期管理
- TabBar的构建与展示
- 自定义Tab项样式
2.1 页面生命周期管理
我们定义了一些生命周期函数,帮助我们在页面显示和隐藏时输出相应的信息:
@Entry
@Component
struct Index {
@State currentIndex: number = 0
private controller: TabsController = new TabsController()
onPageShow() {
console.info('Index onPageShow');
}
onPageHide() {
console.info('Index onPageHide');
}
onBackPress() {
console.info('Index onPageBackPress');
}
currentIndex
用于跟踪当前选中的Tab项,而controller
则用于控制Tab的切换。
2.2 构建TabBar
在组件的build
方法中,我们使用Tabs
组件来创建TabBar,添加每个Tab项的内容和样式配置:
build() {
Column() {
Tabs({
barPosition: BarPosition.End,
controller: this.controller
}) {
TabContent() {
Home()
}.tabBar(this.TabBuilder('首页', 0, $r('app.media.icon_sort'), $r('app.media.icon_sort_default')))
TabContent() {
ZhiHu()
}.tabBar(this.TabBuilder('日报', 1, $r('app.media.search_select'), $r('app.media.search_default')))
TabContent() {
Mine()
}.tabBar(this.TabBuilder('我的', 2, $r('app.media.user_selected'), $r('app.media.user')))
}.scrollable(false) // 禁止滑动切换
}
.width('100%')
.height('100%')
}
这里使用了TabContent
来表示每个页面的具体内容,并通过tabBar
来定义每个Tab的样式和功能。
每一个TabContent对应的内容需要有一个页签,可以通过TabContent的tabBar属性进行配置。在如下TabContent组件上设置属性tabBar,可以设置其对应页签中的内容,tabBar作为内容的页签。
设置多个内容时,需在Tabs内按照顺序放置。
导航栏位置使用Tabs的参数barPosition进行设置,默认情况下,导航栏位于顶部,参数默认值为Start。设置为底部导航需要在Tabs传递参数,设置barPosition为End。
对应的图片资源,需放置在entry\src\main\resources\base\media目录中。这里发现个问题,图片只能放在这,好像里面不能再建子文件夹目录了,也就是说图片资源混在一起,这点儿有点儿不太好。
2.3 自定义Tab项样式
接下来,我们自定义了一个名为TabBuilder
的方法,以便我们可以灵活地构建每个Tab的样式:
@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
Column() {
Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
.size({ width: 25, height: 25 })
Text(title)
.fontColor(this.currentIndex === targetIndex ? '#28bff1' : '#8a8a8a')
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.currentIndex = targetIndex
this.controller.changeIndex(this.currentIndex)
})
}
这个构建器根据当前选中的Tab来设置图标和文字颜色,并在点击时更新currentIndex
和Tab的显示状态。
编辑
在page目录下新建文件夹home,mine和zhihu分别用来存放对应的tab页的内容。这样便于清晰的管理各个页面,且不至于把所有内容都放到一个Index.ets文件里。对应的主页Home组件,内容举例如下:
@Component
export default struct Home {
build() {
Column() {
// 标题栏
Text("首页")
.size({ width: '100%', height: 50 })
.backgroundColor("#28bff1")
.fontColor("#ffffff")
.textAlign(TextAlign.Center)
.fontSize("18fp")
// 内容项
Text("首页").width('100%').height('100%').textAlign(TextAlign.Center).fontSize("25fp")
}.size({ width: '100%', height: '100%' })
}
}
3. 完整实现
import Home from "../pages/home/Home"
import ZhiHu from "../pages/zhihu/Zhihu"
import Mine from "../pages/mine/Mine"
@Entry
@Component
struct Index {
@State currentIndex: number = 0
private controller: TabsController = new TabsController()
// 只有被@Entry装饰的组件才可以调用页面的生命周期
onPageShow() {
console.info('Index onPageShow');
}
// 只有被@Entry装饰的组件才可以调用页面的生命周期
onPageHide() {
console.info('Index onPageHide');
}
// 只有被@Entry装饰的组件才可以调用页面的生命周期
onBackPress() {
console.info('Index onBackPress');
}
build() {
Column() {
Tabs({
barPosition: BarPosition.End,
controller: this.controller
}) {
TabContent() {
Home()
}.tabBar(this.TabBuilder('首页', 0, $r('app.media.icon_sort'), $r('app.media.icon_sort_default')))
TabContent() {
ZhiHu()
}.tabBar(this.TabBuilder('日报', 1, $r('app.media.search_select'), $r('app.media.search_defaut')))
TabContent() {
Mine()
}.tabBar(this.TabBuilder('我的', 2, $r('app.media.user_selected'), $r('app.media.user')))
}.scrollable(false) // 禁止滑动切换
}
.width('100%')
.height('100%')
}
// 自定义导航页签的样式
@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
Column() {
Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
.size({ width: 25, height: 25 })
Text(title)
.fontColor(this.currentIndex === targetIndex ? '#28bff1' : '#8a8a8a')
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
.onClick(() => {
this.currentIndex = targetIndex
this.controller.changeIndex(this.currentIndex)
})
}
}
4. 总结
通过上述步骤,我们在HarmonyOS NEXT的应用中成功实现了一个简单的TabBar。这个TabBar包含了三个功能模块,并能够根据用户的操作进行动态更新。接下来,您可以在此基础上,进一步扩展更多功能,提升用户体验。希望这篇博文能够对您在HarmonyOS应用开发中有所帮助。
写在最后
最后,推荐下笔者的业余开源app影视项目“爱影家”,推荐分享给与我一样喜欢观影的朋友。
开源地址: 爱影家app开源项目介绍及源码
https://gitee.com/yyz116/imovie
作者:猫哥 (blog.csdn.net/qq8864),转载请注明出处。 团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙原生应用,三方库60+,欢迎交流。
其他资源
HarmonyOS 鸿蒙应用开发( 五、快速实现ArkUI页面底部导航Tabs)_鸿蒙开发底部导航-CSDN博客
- 3回答
- 2粉丝
- 3关注
- HarmonyOS应用开发实战:半天实现知乎日报项目(八、知乎日报详情页的实现)
- HarmonyOS应用开发实战:半天实现知乎日报项目(四、仿知乎日报的首页轮播图实现)
- HarmonyOS应用开发实战:半天实现知乎日报项目( 五、组件导航Navigation使用详解)
- HarmonyOS应用开发实战:半天实现知乎日报项目(九、知乎日报项目接口使用指南)
- HarmonyOS应用开发实战:半天实现知乎日报项目(六、首页轮播图的完整实现)
- HarmonyOS 应用开发实战:半天实现知乎日报完整项目(一、开篇,环境准备)
- HarmonyOS应用开发实战:半天实现知乎日报项目(七、知乎日报List列表下拉刷新及上滑加载更多分页的实现)
- 基础的页面布局
- HarmonyOS NEXT应用开发 ( 应用的签名打包上架,各种证书详解)
- OpenHarmony5.0应用开发 (三、应用程序包结构理解及Ability的跳转,与Android的对比)
- HarmonyOS NEXT应用开发实战(封装比UniApp和小程序更简单好用的网络库)
- HarmonyOS 地图服务:深度解析其丰富功能与精准导航实力
- 『中工开发者』HarmonyOS应用开发者基础认证习题及答案
- 元服务——基础页面创建
- 开发元服务的环境