HarmonyOS Navigation转场动画能否只对单个页面使用自定义转场动画

为实现转场动画而参考下文:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-navigation-V5#%E7%A4%BA%E4%BE%8B3

但是此处存在一个疑问:

如果customNavContentTransition返回为undefined,则使用系统默认转场动画

如果customNavContentTransition返回了NavigationAnimatedTransition对象,则必须同时注册fromParam和toParam才能使from页面和to页面有动画。但是,假如我想要from页面保持默认动画,to页面使用自定义动画,则无法做到。这该怎么处理

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

页面打开顺序是 A -> B -> C

操作步骤一:A 打开B时,A不动,B升起,B返回A时,B降下,A不动

操作步骤二:B打开C,使用默认的推入推出动画,C返回B也是默认动画

针对操作步骤一,通过自定义转场实现,分别定义a、b页面转场动画

针对操作步骤二,customNavContentTransition返回undefined

// Index.ets
import { CustomTransition, AnimateCallback } from './CustomNavigationUtils'

@Entry
@Component
struct NavigationExample {
  @Provide('NavPathStack') pageInfos: NavPathStack = new NavPathStack()

  aboutToAppear() {
    if (this.pageInfos === undefined) {
      this.pageInfos = new NavPathStack();
    }
    this.pageInfos.pushPath({ name: 'pageOne1' }, false)
  }

