当前位置:首页 > 科技  > 软件

Navigation常见场景的解决方案

来源: 责编: 时间:2024-05-09 09:27:24 99观看
导读想了解更多关于开源的内容,请访问:51CTO 鸿蒙开发者社区https://ost.51cto.com路由跳转场景页面跳转是路由最常用的能力,Navigation通过NavPathStack提供了诸多方法,下文以pushDestination方法为例,介绍Navigation的路由跳

l7H28资讯网——每日最新资讯28at.com

想了解更多关于开源的内容,请访问:l7H28资讯网——每日最新资讯28at.com

51CTO 鸿蒙开发者社区l7H28资讯网——每日最新资讯28at.com

https://ost.51cto.coml7H28资讯网——每日最新资讯28at.com

路由跳转场景

页面跳转是路由最常用的能力,Navigation通过NavPathStack提供了诸多方法,下文以pushDestination方法为例,介绍Navigation的路由跳转相关能力。l7H28资讯网——每日最新资讯28at.com

页面间跳转

NavPathStack提供了路由管理的能力,通过NavPathStack进行页面跳转,主要适用于页面较多的应用。l7H28资讯网——每日最新资讯28at.com

Step1:创建NavPathStack对象pageStack,通常使用@Provide进行修饰,方便后续子组件通过@Comsumer获取,以实现子页面的路由跳转。l7H28资讯网——每日最新资讯28at.com

也可以将pageStack传入路由框架,以实现路由框架开发(后续路由框架章节会介绍)的开发。l7H28资讯网——每日最新资讯28at.com

@Entry @Component struct mainPageView {   @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()   ...   build() {     ...   } }

Step2:构建路由表pageMap,该方法通过@Builder进行修饰,通过传入的pageName属性,返回不同页面。l7H28资讯网——每日最新资讯28at.com

@Entry @Component struct mainPageView {   @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()   @Builder   PageMap(pageName: string) {     if (pageName === 'loginPage') {       loginPageView()     } else if (pageName === 'mainPage') {       mainPageView()     }   }   build() {     ...   } }

Step3:在build创建Navigation组件(需要传入pageStack参数),通过navDestination属性传入路由表pageMap,并通过pageStack.pushPath()实现页面跳转。l7H28资讯网——每日最新资讯28at.com

@Entry @Component struct mainPageView {   @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()   @Builder   pageMap(pageName: string) {     if (pageName === 'loginPage') {       loginPageView()     } else if (pageName === 'mainPage') {       mainPageView()     }   }   build() {     Navigation(this.pageStack){       ...       Button('login').onClick( ent => {         let pathInfo : NavPathInfo = new NavPathInfo('loginPage', null)         this.pageStack.pushDestination(pathInfo, true);       })     }.navDestination(this.pageMap)     ...   } }

页面间参数传递

Navigation的页面间,通过NavPathInfo对象中的params属性,实现从发起页到目标页的数据传递;通过onPop回调参数,实现处理目标页面的返回。l7H28资讯网——每日最新资讯28at.com

Step1:构建NavPathInfo对象,输入需要传递给目标页面的参数。l7H28资讯网——每日最新资讯28at.com

params参数:将需要传递的数据封装起来进行传递,无法传递对象里面的函数。具体的支持参数可以参考指南()l7H28资讯网——每日最新资讯28at.com

onPop参数:目标页面触发pop时的返回,在回调中通过PopInfo.info.param获取到返回的对象。l7H28资讯网——每日最新资讯28at.com

// 发起页 mainPage let loginParam : LoginParam = new LoginParam() // 构建pathInfo对象 let pathInfo : NavPathInfo = new NavPathInfo('loginPage', loginParam   , (popInfo: PopInfo) => {     let loginParam : LoginParam = popInfo.info.param as LoginParam;     ...   }) // 讲参数传递到目标页 this.pageStack.pushDestination(pathInfo, true);  

Step2:目标页通过“NavPathStack.getParamByIndex(0)”获取到发起页传递过来的参数l7H28资讯网——每日最新资讯28at.com

@Component export struct loginPageView {   @Consume('pageInfo') pageStack : NavPathStack;    aboutToAppear(): void {     this.loginParam = this.pageStack.getParamByIndex(0) as LoginParam;   }   ... }

Step3:目标页通过NavPathStack.pop方法返回起始页,其result参数用来传递需要返回给起始页的对象。l7H28资讯网——每日最新资讯28at.com

