HarmonyOS鸿蒙Next中继续请教一个HMRouter页面跳转的问题,求助大佬们!!!

HarmonyOS鸿蒙Next中继续请教一个HMRouter页面跳转的问题,求助大佬们!!! 当前的页面效果是这样的:

cke_741.png cke_1449.png

代码如下:

// Index.ets

import { HMDefaultGlobalAnimator, HMNavigation } from "@hadss/hmrouter";
import { AttributeUpdater } from "@kit.ArkUI";
import { HomePage } from "./HomePage";

@Entry
@Component
export struct Index {

  modifier: MyNavModifier = new MyNavModifier();

  build() {
    // @Entry中需要再套一层容器组件,Column或者Stack
    Column(){
      // 使用HMNavigation容器
        HMNavigation({
          navigationId: 'MyPalsNavigation',
          options: {
            standardAnimator: HMDefaultGlobalAnimator.STANDARD_ANIMATOR,
            dialogAnimator: HMDefaultGlobalAnimator.DIALOG_ANIMATOR,
            modifier: this.modifier
          }
        }){
          HomePage();
        }
    }
    .height('100%')
    .width('100%')
  }


}

class MyNavModifier extends AttributeUpdater<NavigationAttribute> {
  initializeModifier(instance: NavigationAttribute): void {
    instance.hideTitleBar(true)
    instance.mode(NavigationMode.Auto);
    instance.navBarWidth('50%');
  }
}


// HomePage.ets

import { HMRouter, HMRouterMgr } from "@hadss/hmrouter";

@HMRouter({pageUrl:"HomePage"})
@Component
export struct HomePage {

