HarmonyOS 鸿蒙Next Navigation分栏模式下 如何设置右侧的默认显示内容

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

HarmonyOS 鸿蒙Next Navigation分栏模式下 如何设置右侧的默认显示内容

Navigation分栏模式下,右侧显示二级页面。在没有二级页面时,显示空白,不美观。

是否可以在没有二级页面时,为右侧区域设置一个自定义UI样式,比如一个占位图或之类的。

2 回复

不支持给空白页自定义 UI 样式。
但是,在分栏模式下,可以定义一个表示空页面占位图的 NavDestination 子页面。然后在 Navigation 组件所在页的 aboutToAppear() 方法中通过 this.navPathStack.pushPath() 可设置右侧默认展示页面,可实现类似效果。

有以下两种解决方案
方案一:在 Navigation 的 onNavigationModeChange 事件内判断是否分栏,分栏则 push 默认 NavDestination 入栈显示。参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-navigation-V5#onnavigationmodechange11
方案二:提前获取屏幕宽度(页面的 aboutToAppear),判断该宽度下是否需要分栏,需要则 push 默认 NavDestination 入栈显示。对比方案一,可快速显示子组件内容。具体宽度参数可参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-navigation-V5#navigationmode9枚举说明
在 Split 模式下如果路由栈内存在一个页面,此时按返回按钮会直接退出应用,不会使右侧变空白。但是与你的需求还是存在一定差距。
目前可以通过自定义派生类继承 NavPathStack 和对 NavDestination 的 onBackPressed() 事件回调进行处理,实现类似的效果,但会有一点繁琐,可以参考一下。
NavigationExample.ets

// 自定义 NavPathStack 派生类
export class DerivedNavPathStack extends NavPathStack {
  // 传递 NavigationMode 属性
  mode: NavigationMode = NavigationMode.Stack;
  // 自定义返回事件回调
  customBack(): boolean {
    if (this.size() > 1 || this.mode === NavigationMode.Stack) {
      return false;
    } else {
      this.pop();
      this.pushPath({ name: 'EmptyPage' });
      return true;
    }
  }
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct NavigationExample {
  private arr: number[] = [0, 1, 2, 3, 4, 5];
  [@State](/user/State) naviStack: DerivedNavPathStack = new DerivedNavPathStack();
  build() {
    Column() {
      Navigation(this.naviStack) {
        Row() {
          Column() {
            TextInput({ placeholder: 'search...' })
              .width('90%')
              .height(40)
              .backgroundColor('#FFFFFF')
              .margin({ top: 8 });
            List({ space: 12, initialIndex: 0 }) {
              ForEach(this.arr, (item: number) => {
                ListItem() {
                  Text('' + item)
                    .width('90%')
                    .height(72)
                    .backgroundColor('#FFFFFF')
                    .borderRadius(24)
                    .fontSize(16)
                    .fontWeight(500)
                    .textAlign(TextAlign.Center);
                }
                .onClick(() =>
                this.naviStack.pushPath({ name: 'ContentPage' }));
              }, (item: number) => item.toString());
            }
            .scrollBar(BarState.Off)
            .height('100%')
            .width('100%')
            .margin({
              top: 12,
              left: '10%'
            });
          }
          .width('100%')
          .height('100%');
        }
        .width('100%')
        .height('100%');
      }
      .mode(NavigationMode.Auto)
      // 模式切换时,更新 mode 变量和路由栈
      .onNavigationModeChange(mode => {
        this.naviStack.mode = mode;
        if (mode === NavigationMode.Split) {
          if (this.naviStack.size() === 0) {
            this.naviStack.pushPath({ name: 'EmptyPage' });
          }
        } else {
          this.naviStack.removeByName('EmptyPage');
        }
      })
      .title('首页')
      .hideTitleBar(true)
      .hideToolBar(true);
    }.width('100%').height('100%').backgroundColor('#F1F3F5');
  }
}

EmptyPage.ets 空内容占位子页面

[@Builder](/user/Builder)
export function EmptyPageBuilder() {
  EmptyPage()
}
[@Component](/user/Component)
struct EmptyPage {
  [@State](/user/State) message: string = 'Empty Page';
  pathStack: NavPathStack = new NavPathStack()
  build() {
    NavDestination() {
      RelativeContainer() {
        Text(this.message)
          .id('EmptyPage')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          });
      }
      .height('100%')
      .width('100%');
    }
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack
    })
  }
}

ContentPage.ets 内容占位子页面

import { DerivedNavPathStack } from './NavigationExample';
[@Builder](/user/Builder)
export function ContentPageBuilder() {
  ContentPage();
}
[@Component](/user/Component)
struct ContentPage {
  [@State](/user/State) message: string = 'Content Page';
  pathStack: DerivedNavPathStack = new DerivedNavPathStack();
  build() {
    NavDestination() {
      RelativeContainer() {
        Text(this.message)
          .id('ContentPage')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          });
      }
      .height('100%')
      .width('100%');
    }
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack as DerivedNavPathStack;
    })
    // 设置返回事件回调
    .onBackPressed(() => this.pathStack.customBack());
  }
}

route_map.json 系统路由表

{
  "routerMap": [
    {
      "name": "EmptyPage",
      "pageSourceFile": "src/main/ets/pages/EmptyPage.ets",
      "buildFunction": "EmptyPageBuilder"
    },
    {
      "name": "ContentPage",
      "pageSourceFile": "src/main/ets/pages/ContentPage.ets",
      "buildFunction": "ContentPageBuilder"
    }
  ]
}

在HarmonyOS鸿蒙Next中,使用Navigation组件进行分栏模式开发时,若需设置右侧的默认显示内容,可通过以下方式实现:

  1. 利用Navigation的回调

    • 监听Navigation的显示模式变化,当进入分栏模式(Split)时,通过this.naviStack.pushPath()this.naviStack.pushPathByName()方法设置右侧默认页面。
    • 可以在aboutToAppear()方法或监听NavigationMode变化的回调中实现此逻辑。
  2. 确保逻辑在双栏模式被识别时执行

    • 通过判断NavigationMode是否为Split,来确保上述设置默认页面的逻辑只在双栏模式下执行。
  3. 路由配置

    • 确保已正确配置路由,且目标页面已正确注册在路由表中。
  4. 注意事项

    • 在设置默认页面时,确保页面名称和参数正确无误。
    • 若需传递参数至默认页面,可在pushPath()pushPathByName()方法中指定。

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

回到顶部