ArkUI框架的Navigation导航组件
在移动应用中需要在不同的页面进行切换跳转。这种切换和跳转有两种方式:页面路由和Navigation组件实现导航。HarmonyOS推荐使用Navigation实现页面跳转。在本文中在HarmonyOS 5.0.0 Release SDK (API Version 12 Release)版本下,简单介绍ArkUI框架的Navigation导航组件。
一、Navigation组件定义的页面结构
Navigation组件主要包含导航页和子页:
导航页由标题栏、内容区和工具栏组成,其中导航页可以通过hideNavBar属性进行隐藏,导航页不存在页面栈中,导航页和子页,以及子页之间可以通过路由操作进行切换。
二、定义导航页
Navigation是路由导航的根视图容器,一般作为页面(@Entry)的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换。
导航页页面的结构:
@Entry
@Component
struct NavigationPage {
@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()//定义页面栈保存页面路径
build() {Column() {Navigation(this.pageInfos) {...//内容区定义}.title("导航组件标题")//设置导航的标题.mode(NavigationMode.Stack)//配置导航的模式.navDestination(...)//设置导航路径.menus(...)//定义顶部菜单.toolbarConfiguration(...)//配置底部导航栏即工具栏}
说明:
1.在上述导航页中定义的NavPathStack对象表示页面栈,采用了@Provide装饰,可以看作是“提供”给后代的状态变量。在此处,它可以提供给子页同时使用页面栈,用于记录子页的导航路径。注意:导航页的路径不会推入到NavPathStack页面栈中。
2.导航页使用Navigation组件
3.在Navigation组件中:(1)title()函数设置导航页的标题
(2)mode()函数配置导航的模式,NavigationMode.Stack表示单页显示模式,NavigationMode.Split表示分栏显示,NavigationMode.Auto表示自动选择显示模式
(3)navDestination()函数指定导航的路径,所有的导航路径可以通过PageMap来定义。形如:
@Builder
PageMap(routerName:string){
…//定义根据routerName路由名称不同调用不同的页面``
}
(4)menus()函数定义顶部菜单栏的内容,各个菜单项由NavigationMenuItem数组或CustomBuilder两种类型构成。菜单栏在竖屏最多支持显示3个图标,横屏最多支持显示5个图标,多余的图标会被放入自动生成的更多图标。
(5)toolbarConfiguration()配置底部的工具栏。工具栏的单项由ToolbarItem组成,对toolbarConfiguration()函数传递ToolbarItem数组,可以生成底部工具栏的各个导航单项。
导航页的代码示例
@Entry
@Component
struct Index {//定义页面栈,子页也可以使用@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()//定义顶部菜单项,子页也可以使用@Provide topMenuItems:NavigationMenuItem[] = [{value: "首页", icon: 'resources/base/media/startIcon.png', action: ()=> {this.pageInfos.pushPath({ name: "首页"})}},{value: "配置", icon: 'resources/base/media/setting.png', action: ()=> {this.pageInfos.pushPath({ name: "配置"})}},{value: "帮助和支持", icon:'resources/base/media/help.png', action: ()=> {this.pageInfos.pushPath({ name: "帮助和支持"})}}]//定义底部工具栏@State bottomMenuItems:ToolbarItem[] = [{'value': "首页", 'icon': $r("app.media.startIcon"), 'action': ()=> {this.pageInfos.pushPath({ name: "首页"})}},{'value': "配置", 'icon': $r("app.media.setting"), 'action': ()=> {this.pageInfos.pushPath({ name: "配置"})}},{'value': "帮助和支持", 'icon': $r("app.media.help"), 'action': ()=> {this.pageInfos.pushPath({ name: "帮助和支持"})}}]//定义导航路径的数组,其中"退出“对应退出的操作private routerTitles:string[] = ["首页","配置","帮助和支持","退出"]@BuilderPageMap(name: string) {if (name === "首页") {pageOne()} else if (name === "配置") {pageTwo()} else if (name === "帮助和支持") {pageThree()}}build() {Column() {Navigation(this.pageInfos) {//内容区,自行定义TextInput({ placeholder: '检索...' }).width("90%").height(40).backgroundColor('#FFFFFF')List({ space: 12 }) {ForEach(this.routerTitles,(item:string)=>{ListItem(){Text(item).width("100%").height(72).backgroundColor('#D2E76B').borderRadius(24).fontSize(16).fontWeight(500).textAlign(TextAlign.Center).onClick(()=>{if(item=="退出"){(getContext(this) as common.UIAbilityContext)?.terminateSelf();}elsethis.pageInfos.pushPath({ name: item})})}})}.width("90%").margin({ top: 12 })}.title("导航组件测试示例")//设置导航的标题.mode(NavigationMode.Stack)//配置导航的模式.navDestination(this.PageMap)//设置导航路径.menus(this.topMenuItems)//定义顶部菜单.toolbarConfiguration(this.bottomMenuItems)//配置底部工具栏}.height('100%').width('100%').backgroundColor('#83B5FF')}
}
图1 导航页的运行效果
三、定义子页
子页的结构:
@Component
export struct pageOne {@Consume('pageInfos') pageInfos: NavPathStack; //引用build() {NavDestination() {//内容区定义}.title("首页")//定义子页的标题.onBackPressed(() => {const popDestinationInfo = this.pageInfos.pop() // 弹出页面栈栈顶元素return true})}
}
说明:
(1) 子页自定义组件不是页面的入口组件,无需使用@Entry装饰,也不需要在resources/base/profile/main_pages.json中配置页面。
(2)在子页中@Consume 装饰的变量,用于“消费(绑定)”导航页提供的导航路径堆栈。
(3)子页中使用NavDestination是子页面的根容器,用于定义子页面。调用NavDestination的title()函数设置独立的标题栏。
调用NavDestination的menus()函数设置子页的顶部菜单栏。
子页代码示例
//PageOne.ets
@Component
export struct pageOne {@Consume('pageInfos') pageInfos: NavPathStack;//使用导航页的页面栈@Consume('topMenuItems') topMenuItems:NavigationMenuItem[]//使用导航页的菜单项的定义build() {NavDestination() {Column() {}.width('100%').height('100%').backgroundColor(Color.Orange)}.title("首页").menus(this.topMenuItems)//定义顶部菜单栏的菜单项.onBackPressed(() => {this.pageInfos.pop() // 弹出页面栈栈顶元素return true})}
}
图2 子页1的运行效果
//PageTwo.ets
@Component
export struct pageTwo{@Consume('pageInfos') pageInfos: NavPathStack;@Consume('topMenuItems') topMenuItems:NavigationMenuItem[]build() {NavDestination() {Column() {}.width('100%').height('100%').backgroundColor(Color.Blue)}.title("配置").menus(this.topMenuItems).onBackPressed(() => {this.pageInfos.pop() // 弹出页面栈栈顶元素return true})}
}
图3 子页2的运行效果
//PageThree.ets
@Component
export struct pageThree{@Consume('pageInfos') pageInfos: NavPathStack;@Consume('topMenuItems') topMenuItems:NavigationMenuItem[]build() {NavDestination() {Column() {}.width('100%').height('100%').backgroundColor(Color.Green)}.title("帮助和支持").menus(this.topMenuItems).onBackPressed(() => {this.pageInfos.pop() // 弹出页面栈栈顶元素return true})}
}
图4 子页3的运行效果
四、页面的路由处理
页面的路由处理表示从不同页面中进行跳转和切换,通过NavPathStack页面栈来实现。下表中展示了NavPathStack页面栈的常见函数实现不同页面的处理操作
函数 | 说明 |
---|---|
pushPath({name:“pageOne”,param:“somevalue”} | 跳转到name属性指定的路径名对应的页面;param表示传递的参数,也可不用 |
pushPathByName(“pageOne”,“somevalue”) | 跳转到name属性指定的路径名对应的页面,可以传递参数值 |
pop() | 返回上一页 |
popToName(‘pageOne’) | 返回路由路径名为pageOne对应的页面 |
popToIndex(1) | 返回索引为1的页面 |
clear() | 返回到根首页,清除页面栈 |
replacePath({name:“pageOne”,param:“somevalue”} ) | 替换页面 |
replacePathByName(“pageOne”,“somevalue”) | 替换页面 |
修改PageTwo.ets,使之增加图片,并为图片配置点击交互处理,当点击该图片返回到首页(对应pageOne页面),代码如下: |
@Component
export struct pageTwo{@Consume('pageInfos') pageInfos: NavPathStack;@Consume('topMenuItems') topMenuItems:NavigationMenuItem[]build() {NavDestination() {Column() {Text("配置说明").fontSize(50).fontColor(Color.White)Image("resources/base/media/startIcon.png").width(60).height(60).margin(5).position({x:260,y:600}).onClick(() => {this.getUIContext()?.animateTo({ duration: 1000 }, () => {this.pageInfos.pushPath({ name: '首页' }, false)//返回首页})})}.width('100%').height('100%').backgroundColor(Color.Blue)}.title("配置").menus(this.topMenuItems).onBackPressed(() => {this.pageInfos.pop() // 弹出路由栈栈顶元素return true})}
}
图5 修改后的页面2运行结果
当点击图片后,会跳转到首页。当在首页页面的标题栏的返回按钮时,因为执行了this.pageInfos.pop(),仍会返回到上一级的页面,就是上述图5展示的页面。
参考文献:
1.单页面布局示意图 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-navigation-navigation-V5