HarmonyOS鸿蒙Next中如何解决navigation初始页进栈无转场动画问题

HarmonyOS鸿蒙Next中如何解决navigation初始页进栈无转场动画问题 navigation分栏时初始页进栈无动画,与后续页面的进出栈动画不统一,有没有什么处理方法?

6 回复

可以在分栏模式下右侧使用NavDestination作为占位页,后续push的页面就有动画了。

import { common } from '@kit.AbilityKit';

@Entry
@Component
struct StartPage {
  pathStack: NavPathStack = new NavPathStack();

  aboutToAppear() {
    this.pathStack.pushPathByName('DefaultPage', '', false);
    // 设置Navigation页面跳转拦截回调
    this.pathStack.setInterception({
      willShow: (from: NavDestinationContext | 'navBar', to: NavDestinationContext | 'navBar',
        operation: NavigationOperation, animated: boolean) => {
        console.info(`${from} ${to} ${operation} ${animated}`);
        // 如果要返回到首页,就push到占位页
        if (to === 'navBar') {
          this.pathStack.pushPathByName('DefaultPage', '', false);
        }
      }
    });
  }

  @Builder
  pageMap(name: string) {
    if (name === 'DefaultPage') {
      DefaultPage();
    } else if (name === 'PageA') {
      PageA();
    }
  }

  build() {
    Navigation(this.pathStack) {
      Column() {
        Button('click')
          .onClick(() => {
            this.pathStack.pushPathByName('PageA', null, true);
          });
      }.justifyContent(FlexAlign.Center)
      .height('100%')
      .width('100%');
    }
    .navDestination(this.pageMap)
    .mode(NavigationMode.Split)
    .hideTitleBar(true)
    .navBarWidth('50%');
  }
}

@Component
export struct DefaultPage {
  pathStack: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Column() {
        Text('DefaultPage');
      }.width('100%').height('100%');
    }.title('DefaultPage')
    .onReady((ctx: NavDestinationContext) => {
      this.pathStack = ctx.pathStack;
    })
    .onBackPressed(() => {
      // 返回true表示自定义返回,能避免返回空白页面。返回false则表示系统默认返回,会返回空白页面。
      try {
        // 获取Context
        let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
        // 通过Context获取windowStage
        let windowStage = context.windowStage;
        // 通过windowStage获取主窗口
        let mainWindow = windowStage.getMainWindowSync();
        // 将主窗口最小化
        mainWindow.minimize();
      } catch (exception) {
        console.error(`Failed to obtain the top window. Cause code: ${exception.code}, message: ${exception.message}`);
      }
      return true;
    });
  }
}

@Component
export struct PageA {
  pathStack: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Column() {
        Text('PageA');
        Button('清空路由栈')
          .onClick(() => {
            this.pathStack.clear();
          });
      }.width('100%').height('100%');
    }.title('PageA')
    .onReady((ctx: NavDestinationContext) => {
      this.pathStack = ctx.pathStack;
    });
  }
}

更多关于HarmonyOS鸿蒙Next中如何解决navigation初始页进栈无转场动画问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


有以下几种处理方式:

方法1: 使用 animated 参数控制单次动画

在初始页面进栈时,可以通过 pushPath 等路由方法的 animated 参数来控制是否开启动画:

// 在 onAppear 或初始化时,设置 animated 为 true 开启动画

 this.pageStack.pushPathByName('PageOne', null, true); // 第三个参数设为 true

 // 或者使用 pushPath

 this.pageStack.pushPath({ name: 'PageOne' }, true); // 第二个参数设为 true

说明:

  • animated 参数默认为 true 表示有转场动画
  • 设置为 false 可以关闭单次转场动画,不影响下次转场
  • 这是最简单直接的方法

方法2: 延迟初始页面加载

可以将初始页面的加载稍微延迟,让 Navigation 完成首次渲染后再触发路由:

 Navigation(this.pageStack) {

   // ...

 }

 .onAppear(() => {

   // 使用 setTimeout 延迟执行

   setTimeout(() => {

     this.pageStack.pushPathByName('PageOne', null, true);

   }, 100);

 })

方法3: 使用 animateTo 包裹路由操作

参考文档中共享元素转场的做法,可以用 animateTo 包裹路由操作:

this.getUIContext()?.animateTo({ duration: 300 }, () => {

   this.pageStack.pushPath({ name: 'PageOne' }, false); // 这里 animated 设为 false

 });

方法4: 全局动画控制

如果想统一控制所有转场动画,可以使用 disableAnimation:

pageStack: NavPathStack = new NavPathStack();

 aboutToAppear(): void {

   // 初始化时先关闭动画

   this.pageStack.disableAnimation(true);

   // 加载初始页面

   this.pageStack.pushPathByName('PageOne', null);

   // 再开启动画,后续操作就有动画了

   this.pageStack.disableAnimation(false);

 }

期待HarmonyOS能在未来带来更多创新的技术和理念。

拿平板举例,默认是stack布局,然后点击按钮后push页面变成split。,这个时候页面被压进内容区,和导航区行成双栏。但是页面被放进内容区时相当于是起始页,并没办法调用nv默认的压入动画,这个算是nv的特性,不知道有没有解决办法🤔,

在HarmonyOS Next中,navigation初始页无转场动画是预期行为。navigation组件在首次加载时,初始页作为根页面直接显示,不触发页面转场动画。若需为后续页面跳转添加动画,可在调用router.pushUrl()时,在RouterOptions中配置动画参数,例如使用router.AnimationType.PUSH。

在HarmonyOS Next中,Navigation组件初始页进栈时默认不播放转场动画,这是为了确保应用启动时的流畅性和即时性。若需实现初始页与后续页面动画的统一,可通过以下方式处理:

  1. 使用延迟动画触发:在初始页加载完成后,通过setTimeout或页面生命周期回调(如aboutToAppear)短暂延迟后,手动为Navigation组件或初始页的容器添加一个自定义的入场动画(例如淡入或平移效果)。这能模拟出转场效果,但需注意延迟时间不宜过长。

  2. 封装自定义Navigation组件:继承或封装Navigation,重写其初始加载逻辑。在初始页入栈时,主动调用页面转场动画接口(如pageTransition相关方法),强制启用动画效果。需注意HarmonyOS Next的API支持情况,确保方法兼容。

  3. 统一使用自定义路由管理:若不依赖Navigation内置栈管理,可自行管理页面栈,并通过全局动画控制器控制所有页面(包括初始页)的进出场。初始页加载时,手动触发与后续页面一致的动画效果。

  4. 检查分栏模式配置:分栏模式(如NavigationMode.Split)可能影响动画行为。确认分栏布局的配置是否正确,或尝试调整分栏参数,部分场景下动画异常可能与布局约束有关。

关键点:初始页无动画是系统默认行为,修改需权衡启动性能。若强制添加动画,需测试低端设备上的流畅度,避免影响用户体验。建议参考HarmonyOS官方文档中的Navigation动画示例,适配具体场景。

回到顶部