HarmonyOS鸿蒙Next中适配了折叠屏的分栏效果后,怎么像手机中一样跳转到一个页面,这个页面覆盖整个app

HarmonyOS鸿蒙Next中适配了折叠屏的分栏效果后,怎么像手机中一样跳转到一个页面,这个页面覆盖整个app

咨询描述:项目已经使用HMRouter适配了折叠屏的分栏效果,如果用户设置了密码,那么进入app之后,进入到消息模块后,会跳转到解锁页面,需求是需要解锁页面把整个app都覆盖住(类似于在手机上的效果),解锁返回后,Tabs组件的各个模块还是分栏的效果。也就是只在解锁页面是覆盖整个app的。

4 回复

【背景知识】

  1. Navigation组件的分栏模式由mode属性控制,包括单栏(Stack)、分栏(Split)和自适应(Auto)三个属性。可通过状态管理实现动态切换mode属性的单栏与分栏模式,实现子页的放大效果。

  2. 状态管理中的AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。

通过@StorageLink可以和AppStorage中key对应的属性建立双向数据同步:

  • 本地修改发生,该修改会被写回AppStorage中。
  • AppStorage中的修改发生后,该修改会被同步到所有绑定AppStorage对应key的属性上,包括单向(@StorageProp和通过Prop创建的单向绑定变量)、双向(@StorageLink和通过Link创建的双向绑定变量)变量和其他实例(比如PersistentStorage)。

【解决方案】

  1. 通过@StorageLink创建状态管理变量isSplit控制Navigation组件的mode属性。
@Entry
@Component
struct Index {
  pageInfos: NavPathStack = new NavPathStack()
  [@StorageLink](/user/StorageLink)('isSplit') isSplit: boolean = true;
  
  // 跳转回主页时重新修改为分栏模式,根据实际需求设置
  aboutToAppear(): void {
    AppStorage.set('isSplit', true);
  }

  build() {
    Navigation(this.pageInfos) {
      Column() {
        Button('跳转')
          .backgroundColor('#ff002cba')
          .width('150')
          .height('60')
          .onClick(() => {
            this.pageInfos.pushPath({ name: 'Index2' })
          })
      }
    }
    .mode(this.isSplit ? NavigationMode.Split : NavigationMode.Stack)
    .hideTitleBar(true)
    .hideToolBar(true)
  }
}
  1. 通过AppStorage.set方法修改状态管理变量isSplit值,从而控制Navigation组件的mode属性,并刷新UI。
@Builder
export function Index2Builder() {
  Index2()
}

@Entry
@Component
struct Index2 {
  @State message: string = '放大'

  // 跳转回该页面时重新修改为分栏模式,根据实际需求设置
  aboutToAppear(): void {
    AppStorage.set('isSplit', true);
  }

  build() {
    NavDestination() {
      RelativeContainer() {
        Text(this.message)
          .onClick(() => {
            let a = AppStorage.get<boolean>('isSplit')
            if (a === false || a === undefined) {
              AppStorage.set('isSplit', true)
              this.message = '放大'
            } else {
              AppStorage.set('isSplit', false)
              this.message = '缩小'
            }
          })
      }
      .height('100%')
      .width('100%')
    }
    .hideTitleBar(true)
  }
}

【常见FAQ】

Q: navBarWidthnavBarWidthRange属性是否可以实现子页放大的功能?

A: 在分栏模式下可以实现子页放大的功能。但是存在以下限制,可按照需求参考:

  1. navBarWidth设置Navigation主页宽度存在设置大小问题,当设置主页宽度为0%时,默认识别为100%,可以设置为0.000001%与0%区分:
.navBarWidth(this.isSplit ? '30%' : '0.000001%')
  1. navBarWidthRange设置Navigation主页宽度存在最小宽度限制,不存在最大宽度限制,即可实现子页放大效果,但是不能实现子页全屏效果:
.navBarWidthRange(this.isSplit ? ['30%', '70%'] : ['0%', '100%'])

更多关于HarmonyOS鸿蒙Next中适配了折叠屏的分栏效果后,怎么像手机中一样跳转到一个页面,这个页面覆盖整个app的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以通过 @StorageLink('isSplit') isSplit: boolean = false; AppStorage.set('isSplit',true) 来实现。 在需要的地方修改 isSplit 的值来触发界面刷新。 请参考代码:

// Index.ets
@Entry
@Component
struct Index {
  @State nav:NavPathStack = new NavPathStack()
  @StorageLink('isSplit') isSplit: boolean = false;
  aboutToAppear(): void {
    AppStorage.setOrCreate('isSplit',false);
    AppStorage.setOrCreate('pathStack',this.nav)
  }
  build() {
    Navigation(this.nav){
      Column()
        .backgroundColor('#f00')
        .width('100%').height('100%')
        .onClick(()=>{
          this.nav.pushPathByName('Page','')
        })
    }
    .mode(this.isSplit? NavigationMode.Split : NavigationMode.Stack)
    .hideTitleBar(true)
    .hideToolBar(true)
  }
}
// Page.ets
@Builder
export function PageBuilder() {
  Page()
}
@Entry
@Component
struct Page {
  onPageShow(): void {
    AppStorage.set('isSplit',true)
  }
  build() {
    NavDestination(){
      RelativeContainer () {
        Text('Hello')
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
      }
      .onClick(()=>{
        let a = AppStorage.get<boolean>('isSplit')
        if (a == false || a == undefined) {
          AppStorage.set('isSplit',true)
        }else{
          AppStorage.set('isSplit',false)
        }
      })
      .height('100%')
      .width('100%')
    }
  }
}

在HarmonyOS鸿蒙Next中,适配折叠屏的分栏效果后,若需跳转到一个覆盖整个应用的页面,可以使用PageAbilityUIAbility的全屏模式。通过设置IntentFlagsIntent.FLAG_ABILITY_NEW_TASK,并调用startAbility方法启动目标页面,确保页面以全屏形式显示。

在HarmonyOS Next中实现折叠屏分栏布局下全屏覆盖效果,可以通过以下方式处理:

  1. 使用AbilityContextstartAbility方法启动解锁页面:
let want = {
  deviceId: "",
  bundleName: "com.example.app",
  abilityName: "LockScreenAbility",
  parameters: {
    fullScreen: true
  }
};
this.context.startAbility(want);
  1. 在解锁页面的onWindowStageCreate中设置全屏模式:
onWindowStageCreate(windowStage: window.WindowStage) {
  windowStage.getMainWindow().then((window) => {
    window.setFullScreen(true);
    window.setLayoutFullScreen(true);
  });
}
  1. 解锁完成后调用terminateSelf()返回分栏布局:
// 解锁成功后
this.context.terminateSelf();
  1. 在分栏布局的PageAbility中重写onBackPress处理返回键逻辑:
onBackPress() {
  // 阻止返回键退出应用
  return true;
}

注意确保解锁页面配置为全屏模式,并且不继承分栏布局的导航栏样式。这种方式可以在保持分栏布局的同时,实现特定页面的全屏覆盖效果。

回到顶部