HarmonyOS navigation导航转场动画怎么写

我路由用的navagtion想知道从一个页面跳转到另外一个页面的动画怎么写,比如我页面1 打开页面2 ,页面2 从底部弹出

HarmonyOS
1天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

转场动画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;
  }
}
分享
微博
QQ
微信
回复
1天前
相关问题
HarmonyOS Navigation实现Dialog转场动画
34浏览 • 1回复 待解决
救命,鸿蒙怎么动画
5780浏览 • 2回复 待解决
HarmonyOS Navigation转场?
139浏览 • 0回复 待解决
HarmonyOS Navigation导航
17浏览 • 1回复 待解决
HarmonyOS 如何自定义导航转场
56浏览 • 1回复 待解决
如何实现动画转场效果
872浏览 • 1回复 待解决
Navigation如何隐藏导航
2205浏览 • 1回复 待解决
HarmonyOS 页面内的组件转场动画
441浏览 • 1回复 待解决
HarmonyOS Refresh和页面转场动画demo
31浏览 • 1回复 待解决
HarmonyOS 无感转场动画推荐方案
123浏览 • 1回复 待解决
Tabs 出现/消失转场动画效果
409浏览 • 1回复 待解决
如何全局设置页面转场动画
763浏览 • 1回复 待解决