  build() {
    Column(){
      Tabs(){
        TabContent(){
          Column(){
            Text('Tab1')
            Button('跳转Page1')
              .onClick(() => {
                HMRouterMgr.replace({pageUrl:'Page1'})
              })
          }
        }.tabBar('Tab1')
        TabContent(){
          Column(){
            Text('Tab2')
            Button('跳转Page2')
              .onClick(() => {
                HMRouterMgr.replace({pageUrl:'Page2'})
              })
          }
        }.tabBar('Tab2')
        TabContent(){
          Column(){
            Text('Tab3')
          }
        }.tabBar('Tab3')
        TabContent(){
          Column(){
            Text('Tab4')
          }
        }.tabBar('Tab4')
      .barPosition(BarPosition.End)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .border({width:1,color:Color.Red})
  }
}

// Page1.ets

import { HMRouter, HMRouterMgr } from "@hadss/hmrouter";

@HMRouter({pageUrl:'Page1'})
@Component
export struct Page1 {
  build() {
    Column(){
      Text('Page1')
        .fontSize(70)
        .fontWeight(FontWeight.Bold)
      Button('跳转页面')
        .onClick(() => {
          HMRouterMgr.push({pageUrl:'Page3'})
        })
    }
    .width('100%')
    .height('100%')
    .border({width:1,color: '#ffff0000' })
  }
}

// Page3.ets
import { HMRouter } from "@hadss/hmrouter";

@HMRouter({pageUrl:'Page3',singleton:true})
@Component
export struct Page3 {
  build() {
    Column(){
      Text('Page3')
        .fontSize(70)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
    .border({width:1,color:'#ff00ff7b'})
  }
}

但是我想实现这样的效果,上图第一步第二步不变,点击第二步后,显示这样的效果:

cke_203617.png

即不是分栏显示的,这个该如何实现呢?求教!!!


更多关于HarmonyOS鸿蒙Next中继续请教一个HMRouter页面跳转的问题,求助大佬们!!!的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

小伙伴你好,参考以下代码段:

class MyNavModifier extends AttributeUpdater<NavigationAttribute> {
  initializeModifier(instance: NavigationAttribute): void {
    instance.hideTitleBar(true)
    instance.mode(NavigationMode.Split); // 为双栏模式
    instance.navBarWidth('50%');
  }
}

参考文档:

更多关于HarmonyOS鸿蒙Next中继续请教一个HMRouter页面跳转的问题,求助大佬们!!!的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


他意思是点了跳转3后变成stack模式,

那就注册个 EventHub,动态更新模式,

在HarmonyOS Next中,HMRouter页面跳转可通过router.pushUrl()实现。需在config.json中配置路由信息,并确保目标页面已注册。使用示例:router.pushUrl({url: ‘pages/Index’})。注意页面路径需与配置一致。

从你的代码和截图来看,你遇到的问题是:在使用了 NavigationMode.Auto 并设置了 navBarWidth('50%') 的分栏模式下,从 Page1 跳转到 Page3 时,Page3 仍然显示在右侧分栏中,而你希望 Page3 能占据整个窗口,覆盖掉底部的 Tabs

这个问题是由于 HMNavigationAuto 模式下,其页面栈的导航行为是“分栏感知”的。当从 HomePage (内含Tabs) 通过 replacePage1 时,Page1 作为新页面被推入当前活动栏(右侧栏)的页面栈。随后,在 Page1push Page3Page3 会被推入同一个活动栏的栈顶,因此它仍然只占据右侧50%的空间。

要实现你期望的效果(Page3 全屏覆盖),有以下几种方案:

方案一:使用不同的导航模式或容器(推荐) 这是最直接的方法。你的 HomePage 是一个带底部 Tabs 的主页框架,通常希望其内部的页面跳转保持在分栏内。而像 Page3 这样的详情页或独立功能页,应该以全屏模式呈现。

  1. 为全屏页面使用独立的 HMNavigation 容器: 不要试图在同一个分栏导航容器内实现全屏覆盖。可以在 Page1 中,使用 HMRouterMgrpush 方法并指定不同的 navigationId,跳转到一个配置为全屏模式的新 HMNavigation 容器。但这需要更复杂的应用结构设计。

  2. 使用模态窗口或全屏对话框: 如果 Page3 是一个临时性的、需要聚焦用户注意力的页面,可以考虑使用 HMRouterMgrpresent 方法(如果HMRouter支持类似API)或者ArkUI的原生弹窗能力(例如 @CustomDialogbindSheet)来实现全屏覆盖效果。但这会改变页面的交互模式。

方案二:动态修改导航模式(针对当前架构的调整) 这个方案尝试在你现有结构上调整,但实现起来可能不够优雅,且可能伴随复杂的生命周期管理。

核心思路是:在需要全屏展示 Page3 时,将 HMNavigationmode 临时改为 NavigationMode.Stack(栈模式,全屏)。这需要你能访问到 Index 组件中的 modifier 实例。

  1. 修改 MyNavModifier 类,暴露一个修改模式的方法

    class MyNavModifier extends AttributeUpdater<NavigationAttribute> {
      private instance: NavigationAttribute | null = null;
    
      initializeModifier(instance: NavigationAttribute): void {
        this.instance = instance;
        instance.hideTitleBar(true);
        instance.mode(NavigationMode.Auto);
        instance.navBarWidth('50%');
      }
    
      // 新增方法:切换到全屏栈模式
      switchToFullScreenMode(): void {
        if (this.instance) {
          this.instance.mode(NavigationMode.Stack);
          // 可能需要隐藏NavBar,如果之前是显示的
          // this.instance.hideNavBar(true);
        }
      }
    
      // 新增方法:切换回分栏模式
      switchToSplitMode(): void {
        if (this.instance) {
          this.instance.mode(NavigationMode.Auto);
          this.instance.navBarWidth('50%');
          // this.instance.hideNavBar(false);
        }
      }
    }
    
  2. Index 中通过上下文或全局状态将 modifier 实例传递下去: 你需要通过ArkUI的上下文(例如 AppStorage 或自定义 LocalStorage)或者一个全局状态管理工具,让 Page1 能获取到 modifier 实例的引用。

  3. Page1 的跳转事件中修改模式并跳转

    // Page1.ets 中
    Button('跳转页面')
      .onClick(() => {
        // 1. 先获取到全局的 modifier 实例(假设已存入 AppStorage)
        let modifier: MyNavModifier = AppStorage.get('globalNavModifier');
        // 2. 切换到全屏模式
        modifier.switchToFullScreenMode();
        // 3. 执行跳转
        HMRouterMgr.push({pageUrl:'Page3'});
      })
    
  4. Page3 返回时恢复模式: 你需要在 Page3 的返回事件(例如系统返回键或自定义返回按钮)中,将模式切换回 Auto

    // Page3.ets 中
    aboutToDisappear(): void {
      // 页面即将消失时,恢复分栏模式
      let modifier: MyNavModifier = AppStorage.get('globalNavModifier');
      modifier.switchToSplitMode();
    }
    

    注意:这个时机可能不准确,因为页面动画期间可能就会触发。更可靠的做法是在 Page3 的返回按钮点击事件中执行。

方案三:重新思考页面结构 你的需求暴露出当前页面结构设计上的一个矛盾点:HomePage 作为Tabs容器,其设计初衷是作为应用的主导航框架。Page1Page3 在逻辑上可能不属于这个框架内的“子页面”,而应该是与 HomePage 平级或更顶层的页面。

建议的调整是:

  • HomePageTabs 内容简化,每个 TabContent 内只放置最核心的入口。
  • 当点击“跳转Page1”时,不使用 replace,而是使用 push 到一个新的、独立的全屏导航栈。这意味着 Page1Page3 不再与 HomePage 的Tabs共享同一个分栏导航容器。

总结 最根本的解决方法是方案三,即根据页面功能重新规划导航结构。如果必须在现有框架内快速修改,方案二提供了一种动态切换导航模式的思路,但需要注意状态管理的复杂性和可能出现的UI闪烁问题。HMRouter的设计通常鼓励一个清晰的、层次化的导航栈规划,强行在分栏内实现全屏覆盖可能不符合其最佳实践。

回到顶部