HarmonyOS鸿蒙Next中nav tab下的功能点击跳转到了a 但是a不想返回到tab下 需要怎么做

HarmonyOS鸿蒙Next中nav tab下的功能点击跳转到了a 但是a不想返回到tab下 需要怎么做 为什么当前路由栈只有一个 还能返回

5 回复

【背景知识】
onBackPressed:当与Navigation绑定的页面栈中存在内容时,此回调生效。当点击返回键时,触发该回调。返回值为true时,表示重写返回键逻辑,返回值为false时,表示回退到上一个页面。
setInterception:设置Navigation页面跳转拦截回调。

【解决方案】
方案一:通过NavDestination组件的onBackPressed回调对返回事件进行拦截,该方案支持拦截系统侧滑返回事件和使用NavDestination的标题栏返回键返回事件,不支持拦截使用NavPathStack.pop()返回。
示例代码如下:

import { promptAction, ShowDialogSuccessResponse } from '@kit.ArkUI';
@Entry
@Component
struct SideslipIntercept {
  controller: TextAreaController = new TextAreaController();
  @State text: string = '';
  @Provide pageStackForComponentSharedPages: NavPathStack = new NavPathStack();

  build() {
    // 应用主页用NavDestination承载,用于显示Navigation的内容区
    Navigation(this.pageStackForComponentSharedPages) {
    }
    .onAppear(() => {
      this.pageStackForComponentSharedPages.pushPathByName('MainPage', null, false);
    })
    // 创建NavDestination组件,需使用此组件的onBackPressed回调拦截返回事件
    .navDestination(this.textArea)
  }

  @Builder
  textArea(name: string) {
    NavDestination() {
      Column() {
        TextArea({
          text: this.text,
          placeholder: 'input your word...',
          controller: this.controller
        })
          .onChange((value: string) => {
            this.text = value;
          })
      }
      .justifyContent(FlexAlign.Start)
      .width('100%')
      .height('100%')
    }
    .onBackPressed(() => {
      // 此处可添加拦截处理逻辑,然后return true放行
      promptAction.showDialog({
        message: '是否返回',
        alignment: DialogAlignment.Center,
        buttons: [
          {
            text: '取消',
            color: '#0000FF'
          },
          {
            text: '确认',
            color: '#0000FF'
          }
        ]
      }).then((data: ShowDialogSuccessResponse) => {
        // 操作菜单的响应结果,选中按钮在buttons数组中的索引,从0开始,第二个索引为1
        // 点击取消按钮,留在此页面
        if (data.index === 0) {
          console.info('取消')
        }
        // 点击确认按钮,返回上层页面
        if (data.index === 1) {
          this.pageStackForComponentSharedPages.pop()
          console.info('确认')
        }
      })
      return true;
    })
  }
}

方案二:使用setInterception拦截Navigation页面跳转。
示例代码如下:

// Index.ets
import { promptAction, ShowDialogSuccessResponse } from '@kit.ArkUI';
@Entry
@Component
struct NavigationExample {
  pageInfos: NavPathStack = new NavPathStack();
  isUseInterception: boolean = false;
  isConfirm: boolean = false;

