FAQs About Navigation Animation

Dialog-Type NavDestination Animation Is Not Smooth

Symptom

When the default transition animation NavDestinationMode.DIALOG is used, the following two problems occur:

  • If a mask background color is set for the page, the mask does not disappear immediately when the page is popped; it persists until the content has fully slid out.

    normal

  • If the mask color is applied directly to the content area, the mask exits from top to bottom.

    content

Expected behavior: The mask should fade out while the content area slides down.

Solution

Execute the background color animation in the onWillAppear and onWillDisappear life cycles. The following is an example:

@Builder
export function DialogNavDestinationBuilder() {
  DialogNavDestination();
}

@Component
export struct DialogNavDestination {
  stack: NavPathStack = AppStorage.get<NavPathStack>('basicNavigationStack')!;
  @State backColor: ResourceColor = '#0000000';

  build() {
    NavDestination() {
      Stack() {
        Text('Dialog')
          .fontSize(44)
          .backgroundColor(Color.White)
      }
      .width('100%')
      .height('100%')
    }
    .hideTitleBar(true)
    .backgroundColor(this.backColor)
    .mode(NavDestinationMode.DIALOG)
    .onWillAppear(() => {
      // Fade in the mask.
      this.getUIContext().animateTo({ duration:450 }, () => {
        this.backColor = '#66000000';
      });
    })
    .onWillDisappear(() => {
      // Fade out the mask.
      this.getUIContext().animateTo({ duration: 450 }, () => {
        this.backColor = '#00000000';
      });
    })
  }
}

modify

Router and Navigation Animation Conflict

Symptom

When a router jump navigates to a navigation page, and the page immediately pushes a NavDestination in its aboutToAppear callback, the page entrance animation and the NavDestination push animation play simultaneously, resulting in a poor visual experience.

Solution

Disable the push animation in the aboutToAppear callback.

@Entry
@Component
struct NavigationPage {
  navStack: NavPathStack = new NavPathStack();

  aboutToAppear(): void {
    AppStorage.setOrCreate<NavPathStack>('basicNavigationStack', this.navStack);
    this.navStack.pushPath({ name: 'animation-BasicNavDestination' }, false); // Disable animation for the push operation.
  }

  build() {
    Navigation(this.navStack) {
      // ...
    }
  }
}

Pop Animation Plays When pop and push Are Performed Together

Symptom

When the top page is popped and another page is pushed immediately afterward, the pop animation of the removed page is displayed instead of the push animation of the new page.

this.stack.pop();
this.stack.pushPath({ name: 'animation-BasicNavDestination' });

Solution

Navigation calculates the final stack state after all operations and executes only one animation per transition.

The animation type is determined by the top page before the operation: If that page is no longer in the stack afterward, a pop animation is played. If that page remains in the stack, a push animation is played.

In the example above, the original top page is removed, so the pop animation is triggered.

To remove one page and push another while displaying a push animation, set the new page's launch mode to NEW_INSTANCE.

this.stack.pop();
this.stack.pushPath({ name: 'animation-BasicNavDestination' }, { launchMode: LaunchMode.NEW_INSTANCE });

Is There an End Callback for the Default Transition Animation?

The system does not provide an end callback for the default transition animation. Only custom transition animations support an end callback. Related APIs: NavDestinationTransition and NavigationAnimatedTransition.

How Do I Implement a Shared Element Transition Between Navigation and NavDestination Components?

Shared element transitions are only supported between NavDestination pages; transitions between the NavBar and a NavDestination do not support shared element transitions.

The shared element transition requires the geometryTransition API call and following operations:

For details, see Defining a Shared Element Transition.

The zIndex attribute modifies a component's display layer. Setting it on the NavDestination component overrides the system-managed layering and may break transition animations. As such, avoid setting zIndex directly on NavDestination.

Similarly, avoid setting the following attributes directly on NavDestination (they may conflict with system animations): transition, geometryTransition, sharedTransition, and animation. If these effects are required for your design, apply the attributes to the content nodes inside the NavDestination component instead.