  build() {
    Navigation(this.pageInfos) {
    }.title('NavIndex')
    .hideNavBar(true)
    .customNavContentTransition((from: NavContentInfo, to: NavContentInfo, operation: NavigationOperation) => {
      if (from.mode == NavDestinationMode.DIALOG || to.mode == NavDestinationMode.DIALOG) {
        return undefined;
      }
      console.log(`current 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) {
        return undefined;
      }
      if(from.name == 'pageThree1' || to.name == 'pageThree1') { // b进入c页面或者c返回b页面
        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");
          // 从封装类CustomTransition中根据子页面的序列获取对应的转场动画回调
          let fromParam: AnimateCallback = CustomTransition.getInstance().getAnimateParam(from.index);
          let toParam: AnimateCallback = CustomTransition.getInstance().getAnimateParam(to.index);
          if (fromParam.start != undefined) {
            fromParam.start(operation == NavigationOperation.PUSH, true);
          }
          if (toParam.start != undefined) {
            toParam.start(operation == NavigationOperation.PUSH, false);
          }
          //自定义转场动画,转场开始时系统调用
          animateTo(
            {
              duration: 1000,
              onFinish: () => {
                if (fromParam.onFinish != undefined) {
                  fromParam.onFinish(operation === NavigationOperation.PUSH, true);
                }
                if (toParam.onFinish != undefined) {
                  toParam.onFinish(operation === NavigationOperation.PUSH, true);
                }
                transitionProxy.finishTransition();
              }
            },
            () => {
              if (fromParam.finish != undefined) {
                fromParam.finish(operation === NavigationOperation.PUSH, true);
              }
              if (toParam.finish != undefined) {
                toParam.finish(operation === NavigationOperation.PUSH, false);
              }
            })
        }
      };
      return customAnimation;
    })
  }
}


// PageOne.ets
import { CustomTransition } from './CustomNavigationUtils'

@Builder
export function PageOneBuilder(name: string, param: Object) {
  PageOne1()
}

@Component
export struct PageOne1 {
  @Consume('NavPathStack') 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) => {
        console.log('pagestart One ')
        this.x = isExit ? 0 : 300;
      },
      (isPush: boolean, isExit: boolean) => {
        console.log('pagefinish One')
        this.x = isExit ? -300 : 0;
      },
      (isPush: boolean, isExit: boolean) => {
        console.log('pageonfinish One ')
        this.x = 0;
      },
      200
    );
  }

  build() {
    NavDestination() {
      Column() {
        Text('p1X:' + this.x)
        Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.pageInfos.pushPathByName('pageTwo1', null) //将name指定的NavDestination页面信息入栈,传递的数据为param
          })
      }.width('100%').height('100%')
    }
    .title('PageOne1')
    .mode(NavDestinationMode.STANDARD)
    .onBackPressed(() => {
      const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素
      console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))
      return true
    })
    .onDisAppear(() => {
      CustomTransition.getInstance().unRegisterNavParam(this.pageId)
    })
    .onReady((context: NavDestinationContext) => {
      this.pageInfos = context.pathStack
    })
    // .translate({ x: this.x, y: 0, z: 0 })
    .backgroundColor(Color.White)
  }
}


// PageTwo.ets
import { CustomTransition } from './CustomNavigationUtils'

@Builder
export function PageTwoBuilder(name: string, param: Object) {
  PageTwo1()
}

@Component
export struct PageTwo1 {
  @Consume('NavPathStack') pageInfos: NavPathStack
  @State x: number = 300
  @State y: number = 300
  pageId: number = 0

  aboutToAppear() {
    this.pageId = this.pageInfos.getAllPathName().length - 1;
    CustomTransition.getInstance().registerNavParam(
      this.pageId,
      (isPush: boolean, isExit: boolean) => {
        console.log('pagestart Two ')
        // this.x = isExit ? 0 : isPush ? 300 : -300;
        if (isExit) {
          if (!isPush) { // b回a
            this.x = 0;
            this.y = 0;
          }
        } else {
          if (isPush) { // a到b
            this.x = 0;
            this.y = 300;
          }
        }
      },
      (isPush: boolean, isExit: boolean) => {
        console.log('pagefinish Two ')
        // this.x = isExit ? isPush ? -300 : 300 : 0;
        if (isExit) {
          if (!isPush) { // b回a
            this.x = 0;
            this.y = 300;
          }
        } else {
          if (isPush) { // a到b
            this.x = 0;
            this.y = 0;
          }
        }
      },
      (isPush: boolean, isExit: boolean) => {
        console.log('pageonfinish Two')
        this.x = 0;
        this.y = 0;
      },
      10000
    )
  }

  build() {
    NavDestination() {
      Column() {
        Text('p2X:' + this.x)
        Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.pageInfos.pushPathByName('pageThree1', null) //将name指定的NavDestination页面信息入栈,传递的数据为param
          })
      }.width('100%').height('100%')
    }
    .title('PageTwo1')
    .onBackPressed(() => {
      const popDestinationInfo = this.pageInfos.pop() // 弹出路由栈栈顶元素
      console.log('pop' + '返回值' + JSON.stringify(popDestinationInfo))
      return true
    })
    .onDisAppear(() => {
      CustomTransition.getInstance().unRegisterNavParam(this.pageId)
    })
    .onReady((context: NavDestinationContext) => {
      this.pageInfos = context.pathStack;
    })
    // .opacity(0.5)
    .translate({ x: this.x, y: this.y })
    .backgroundColor(Color.White)
  }
}
分享
微博
QQ
微信
回复
23h前
相关问题
自定义弹窗自定义转场动画
1165浏览 • 1回复 待解决
HarmonyOS Navigation实现Dialog转场动画
10浏览 • 0回复 待解决
如何全局设置页面转场动画
755浏览 • 1回复 待解决
HarmonyOS 页面内的组件转场动画
438浏览 • 1回复 待解决
HarmonyOS Refresh和页面转场动画demo
16浏览 • 1回复 待解决
HarmonyOS 如何自定义导航转场
12浏览 • 1回复 待解决
如何实现动画转场效果
854浏览 • 1回复 待解决
Tabs 出现/消失转场动画效果
402浏览 • 1回复 待解决
HarmonyOS 无感转场动画推荐方案
107浏览 • 1回复 待解决
HarmonyOS Navigation转场?
135浏览 • 0回复 待解决