  registerInterception() {
    this.pageInfos.setInterception({
      // 页面跳转前拦截,允许操作栈,在当前跳转中生效。
      willShow: async (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
        operation: NavigationOperation, animated: boolean) => {
        if (!this.isUseInterception) {
          return;
        }

        if (typeof from === "string") {
          return;
        }
        let origin: NavDestinationContext = from as NavDestinationContext;
        let pathName = origin.pathInfo.name;
        if (operation === NavigationOperation.POP && !this.isConfirm) {
          promptAction.showDialog({
            message: '是否返回',
            alignment: DialogAlignment.Center,
            buttons: [
              {
                text: '取消',
                color: '#0000FF'
              },
              {
                text: '确认',
                color: '#0000FF'
              }
            ]
          }).then((data: ShowDialogSuccessResponse) => {
            // 操作菜单的响应结果,选中按钮在buttons数组中的索引,从0开始,第二个索引为1
            // 点击取消按钮,留在此页面
            if (data.index === 0) {
              console.info('取消')
            }
            // 点击确认按钮,返回上层页面
            if (data.index === 1) {
              this.isConfirm = true; // 用户判断是否确认返回上层页面的标识
              origin.pathStack.pop();
              console.info('确认')
            }
          })
          origin.pathStack.pop(); // 弹窗未响应前,停留在当前页面
          origin.pathStack.pushPathByName(pathName, null, false);
        } else {
          this.isConfirm = false;
        }
      },
      // 页面跳转后回调,在该回调中操作栈在下一次跳转中刷新。
      didShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
        operation: NavigationOperation, isAnimated: boolean) => {
        if (!this.isUseInterception) {
          return;
        }
        if (typeof from === "string") {
          console.info("current transition is from navigation home");
        } else {
          console.info(`current transition is from  ${(from as NavDestinationContext).pathInfo.name}`);
        }
        if (typeof to === "string") {
          console.info("current transition to is navBar");
        } else {
          console.info(`current transition is to ${(to as NavDestinationContext).pathInfo.name}`);
        }
      },
      // Navigation单双栏显示状态发生变更时触发该回调。
      modeChange: (mode: NavigationMode) => {
        if (!this.isUseInterception) {
          return;
        }
        console.info(`current navigation mode is ${mode}`);
      }
    })
  }

  build() {
    Navigation(this.pageInfos) {
      Column() {
        Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.pageInfos.pushPath({ name: 'pageOne' }); // 将name指定的NavDestination页面信息入栈
          })
        // 需要先点击此按钮,然后再点击pushPath按钮
        Button('use interception', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.isUseInterception = !this.isUseInterception;
            if (this.isUseInterception) {
              this.registerInterception();
            } else {
              this.pageInfos.setInterception(undefined);
            }
          })
      }
    }.title('NavIndex')
  }
}
// PageOne.ets
class TmpClass {
  count: number = 10;
}

@Builder
export function PageOneBuilder(name: string, param: Object) {
  PageOne()
}
@Component
export struct PageOne {
  pageInfos: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Column() {
        Button('pageOne', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
      }.width('100%').height('100%')
    }.title('pageOne')
  }
}

更多关于HarmonyOS鸿蒙Next中nav tab下的功能点击跳转到了a 但是a不想返回到tab下 需要怎么做的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以拦截 a 页面的返回事件:

无论是手势返回,还是左上角按钮返回都会调用: onBackPressed 方法,返回true, 表示自己处理返回事件。

// a page
NavDestination() {
  Column() {}
}
.onBackPressed(() => {
  // 处理返回事件
  return true
})

在HarmonyOS Next中,使用router.clear()清除路由栈后再跳转。具体代码:

import router from '@ohos.router'

// 在页面A执行跳转时
router.clear()
router.pushUrl({
  url: 'pages/TargetPage'
})

这会清空导航历史,使目标页面成为新栈底。或者使用router.replaceUrl()替换当前页面:

router.replaceUrl({
  url: 'pages/TargetPage'
})

在HarmonyOS Next中,要实现从nav tab跳转到页面A后不返回到tab页,可以通过以下方式处理:

  1. 使用router.replace()替代router.push()方法跳转,这样会替换当前路由而不是压栈:
router.replace({
  url: 'pages/A'
})
  1. 如果需要更精细的控制,可以在页面A的onBackPress()回调中拦截返回事件:
onBackPress() {
  // 直接返回true阻止默认返回行为
  return true
}
  1. 关于路由栈问题:即使只有一个页面,系统仍会保留默认的返回逻辑。要完全清除历史记录,可以使用:
router.clear()

这些方法可以避免从页面A返回到tab页的情况。根据具体场景选择最适合的方案即可。

回到顶部