HarmonyOS鸿蒙Next中Navigation实现类似闪屏的效果

HarmonyOS鸿蒙Next中Navigation实现类似闪屏的效果 使用navigation组件实现类似闪屏的效果,需要把home页面替换掉,但是使用replacePathByName方法无法彻底将home页面替换,点击返回按钮还是会回到home页面,看到相关帖子说navigation栈底元素无法被移除,请问是否有官网的文档说明navigation栈底元素无法被移除

cke_12765.png

cke_11357.png

cke_11938.png


更多关于HarmonyOS鸿蒙Next中Navigation实现类似闪屏的效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

【解决方案】

完整的Navigation实现闪屏页方式可以参考demo:Navigation实现闪屏页

  • 方案一:通过隐藏导航页和重写返回键的方法,实现不返回开屏页。
    1. 开屏页通过导航页Navigation容器组件实现;
    2. Navigation启动时,通过this.pathStack.pushPathByName直接跳转到MainPage界面;
    3. 添加路由拦截,当路由目标页面名称为navBar(Navigation首页名字)时,就跳转到MainPage界面;
    4. 设置Navigation属性hideNavBar为true,隐藏返回导航页。

示例代码如下:

// MainPage.ets
@Component
struct MainPage {
  pageName: string = '';
  pathStack: NavPathStack | undefined = undefined;

  build() {
    NavDestination() {
      Column() {
        Text('this is MainPage').fontSize(24)
        Button(`push Page`).width('80%').margin({ top: 10, bottom: 10 })
          .onClick(() => {
            this.pathStack?.pushPathByName('Page', '');
          })
        Button(`pop`).width('80%').margin({ top: 10, bottom: 10 })
          .onClick(() => {
            this.pathStack?.pop();
          })
      }
    }.title('MainPage')
    .onReady((context: NavDestinationContext) => {
      this.pageName = context.pathInfo.name;
      this.pathStack = context.pathStack;
    })
  }
}
// Page.ets
@Component
struct Page {
  pageName: string = '';
  pathStack: NavPathStack | undefined = undefined;

  build() {
    NavDestination() {
      Column() {
        Text('this is Page').fontSize(24)
        Button(`pop`).width('80%').margin({ top: 10, bottom: 10 })
          .onClick(() => {
            this.pathStack?.pop();
          })
      }
    }.title('Page')
    .onReady((context: NavDestinationContext) => {
      this.pageName = context.pathInfo.name;
      this.pathStack = context.pathStack;
    })
  }
}
// Index.ets(即启动页)
import { promptAction } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  pathStack: NavPathStack = new NavPathStack();
  @State hideNavBar: boolean = false

  aboutToAppear(): void {
    setTimeout(() => {
      this.pathStack.pushPathByName('MainPage', undefined, false);
      this.hideNavBar = true
      // 添加路由拦截功能
      this.pathStack.setInterception({
        willShow: (from: NavDestinationContext | NavBar, to: NavDestinationContext | NavBar,
          operation: NavigationOperation, isAnimated: boolean) => {
          // 如果返回到首页,就跳转为MainPage页面
          if (to == 'navBar') {
            promptAction.showToast({ message: '无法返回到首页' })
            this.pathStack.pushPathByName('MainPage', undefined, false);
          }
        }
      })
    }, 2000)
  }

  @Builder
  pagesMap(name: string, param: number) {
    if (name == 'MainPage') {
      MainPage()
    } else if (name == 'Page') {
      Page()
    }
  }

  build() {
    Navigation(this.pathStack) {
      Text('欢迎进入APP').fontSize(30)
    }.title('启动页')
    .hideNavBar(this.hideNavBar)
    .navDestination(this.pagesMap)
  }
}
  • 方案二:通过销毁作为开屏页的NavDestination页面,实现不返回开屏页。
    1. 首页使用Navigation作为根容器,闪屏页使用NavDestination作为根容器;
    2. 在首页的aboutToAppear回调中跳转到闪屏页;
    3. 闪屏页在定时器setTimeout回调中通过removeByName销毁自身。

示例代码如下:

// Index.ets
@Entry
@Component
struct Index {
  @Provide('navPathStack') navPathStack: NavPathStack = new NavPathStack();

  @Builder
  pageMap(name: string) {
    if (name === "Splash") {
      Splash()
    }
  }

  aboutToAppear(): void {
    this.navPathStack.pushPathByName("Splash", "")
  }

  build() {
    Navigation(this.navPathStack) {
      Column() {
        Text('首页')
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }
    .hideToolBar(true)
    .navDestination(this.pageMap)
  }
}
// Splash.ets
@Component
export struct Splash {
  @Consume('navPathStack') navPathStack: NavPathStack;

  aboutToAppear(): void {
    setTimeout(() => {
      this.navPathStack.removeByName("Splash")
    }, 2000)
  }

  build() {
    NavDestination() {
      Column() {
        Text('闪屏页')
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }
    .hideTitleBar(true)
  }
}

【背景知识】

  • Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用。其主要用于实现页面间以及组件内部的页面跳转。removeByName方法可以将指定的NavDestination页面删除。
  • NavDestination是Navigation的子页面的根容器,onBackPressed方法可以重写返回键逻辑。

更多关于HarmonyOS鸿蒙Next中Navigation实现类似闪屏的效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


// 在闪屏页销毁时重建根容器
import { NavPathStack } from '@kit.ArkUI';

@Component
struct SplashPage {
  @Provide('navStack') navStack: NavPathStack = new NavPathStack();

  aboutToDisappear() {
    this.navStack.popAll();
    this.navStack.pushPathByName('MainPage');
  }
}

HarmonyOS的社区里有很多技术大牛分享经验,学到了很多有用的知识。

可以使用一个状态变量控制,如果想着全局控制这个 isShowHome, 可以把它放到 AppStorage 里面

@State isShowHome: boolean = true

Navigation(){
  if (this.isShowHome) {
    PageHome()
  } else {
    PageOther()
  }
}

在HarmonyOS Next中,可通过Navigation组件结合页面导航与动画实现类似闪屏效果。使用Navigation的页面栈管理能力,在应用启动时加载初始页面作为闪屏页,并利用Navigation的过渡动画或自定义动画效果(如淡入淡出)展示短暂界面。随后通过路由跳转快速切换至主页面。关键步骤包括:在EntryAbility中配置初始路由为闪屏页,在闪屏页使用定时器或异步任务延迟后调用router.pushUrl跳转。全程基于ArkTS声明式开发,无需依赖Java或C。

在HarmonyOS Next中,Navigation组件的栈底页面(即初始页面)确实无法通过replacePathByName方法移除。这是Navigation组件的设计机制,目的是确保应用始终有一个可用的根页面,避免出现空栈状态导致应用无响应或意外退出。

根据官方设计规范,栈底页面作为Navigation容器的基础,不允许被完全替换或移除。当你使用replacePathByName替换栈底页面时,实际上是在栈底之上覆盖新页面,但原始栈底页面仍保留在导航栈中。因此点击返回按钮时,会回到初始的home页面。

要实现类似闪屏效果并彻底替换home页面,建议采用以下方案:

  1. 将闪屏页面设计为应用的初始页面(即Navigation的根页面)
  2. 在闪屏页面完成展示后,使用router.clear清空整个导航栈
  3. 立即使用router.replaceUrl跳转到真正的home页面

这种方法可以确保闪屏页面不会留在导航栈中,用户点击返回时将直接退出应用,符合闪屏页面的典型交互逻辑。

关于栈底页面不可移除的具体说明,可参考官方Navigation组件文档中"页面栈管理"章节的相关约束说明。

回到顶部