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[] = ["首页","配置","帮助和支持","退出"]
@Builder
PageMap(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();
}
else
this.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