@Component export struct loginPageView {   @Consume('pageInfo') pageStack : NavPathStack;   // 页面构建的对象   private loginParam! : LoginParam;   ...   build() {     NavDestination(){       ...       Button('login').onClick( ent => {         // 将对象返回给起始页         this.pageStack.pop(this.loginParam, true)       })     }   } }

跨模块页面跳转

当应用模块较多,需要使用HSP(HAR)进行多模块开发,比如登录模块是一个独立团队开发,以HSP(HAR)的形式交付。此时主页应当从mainPage跳转到HSP(HAR)中的页面,需要先导入模块的自定义组件,将组件添加到pageMap中,再通过pushDestination进行跳转。l7H28资讯网——每日最新资讯28at.com

Step1:从HSP(HAR)中完成自定义组件(需要跳转的目标页面)开发,讲自定义组件申明为export。l7H28资讯网——每日最新资讯28at.com

@Component export struct loginPageInHSP {   @Consume('pageStack') pageStack: NavPathStack;   ...   build() {     NavDestination() {       ...     }   } }

Step2:在HSP(HAR)的index.ets中导出组件。l7H28资讯网——每日最新资讯28at.com

export { loginPageInHSP } from "./src/main/ets/pages/loginPageInHSP"

Step3:配置好HSP(HAR)的项目依赖后,在mainPage中导入自定义组件,并添加到pageMap中,即可正常调用。// 导入模块目标页自定义组件。l7H28资讯网——每日最新资讯28at.com

import { loginPageInHSP } from 'library/src/main/ets/pages/loginPageInHSP' @Entry @Component struct mainPage {   @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()   @Builder pageMap(name: string) {     if (name === 'loginPageInHSP') {       // 路由到hsp包中的登录页面       loginPageInHSP()     }   }   build() {     Navigation(this.pageStack) {       Button("login With HSP module")         .onClick(() => {           let loginParam : LoginParamInHSP = new LoginParamInHSP()           let pathInfo : NavPathInfo = new NavPathInfo('loginPageInHSP', loginParam, (popInfo: PopInfo) => {})           this.pageStack.pushDestination(pathInfo, true);         })     }     .navDestination(this.pageMap)   } }

页面转场

默认转场动画

Navigation的pushXXX和pop方法中都带有一个参数animated,将animated设置成false则会取消转场动画,路由到Dialog模式页面或者路由出Dialog模式页面是,均无转场动画,如果需要转场动画,可以通过自定义转场动画实现。l7H28资讯网——每日最新资讯28at.com

自定义转场动画

Navigation通过customNavContentTransition事件提供自定义转场动画的能力,当转场开始时,通过回调函数告知开发者,告知此次动画from(从哪来)、to(到哪去)、是Push、Pop亦或是Repalce。这里需要注意当为根视图时,NavContentInfo的name值为undefined。l7H28资讯网——每日最新资讯28at.com

开发者可以在customNavContentTransition的回调函数中进行动画处理,返回NavigationAnimatedTransition自定义转场协议已实现自定义转场。l7H28资讯网——每日最新资讯28at.com

NavigationAnimatedTransition对象中包含三个参数,timeout(动画超时结束时间),transition(自定义动画执行回调),onTransitionEnd(转场完成回调),需要在transition方法中实现具体动画逻辑。l7H28资讯网——每日最新资讯28at.com

由于自定义转场参数是在Navigation层级,但是每个页面都会有其特定的自定义转场效果,因此需要定义一套转场动画框架,已实现在Navigation层面对框架进行统一管理,各个页面通过实现框架提供的回调函数,将其特定的动画效果传递给Navigation。l7H28资讯网——每日最新资讯28at.com

Step1:构建动画框架,通过一个Map管理各个页面自定义自定义动画对象CustomTransition,CustomTransition对象提供了Push、Pop、Replace各个动画阶段的回调函数给各个页面进行补充,此处将各个阶段细分为In和Out,从而实现页面进入和退出时不同的转场效果。l7H28资讯网——每日最新资讯28at.com

// 自定义动画对象,定义了Push、Pop、Replace各个动画阶段的回调函数。l7H28资讯网——每日最新资讯28at.com

export class CustomTransition {   pageID : number = -1;   onPushInStart: () => void = () => {};   onPushInEnd: () => void = () => {};   onPushInFinish: () => void = () => {};   onPopInStart: () => void = () => {};   onPopInEnd: () => void = () => {};   onPopInFinish: () => void = () => {};   onReplaceInStart: () => void = () => {};   onReplaceInEnd: () => void = () => {};   onReplaceInFinish: () => void = () => {};   onPushOutStart: () => void = () => {};   onPushOutEnd: () => void = () => {};   onPushOutFinish: () => void = () => {};   onPopOutStart: () => void = () => {};   onPopOutEnd: () => void = () => {};   onPopOutFinish: () => void = () => {};   onReplaceOutStart: () => void = () => {};   onReplaceOutEnd: () => void = () => {};   onReplaceOutFinish: () => void = () => {};   ...    // 获取启动阶段参数回调   public getStart(operation : NavigationOperation, isInPage : boolean) : () => void {     if (operation == NavigationOperation.PUSH) {       if (isInPage) {         return this.onPushInStart;       } else {         return this.onPushOutStart;       }     } else if (operation == NavigationOperation.POP) {       if (isInPage) {         return this.onPopInStart;       } else {         return this.onPopOutStart;       }     } else {       if (isInPage) {         return this.onReplaceInStart;       } else {         return this.onReplaceOutStart;       }     }   }   // 获取动画结束阶段参数回调   public getEnd(operation : NavigationOperation, isInPage : boolean) : () => void {     ...   }   // 获取动画结束后参数回调   public getFinished(operation : NavigationOperation, isInPage : boolean) : () => void {     ...   } }  // 自定义动画对象框架 export class CustomTransitionFW {   // 各个页面自定义动画对象映射表   private customTransitionMap: Map<number, CustomTransition> = new Map<number, CustomTransition>()   ...   registerNavParam(ct : CustomTransition): void {     ...     this.customTransitionMap.set(ct.pageID, ct);   }    unRegisterNavParam(pageId: number): void {     ...     this.customTransitionMap.delete(pageId);   }    getAnimateParam(pageId: number): CustomTransition {     ...     return this.customTransitionMap.get(pageId) as CustomTransition;   } }

Step2:配置Navigation的customNavContentTransition属性,当返回undefined时,使用系统默认动画。l7H28资讯网——每日最新资讯28at.com

build() {   Navigation(this.pageStack){     ...   }.hideTitleBar(true)   .hideToolBar(true)   .navDestination(this.pageMap)   .customNavContentTransition((from: NavContentInfo, to: NavContentInfo, operation: NavigationOperation) => {     // 对于Dialog型的页面,此处统一做了自定义动画的屏蔽,若需要动画,可以不做此判断。     if (from.mode == NavDestinationMode.DIALOG || to.mode == NavDestinationMode.DIALOG) {       console.error(`==== no transition because Dialog`);       return undefined;     }     let pageIn : CustomTransition | undefined;     let pageOut : CustomTransition | undefined;     pageIn = CustomTransitionFW.getInstance().getAnimateParam(to.index)     pageOut = CustomTransitionFW.getInstance().getAnimateParam(from.index)     // 业务首页跳转时若没有自定义动画诉求,此处可以通过判断页面id是否为-1(-1表示Navigation根视图)进行跳出。     if (from.index === -1 || to.index === -1) {       return undefined;     }     // 创建自定义转场协议,各个页面都会根据协议中的配置进行转场,当返回undefined时,使用系统默认动画。     let customAnimation: NavigationAnimatedTransition = {       onTransitionEnd: (isSuccess: boolean)=>{         ...       },       transition: (transitionProxy: NavigationTransitionProxy)=>{         ...       },       timeout: 100,     };     return customAnimation;   }) }

Step3:customNavContentTransition事件需要返回NavigationAnimatedTransition对象,具体的动画实现需要在NavigationAnimatedTransition的transition属性中实现。transition中通过各个页面在框架中注册的回调函数,配置框架需要的动画属性。案例中各个页面注册了PUSH/POP/REPLACE的各个阶段动画参数。此处需要注意由于Navigation根页面不在栈中,因此无法与NavDestination无法产生跳转联动,因此如果第一个入栈的页面也需要自定义动画,那么就需要判断pageId是否为-1(-1及表示为根视图),如果是-1则不就行动画设置。l7H28资讯网——每日最新资讯28at.com

let customAnimation: NavigationAnimatedTransition = {   ...   transition: (transitionProxy: NavigationTransitionProxy)=>{   // 配置起始参数   if (pageOut != undefined && pageOut.pageID != -1) {   pageOut.getStart(operation, false)(); } if (pageIn != undefined && pageIn.pageID != -1) {   pageIn.getStart(operation, true)(); } // 执行动画 animateTo({   duration: 1000,   curve: Curve.EaseInOut,   onFinish: ()=>{     if (pageOut != undefined && pageOut.pageID != -1) {       pageOut.getFinished(operation, false)();     }     if (pageIn != undefined && pageIn.pageID != -1) {       pageIn.getFinished(operation, true)();     }     transitionProxy.finishTransition();   }}, ()=>{   if (pageOut != undefined && pageOut.pageID != -1) {     pageOut.getEnd(operation, false)();   }   if (pageIn != undefined && pageIn.pageID != -1) {     pageIn.getEnd(operation, true)();   } }) } }

Step4:在各个页面中定义动画回调,并往自定义动画框架中注册。并在组件onDisAppear生命周期中注销框架中的页面动画回调。l7H28资讯网——每日最新资讯28at.com

Step5:定义NavDestination的translate属性,已实现动画效果。l7H28资讯网——每日最新资讯28at.com

@Component export struct loginPageView {   ...   private pageId: number = 0;   @State transX: number = 0;   @State transY: number = 0;    aboutToAppear(): void {     this.pageId = this.pageStack.getAllPathName().length - 1;     let ct : CustomTransition = new CustomTransition();     ct.pageID = this.pageId;     ct.onPushInStart = ct.onPushOutEnd = ct.onPopInStart = ct.onPopOutEnd = ct.onReplaceInStart = ct.onReplaceOutEnd = () => {       this.transX = -300;     }     ct.onPushInEnd = ct.onPushOutStart = ct.onPopInEnd = ct.onPopOutStart = ct.onReplaceInEnd = ct.onReplaceOutStart = () => {       this.transX = 0;     }     ct.onPushInFinish = ct.onPopInFinish  = ct.onReplaceInFinish = () => {       this.transX = 0;     }     ct.onPushOutFinish = ct.onPopOutFinish  = ct.onReplaceOutFinish = () => {       this.transX = -300;     }     // 将页面的动画效果注册到动画框架中     CustomTransitionFW.getInstance().registerNavParam(ct)   }    build() {     NavDestination(){       ...     }.hideTitleBar(true)     .onDisAppear(()=>{       // 组件销毁的时候,需要将页面的动画效果从框架中删除       CustomTransitionFW.getInstance().unRegisterNavParam(this.pageId)     })     // 定义translate,已实现动画     .translate({x: this.transX, y: this.transY, z: 0})   } }

共享元素转场

NavDestination之间可以通过geometryTransition实现共享元素转场。l7H28资讯网——每日最新资讯28at.com

起始页。l7H28资讯网——每日最新资讯28at.com

Step1:为需要实现共享元素转场的元素添加geometryTransition属性,id参数必须在两个NavDestination之间保持一致。l7H28资讯网——每日最新资讯28at.com

起始页代码。l7H28资讯网——每日最新资讯28at.com

Column() {   Image($r('app.media.startIcon'))     .geometryTransition('1')   Text("起始页共享的图片") } .width(100) .height(100)

目的页代码。l7H28资讯网——每日最新资讯28at.com

Column() {   Image($r('app.media.startIcon'))     .geometryTransition('1')   Text("目的页共享的图片") } .width(200) .height(200)

Step2:animateTo方法发起页面跳转(push 或者 pop),触发共享元素转场动画执行。注意此处需要关闭页面默认的跳转动画。l7H28资讯网——每日最新资讯28at.com

Button('跳转目的页')   .width('80%')   .height(40)   .margin(20)   .onClick(() => {     animateTo({ duration: 1000 }, () => {       this.pageInfos.pushPath({ name: 'DestinationPage' }, false)     })   })

想了解更多关于开源的内容,请访问:l7H28资讯网——每日最新资讯28at.com

51CTO 鸿蒙开发者社区l7H28资讯网——每日最新资讯28at.com

https://ost.51cto.coml7H28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-87498-0.htmlNavigation常见场景的解决方案

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 基于设置应用的应用权限、通知设置跳转

下一篇: 时间序列数据处理,不再使用Pandas

标签:
  • 热门焦点
Top
Baidu
map