HarmonyOS 鸿蒙Next Navigation launchMode 问题咨询

发布于 1周前 作者 h691938207 来自 鸿蒙OS

HarmonyOS 鸿蒙Next Navigation launchMode 问题咨询

请问Navigation pushPath的时候可以做到栈中有同名的实例时自动复用原实例 并且 不改变栈顺序吗? 

例如 A -> B -> C -> A 栈,最后一个A和第一个A共享同一个NavDestination。

目前测试了下launchMode设置貌似没有找到符合要求的,

STANDARD下push相同名称会直接新建实例

MOVE_TO_TOP_SINGLETON下会将同名的实例挪到栈顶,后退时不会按照原来的顺序返回

POP_TO_SINGLETON下直接将同名实例后入栈的NavDestination全部pop掉了,也不满足要求

NEW_INSTANCE好像和STANDARD行为差不多?

总的来说现在期望是如下行为:

入栈顺序 A -> B -> C -> A,最后的A和开始的A可以共享同一个NavDestination实例,出站顺序为A -> C -> B -> A,保持正常栈pop顺序出栈。

不确定是官方不允许这样还是自己没有操作正确,请大家多多指教。


更多关于HarmonyOS 鸿蒙Next Navigation launchMode 问题咨询的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

请问是因为每个NavDestination中记了状态,所以需要这个能力?如果是这样的话,可以用appstorage把状态独立出来。

具体到楼主的问题,官方api没有现成的launchMode或者函数,要自己记录路由栈实现,以下是一个简单的demo,从官方示例修改而来

1. 自己记录路由栈,这个比较简单

export default class History {
  private static arr: string[] = [];

static push(name: string) { History.arr.push(name); }

static pop(): string | undefined { return History.arr.pop(); }

static toString(): string { return History.arr.join(’,’) } }

<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

2. 前进和后退都要重写,简单来说,前进的时候使用LaunchMode.MOVE_TO_TOP_SINGLETON,后退的时候使用move

以下是pageOne.ets

import Logger from ‘…/common/utils/Logger’;
import History from ‘…/History’;
import prompt from ‘@ohos.prompt’;
import { uiObserver } from ‘@kit.ArkUI’;

@Builder export function PageOneBuilder(name: string, param: Object) { PageOne() }

const COLUMN_SPACE: number = 12;

