转场动画demo请参考:// Index.ets import { CustomTransition, AnimateCallback } from './CustomNavigationUtils' import { pageOneTmp } from './PageOne' import {PageTwoTemp} from './PageTwo' @Entry @Component struct NavigationExample { @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack() @Builder PageMap(name: string) { if (name === 'pageOne') { pageOneTmp({pageId: Date.now()}) } else if (name === 'pageTwo') { PageTwoTemp({pageId: Date.now()}) } } aboutToAppear() { if (this.pageInfos === undefined) { this.pageInfos = new NavPathStack(); } this.pageInfos.pushPath({name: 'pageOne'}, false) } build() { Navigation(this.pageInfos) { }.title('NavIndex').navDestination(this.PageMap) .hideNavBar(true) .customNavContentTransition((from: NavContentInfo, to: NavContentInfo, operation: NavigationOperation) => { if (from.mode == NavDestinationMode.DIALOG || to.mode == NavDestinationMode.DIALOG) { return undefined; } console.log(`info: ${to.name}, index: ${to.index}, mode: ${to.mode}`); console.log(`pre info: ${from.name}, index: ${from.index}, mode: ${from.mode}`); console.log(`operation: ${operation}`) if (from.index === -1 || to.index === -1) { console.log("undefined") return undefined; } let customAnimation: NavigationAnimatedTransition = { onTransitionEnd: (isSuccess: boolean)=>{ console.log(`current transition result is ${isSuccess}`); }, timeout: 700, transition: (transitionProxy: NavigationTransitionProxy)=>{ console.log("trigger transition callback"); let fromParam: AnimateCallback = CustomTransition.getInstance()?.getAnimateParam(from.index); let toParam: AnimateCallback = CustomTransition.getInstance()?.getAnimateParam(to.index); if (fromParam.start != undefined) { console.log("fromParam.start"); // push, x = 0 fromParam.start(operation == NavigationOperation.PUSH, true); } if (toParam.start != undefined) { console.log("toParam.start"); // push, x = 300 toParam.start(operation == NavigationOperation.PUSH, false); } animateTo({duration: 1200, onFinish: ()=>{ console.log("animateTo start"); if (fromParam.onFinish != undefined) { console.log("fromParam onFinish"); // push 0 fromParam.onFinish(operation === NavigationOperation.PUSH, true); } if (toParam.onFinish != undefined) { console.log("toParam onFinish"); // push 0 toParam.onFinish(operation === NavigationOperation.PUSH, false); } transitionProxy.finishTransition(); }}, ()=>{ if (fromParam.finish != undefined) { console.log("fromParam finish"); // push x = -300 fromParam?.finish(operation === NavigationOperation.PUSH, true) } if (toParam.finish != undefined) { console.log("toParam finish"); // push x = 0 toParam?.finish(operation === NavigationOperation.PUSH, false); } }) } }; return customAnimation; }) } } import {CustomTransition} from './CustomNavigationUtils' @Component export struct pageOneTmp { @Consume('pageInfos') pageInfos: NavPathStack @State x: number = 0 @State scaleVal: number = 1 pageId: number = 0; aboutToAppear() { this.pageId = this.pageInfos.getAllPathName().length - 1; CustomTransition.getInstance().registerNavParam(this.pageId, (isPush: boolean, isExit: boolean) => { this.x = isExit ? 0 : 300; }, (isPush: boolean, isExit: boolean)=> { this.x = isExit ? -300 : 0; }, (isPush: boolean, isExit: boolean) => { console.log("PageTwo x finish : " + this.x) this.x = 0; }, 200); } build() { NavDestination() { Column() { Button('pageTwo', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pageInfos.pushPathByName('pageTwo', null) //将name指定的NavDestination页面信息入栈,传递的数据为param }) Button('pageOne', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pageInfos.pushPathByName('pageOne', null) //将name指定的NavDestination页面信息入栈,传递的数据为param }) }.width('100%').height('100%') }.title('pageOne') .mode(NavDestinationMode.STANDARD) .onBackPressed(() => { const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素 console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo)) return true }) .onDisAppear(()=>{ console.log("pageone onDisAppear"); CustomTransition.getInstance().unRegisterNavParam(this.pageId) }) .translate({x: 0, y: this.x, z: 0}) .backgroundColor(Color.White) } } import {CustomTransition} from './CustomNavigationUtils' @Component export struct PageTwoTemp { @Consume('pageInfos') pageInfos: NavPathStack @State x: number = 300 pageId:number = 0; aboutToAppear() { this.pageId = this.pageInfos.getAllPathName().length - 1; CustomTransition.getInstance().registerNavParam(this.pageId, (isPush: boolean, isExit: boolean) => { this.x = isExit ? 0 : isPush ? 300 : -300; console.log("PageTwo x start is : " + this.x) }, (isPush: boolean, isExit: boolean)=> { this.x = isExit ? isPush ? -300 : 300 : 0; console.log("PageTwo x end is : " + this.x) }, (isPush: boolean, isExit: boolean) => { this.x = 0; console.log("PageTwo x finish : " + this.x) }, 2000); } build() { NavDestination() { Column() { Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pageInfos.pushPathByName('pageOne', null) //将name指定的NavDestination页面信息入栈,传递的数据为param }) Button('pageTwo', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pageInfos.pushPathByName('pageTwo', null) //将name指定的NavDestination页面信息入栈,传递的数据为param }) }.width('100%').height('100%') }.title('pageTwo') .onBackPressed(() => { console.log("pagetwo onBackPressed"); const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素 console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo)) return true }) .onDisAppear(()=>{ console.log("pagetwo onDisAppear"); CustomTransition.getInstance().unRegisterNavParam(this.pageId) }) .opacity(0.5) .translate({x: 0, y: 0, z: this.x}) .backgroundColor(Color.White) } } // CustomNavigationUtils.ts // 自定义接口,用来保存某个页面相关的转场动画回调和参数 export interface AnimateCallback { finish: ((isPush: boolean, isExit: boolean) => void | undefined) | undefined; start: ((isPush: boolean, isExit: boolean) => void | undefined) | undefined; onFinish: ((isPush: boolean, isExit: boolean) => void | undefined) | undefined timeout: (number | undefined) | undefined; } const customTransitionMap: Map<number, AnimateCallback> = new Map() export class CustomTransition { private constructor() { } static delegate = new CustomTransition(); static getInstance() { return CustomTransition.delegate; } registerNavParam(name: number, startCallback: (operation: boolean, isExit: boolean) => void, endCallback:(operation: boolean, isExit: boolean) => void, onFinish: (opeation: boolean, isExit: boolean) => void, timeout: number): void { console.log("registerNavParam"); if (customTransitionMap.has(name)) { let param = customTransitionMap.get(name); if (param != undefined) { param.start = startCallback; param.finish = endCallback; param.onFinish = onFinish; param.timeout = timeout; return; } } let params: AnimateCallback = {timeout: timeout, start: startCallback, finish: endCallback, onFinish: onFinish}; customTransitionMap.set(name, params); } unRegisterNavParam(name: number): void { console.log("unRegisterNavParam"); customTransitionMap.delete(name); } getAnimateParam(name: number): AnimateCallback { console.log("unRegisterNavParam"); let result: AnimateCallback = { start: customTransitionMap.get(name)?.start, finish: customTransitionMap.get(name)?.finish, timeout: customTransitionMap.get(name)?.timeout, onFinish: customTransitionMap.get(name)?.onFinish }; return result; } }
转场动画demo请参考: