HarmonyOS 鸿蒙Next Navigation launchMode 问题咨询
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
请问是因为每个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
针对您提出的HarmonyOS 鸿蒙Next Navigation launchMode 问题,以下是直接且专业的回答:
在HarmonyOS中,Navigation组件的launchMode主要控制Activity或Page的启动方式,与Android中的概念类似但有所区别。HarmonyOS的Navigation提供了几种主要的launchMode,包括:
- standard:默认模式,每次启动都会创建一个新的实例。
- singleTop:如果目标实例已经位于栈顶,则不会创建新实例,而是复用该实例。
- singleTask:如果目标实例已经存在于任务栈中,则将该实例以上的所有实例出栈,并复用该实例。
- singleInstance:创建一个新的任务栈,并将目标实例作为该栈的唯一实例。
在配置Navigation时,可以通过XML或代码方式指定launchMode。例如,在XML中,可以通过设置Page元素的ohos:launchMode
属性来指定;在代码中,则可以通过创建Intent时设置相关参数来实现。
请确保您的项目依赖和配置正确,以支持所选择的launchMode。同时,检查代码中是否有逻辑错误或不一致的启动方式调用。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html