@Component export struct PageOne { @State count: number = 0; pageInfos: NavPathStack = new NavPathStack(); navDesInfo: uiObserver.NavDestinationInfo | undefined @State currentNavPathStackStr: string = ‘’; @State currentCustomizedNavStack: string = ‘’;

aboutToAppear(): void { uiObserver.on(‘navDestinationUpdate’, (info) => { this.currentNavPathStackStr = this.pageInfos.getAllPathName().join(’,’); this.currentCustomizedNavStack = History.toString(); }); }

goTo(name: string) { let pathNames = this.pageInfos.getAllPathName(); let index = pathNames.indexOf(name); if (index >= 0) { this.pageInfos.pushDestination(new NavPathInfo(name, null), { launchMode: LaunchMode.MOVE_TO_TOP_SINGLETON }); } else { this.pageInfos.pushPathByName(name, null); } }

back(name: string) { let pathNames = this.pageInfos.getAllPathName(); let index = pathNames.indexOf(name); if (index >= 0) { this.pageInfos.moveToTop(name, false); } else { prompt.showToast({ message: 'page ’ + name + ‘does not exist’ }); } }

build() { NavDestination() { Column({ space: COLUMN_SPACE }) { Text('当前路由栈,navPathStack = ’ + this.currentNavPathStackStr).align(Alignment.Start); Text('自己记录的路由栈,customizednavstack = ’ + this.currentCustomizedNavStack).align(Alignment.Start); Text('模拟保存状态,count = ’ + this.count).align(Alignment.Start); Button(‘count++’, { stateEffect: true, type: ButtonType.Capsule }) .width($r(‘app.string.button_width’)).height($r(‘app.string.button_height’)).onClick(() => { this.count++; }) Button($r(‘app.string.entry_pageTwo’), { stateEffect: true, type: ButtonType.Capsule }) .width($r(‘app.string.button_width’)).height($r(‘app.string.button_height’)).onClick(() => { History.push(‘pageOne’); this.goTo(‘pageTwo’); }) } .width($r(‘app.string.navDestination_width’)) .height($r(‘app.string.navDestination_height’)) .justifyContent(FlexAlign.End) .padding({ bottom: $r(‘app.string.column_padding’), left: $r(‘app.string.column_padding’), right: $r(‘app.string.column_padding’) }) } .title(‘entry-pageOne’) .onBackPressed(() => { let pop = History.pop(); if (pop != undefined) { this.back(pop); return true; } prompt.showToast({ message: ‘不能再回退了’ }); return true; }) .onReady((context: NavDestinationContext) => { this.pageInfos = context.pathStack; Logger.info("current page config info is " + JSON.stringify(context.getConfigInRouteMap())); }) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

pageTwo.ets

import Logger from ‘…/common/utils/Logger’;
import History from ‘…/History’;
import { prompt, uiObserver } from ‘@kit.ArkUI’;

@Builder export function PageTwoBuilder(name: string, param: Object) { PageTwo() }

const COLUMN_SPACE: number = 12;

@Component export struct PageTwo { pageInfos: NavPathStack = new NavPathStack(); navDesInfo: uiObserver.NavDestinationInfo | undefined

@State currentNavPathStackStr:string = ‘’; @State currentCustomizedNavStack:string = ‘’; aboutToAppear(): void { uiObserver.on(‘navDestinationUpdate’, (info) => { this.currentNavPathStackStr = this.pageInfos.getAllPathName().join(’,’); this.currentCustomizedNavStack = History.toString(); }); } goTo(name: string) { let pathNames = this.pageInfos.getAllPathName(); let index = pathNames.indexOf(name); if (index >= 0) { this.pageInfos.pushDestination(new NavPathInfo(name, null), { launchMode: LaunchMode.MOVE_TO_TOP_SINGLETON }); } else { this.pageInfos.pushPathByName(name, null); } }

back(name: string) { let pathNames = this.pageInfos.getAllPathName(); let index = pathNames.indexOf(name); if (index >= 0) { this.pageInfos.moveToTop(name, false); } else { prompt.showToast({ message: 'page ’ + name + ‘does not exist’ }); } } build() { NavDestination() { Column({ space: COLUMN_SPACE }) { Text('当前路由栈,navPathStack = ’ + this.currentNavPathStackStr).align(Alignment.Start); Text('自己记录的路由栈,customizednavstack = ’ + this.currentCustomizedNavStack).align(Alignment.Start); Button($r(‘app.string.entry_pageOne’), { stateEffect: true, type: ButtonType.Capsule }) .width($r(‘app.string.button_width’)) .height($r(‘app.string.button_height’)) .onClick(() => { //Push the NavDestination page information specified by name onto the stack, and pass the data as param. History.push(‘pageTwo’); this.goTo(‘pageOne’); }) } .width($r(‘app.string.navDestination_width’)) .height($r(‘app.string.navDestination_height’)) .justifyContent(FlexAlign.End) .padding({ bottom: $r(‘app.string.column_padding’), left: $r(‘app.string.column_padding’), right: $r(‘app.string.column_padding’) }) } .title(‘entry-pageTwo’) .onBackPressed(() => { let pop = History.pop(); if (pop != undefined) { this.back(pop); return true; } prompt.showToast({ message: ‘不能再回退了’ }); return true; }) .onReady((context: NavDestinationContext) => { this.pageInfos = context.pathStack Logger.info('current page config info is ’ + JSON.stringify(context.getConfigInRouteMap())); }) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

3. 首页基本不变

@Entry
@Component
struct NavigationExample {
pageInfos: NavPathStack = new NavPathStack();

build() { Navigation(this.pageInfos) { Column({ space: 12 }) { Button($r(‘app.string.entry_pageOne’), { stateEffect: true, type: ButtonType.Capsule }) .width($r(‘app.string.button_width’)) .height($r(‘app.string.button_height’)) .onClick(() => { this.pageInfos.pushPathByName(‘pageOne’, null); }) } .width($r(‘app.string.navDestination_width’)) .height($r(‘app.string.navDestination_height’)) .justifyContent(FlexAlign.End) .padding({ bottom: $r(‘app.string.column_padding’), left: $r(‘app.string.column_padding’), right: $r(‘app.string.column_padding’) }) } .title($r(‘app.string.entry_index_title’)) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

更多关于HarmonyOS 鸿蒙Next Navigation launchMode 问题咨询的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


我还真理解这个需求了,但现在不支持。不过想复用的,可以直接复用内容,NodeController这种。

针对您提出的HarmonyOS 鸿蒙Next Navigation launchMode 问题,以下是直接且专业的回答:

在HarmonyOS中,Navigation组件的launchMode主要控制Activity或Page的启动方式,与Android中的概念类似但有所区别。HarmonyOS的Navigation提供了几种主要的launchMode,包括:

  1. standard:默认模式,每次启动都会创建一个新的实例。
  2. singleTop:如果目标实例已经位于栈顶,则不会创建新实例,而是复用该实例。
  3. singleTask:如果目标实例已经存在于任务栈中,则将该实例以上的所有实例出栈,并复用该实例。
  4. singleInstance:创建一个新的任务栈,并将目标实例作为该栈的唯一实例。

在配置Navigation时,可以通过XML或代码方式指定launchMode。例如,在XML中,可以通过设置Page元素的ohos:launchMode属性来指定;在代码中,则可以通过创建Intent时设置相关参数来实现。

请确保您的项目依赖和配置正确,以支持所选择的launchMode。同时,检查代码中是否有逻辑错误或不一致的启动方式调用。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部