鸿蒙开发6--HarmonyOS标签页应用开发实战教程
上一篇文章,我们体验了一下声明式导航Navigation组件,为了巩固一下,本文我们复用上文的商品信息页面,再添加上标签页(Tab)这种导航方式。
我们的目标是构建一个包含"商城"和"我的"两个标签页的应用。
用户可以在商城页面浏览商品列表,然后点击查看详情;
在个人中心查看用户信息,进入设置页面。
第一步:理解应用架构
虽然简单,但是在开始编码之前,我们梳理下整个应用的结构。我们的应用采用分层架构:
主页面(MainPage)├── 标签页1:商城(ProductListPage)│ └── 商品详情页(ProductDetailPage)└── 标签页2:我的(MyProfileTabPage)└── 设置页(SettingsPage)
每个标签页都有独立的导航栈,用户可以在不同标签页间自由切换,不会丢失各自的浏览状态。
第二步:数据模型设计
我们首先定义两个核心数据模型,Product是上文已经有的,这次新增了User这个数据模型。
// models/ProductModels.etsexport interface Product {id: string;name: string;description: string;}export interface User {uid: string;username: string;avatar: Resource;level: number;}
第三步:构建主标签页容器
主页面是整个应用的入口,使用Tabs
组件来管理多个标签页。让我们看看如何实现:
@Entry@Componentstruct MainPage {@State currentIndex: number = 0@Builderprivate tabBuilder(title: string, targetIndex: number, icon: Resource) {Column() {Image(icon).width(28).height(28).margin({ bottom: 2 })Text(title).fontSize(12).fontColor(this.currentIndex === targetIndex ? '#007DFF' : '#666666')}.width('100%').height('100%').justifyContent(FlexAlign.Center)}build() {Tabs({ barPosition: BarPosition.End }) {TabContent() {ProductListPage()}.tabBar(this.tabBuilder('商城', 0, $r('app.media.ic_shop')))TabContent() {MyProfileTabPage()}.tabBar(this.tabBuilder('我的', 1, $r('app.media.ic_profile')))}.onChange((index) => {this.currentIndex = index;}).animationDuration(300).barWidth('100%').barHeight(56)}}
注意现在MainPage.ets作为了应用的入口,在day5_navigation模块中,ProductListPage是应用入口。拷贝到day6_tab模块后,ProductListPage上的@Entry就可以去掉了。
然后把day6_tab模块src/main/ets/day6_tabability/Day6_tabAbility.ets中的loadContent修改成MainPage。
状态管理 @State currentIndex: number = 0
用来跟踪当前选中的标签页。当用户切换标签的时候,这个状态会自动更新,触发UI重新渲染。
自定义标签样式 @Builder
装饰器可以让我们我们创建可复用的UI构建器。这里我们自定义了标签页的样式,包括图标、文字和选中状态的颜色变化。
标签页配置 barPosition: BarPosition.End
把标签栏放在底部,一般的手机app都这么布局。animationDuration(300)
设置了切换动画的持续时间。
第四步:商品列表、详情页
直接把前文的ProductListPage和ProductDetailPage页面拷贝过来就可以了。
第五步:构建个人中心页
个人中心页展示了用户信息管理和设置入口:
@Componentexport struct MyProfileTabPage {@State path: NavPathStack = new NavPathStack();@BuilderdestinationBuilder(name: string, param: object) {if (name === 'Settings') {NavDestination() {SettingsPage()}.title('设置')}}build() {Navigation(this.path) {Column({ space: 20 }) {Image(currentUser.avatar).width(100).height(100).borderRadius(50)Text(currentUser.username).fontSize(24).fontWeight(FontWeight.Bold)Text(`等级: Lv.${currentUser.level}`).fontSize(18).fontColor(Color.Gray)Button('进入设置页面').margin({ top: 30 }).onClick(() => {this.path.pushPathByName('Settings', null);})}.width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor('#f1f3f5')}.title('我的').navDestination(this.destinationBuilder)}}
独立的导航栈 每个标签页都有自己的 NavPathStack
,用户在"商城"标签页浏览商品详情,然后切换到"我的"标签页,再回到"商城"时,之前的浏览状态会被保留。
用户信息展示 我们使用模拟的用户数据来展示用户信息,包括头像、用户名和等级。在实际应用中,这些数据通常来自用户登录后的API响应。
第六步:实现设置页面
设置页面展示了状态管理和用户交互:
@Componentexport struct SettingsPage {@State isNotificationOn: boolean = true;@State isDarkMode: boolean = false;build() {Column() {List({ space: 10 }) {ListItem() {Row() {Text('开启消息通知').fontSize(18)Toggle({ type: ToggleType.Switch, isOn: this.isNotificationOn }).onChange((isOn) => {this.isNotificationOn = isOn;})}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding(20).backgroundColor(Color.White)}.borderRadius(15)ListItem() {Row() {Text('夜间模式').fontSize(18)Toggle({ type: ToggleType.Switch, isOn: this.isDarkMode }).onChange((isOn) => {this.isDarkMode = isOn;})}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding(20).backgroundColor(Color.White)}.borderRadius(15)}.width('95%').margin({top: 20})}.width('100%').height('100%').backgroundColor('#f1f3f5').alignItems(HorizontalAlign.Start)}}
状态管理的重要性: 每个开关都有对应的 @State
变量来管理其状态。当用户操作开关时,onChange
回调会更新对应的状态,触发UI重新渲染。这种响应式的状态管理是 HarmonyOS 开发的核心特性。
运行效果
主页面:
我的页面:
设置界面:
总结
通过这个标签页应用的学习,我们掌握了HarmonyOS开发的核心技能:
组件化开发:如何设计和实现可复用的组件
状态管理:如何使用
@State
和@Prop
管理应用状态页面导航:如何使用
Navigation
和NavPathStack
实现页面跳转用户交互:如何响应用户操作并更新UI
这些技能是构建复杂HarmonyOS应用的基础。掌握了这些概念,你就可以开始构建更复杂、更有趣的应用了。