# Navigation转场动画

Navigation存在默认转场动画，此外也提供了自定义转场和共享元素转场能力。

#### 系统默认转场

系统提供了多种默认转场类型，可以通过NavDestination.systemTransition接口实现，具体示例请参考设置指定的NavDestination系统转场。

*   NavDestination的默认转场动画使用弹簧曲线，其时长与物理曲线参数有关，而且不同设备上的默认动画不同，因此默认转场动画时长不可控，不建议与业务耦合，若需要监听动画结束，建议使用自定义转场。
*   Dialog类型的NavDestination默认无转场动画；从API version 13开始，Dialog类型的NavDestination默认存在系统转场动画。

默认转场动画支持关闭，有两种方式：

*   全局关闭。
    
    Navigation可以通过NavPathStack提供的disableAnimation接口，关闭或打开当前Navigation的所有转场动画。
    
    ```
    pageStack: NavPathStack = new NavPathStack();
    
    aboutToAppear(): void {
      this.pageStack.disableAnimation(true);
    }
    ```
    
*   单次关闭。
    
    NavPathStack中提供的pushPath、pop、replacePath等接口可以设置animated参数，该参数用于设置是否有转场动画。需要单次关闭转场动画，可以将animated置为false，设置后不影响下次转场动画。
    

#### 自定义转场

Navigation提供了两种自定义转场接口：Navigation自定义转场、NavDestination自定义转场。

*   Navigation自定义转场动画由customNavContentTransition事件提供，适用于控制Navigation内所有页面的场景，统一转场动画效果。步骤如下，具体示例代码请参考设置可交互转场动画。
    
    1.  实现一个自定义转场动画工具类CustomNavigationUtils，通过一个Map管理各页面的自定义动画对象CustomTransition。页面在创建时注册其自定义转场动画对象，在销毁时取消注册。
    2.  实现一个转场协议对象NavigationAnimatedTransition。其中，transition属性为自定义转场动画的具体实现，开发者需在此实现自己的转场动画逻辑，系统在转场开始时会调用此方法。timeout属性表示转场结束的超时时间，默认为1000ms。onTransitionEnd为转场结束时的回调。
    3.  调用customNavContentTransition方法并返回实现的转场协议对象，若返回undefined，则使用系统默认转场。
*   NavDestination支持自定义转场动画，适用于控制单个页面的转场效果。通过设置customTransition属性即可实现单个页面的自定义转场效果。步骤如下，示例代码请参考设置NavDestination自定义转场。
    
    1.  实现NavDestination的转场代理NavDestinationTransitionDelegate，针对不同的堆栈操作类型返回自定义的转场协议对象NavDestinationTransition。其中，event是必填参数，需在此处实现自定义转场动画的逻辑，onTransitionEnd、duration、curve与delay为可选参数，分别对应动画结束后的回调、动画持续时间、动画曲线类型与开始前的延时。如果在转场代理中返回多个转场协议对象，这些动画效果将逐层叠加。
    2.  通过调用NavDestination组件的customTransition属性，并传入上述实现的转场代理，完成自定义转场的设置。

同时使用customNavContentTransition和customTransition时，customNavContentTransition优先级更高。

#### 共享元素转场

NavDestination之间切换时可以通过geometryTransition实现共享元素转场，示例如下。配置了共享元素转场的页面，同时需要关闭系统默认的转场动画，否则默认动画会与共享元素动画叠加，导致效果异常。

1.  为需要实现共享元素转场的组件添加geometryTransition属性，id参数必须在两个NavDestination之间保持一致。
    
    ```
    // 起始页配置共享元素id
    NavDestination() {
      Column() {
        // ...
        // 请将$r('app.media.startIcon')替换为实际资源文件
        Image($r('app.media.startIcon'))
          .geometryTransition('sharedId')
          .width(100)
          .height(100)
      }
    }.title('FromPage')
    ```
    
    ```
    // 目的页配置共享元素id
    NavDestination() {
      Column() {
        // 请将$r('app.media.startIcon')替换为实际资源文件
        Image($r('app.media.startIcon'))
          .geometryTransition('sharedId')
          .width(200)
          .height(200)
      }
    }
    .title('ToPage')
    ```
    
2.  将页面路由的操作，放到animateTo动画闭包中，配置对应的动画参数以及关闭系统默认的转场。
    
    ```
    NavDestination() {
      Column() {
        // $r('app.string.ToPage')需要开发者替换为实际的资源文件，资源文件中的value值为“跳转到目的页”
    
        Button($r('app.string.ToPage'))
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.getUIContext()?.animateTo({ duration: 1000 }, () => {
              this.navPathStack.pushPath({ name: 'ToPage' }, false)
            });
          })
        // ...
      }
    }.title('FromPage')
    ```