鴻蒙 HarmonyOS 實(shí)現(xiàn)沉浸式三種方式

一、setWindowLayoutFullScreen(true)

  • 設(shè)置主窗口或子窗口的布局是否為沉浸式布局,使用Promise異步回調(diào)。
  • 沉浸式布局生效時(shí),布局不避讓狀態(tài)欄與導(dǎo)航欄,組件可能產(chǎn)生與其重疊的情況。
  • 非沉浸式布局生效時(shí),布局避讓狀態(tài)欄與導(dǎo)航欄,組件不會(huì)與其重疊。
  • 窗口的布局是否為沉浸式布局(該沉浸式布局狀態(tài)欄、導(dǎo)航欄仍然顯示)。true表示沉浸式布局;false表示非沉浸式布局。


1、EntryAbility直接設(shè)置

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    GlobalContext.get().setContext(this.context);

    windowStage.getMainWindow().then((windowObj: window.Window) => {
      //設(shè)置沉浸式
      windowObj.setWindowLayoutFullScreen(true).catch((error: BusinessError) => {
        hilog.error(0x0001, 'testTag', `Failed to setWindowLayoutFullScreen. Code: ${error.code}`);
      })
      //獲取并保存狀態(tài)欄高度
      let avoidArea = windowObj.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
      GlobalContext.get().setObject('state_bar_height', avoidArea.topRect.height);

      windowStage.loadContent('pages/Index', (err) => {
        if (err.code) {
          hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
          return;
        }
        hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
      });
    })
  }
}

未做狀態(tài)欄高度處理頁面代碼

@Entry
@Component
struct ImmersivePage {
  build() {
    Column() {
      Text('setWindowLayoutFullScreen(true) 沉浸式')
        .fontSize(50)
        .fontColor(Color.Red)
    }
    .height('100%')
    .width('100%')
  }
}

狀態(tài)欄高度處理頁面代碼

@Entry
@Component
struct ImmersivePage {
  build() {
    Column() {
      //添加狀態(tài)高度,可以封裝好一個(gè)通用
      Text()
        .backgroundColor(Color.Orange)
        .height(px2vp(GlobalContext.get().getT<number>('state_bar_height')))
        .width('100%')

      Text('setWindowLayoutFullScreen(true) 沉浸式')
        .fontSize(50)
        .fontColor(Color.Red)
    }
    .height('100%')
    .width('100%')
  }
}
處理

2、在對(duì)應(yīng)頁面設(shè)置setWindowLayoutFullScreen(true)沉浸式

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    GlobalContext.get().setContext(this.context);

    windowStage.getMainWindow().then((windowObj: window.Window) => {
      //獲取并保存狀態(tài)欄高度
      let avoidArea = windowObj.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
      GlobalContext.get().setObject('state_bar_height', avoidArea.topRect.height);
      //保存窗口全局使用
      GlobalContext.get().window = windowStage.getMainWindowSync()

      windowStage.loadContent('pages/Index', (err) => {
        if (err.code) {
          hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
          return;
        }
        hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
      });
    })
  }
}
@Entry
@Component
struct ImmersivePage {
  build() {
    Column() {
      Text('當(dāng)前頁面設(shè)置setWindowLayoutFullScreen(true) 沉浸式')
        .fontSize(50)
        .fontColor(Color.Red)
    }
    .height('100%')
    .width('100%')
  }

  aboutToAppear(): void {
    //設(shè)置沉浸式
    GlobalContext.get().window?.setWindowLayoutFullScreen(true)
  }

  aboutToDisappear(): void {
     //沉浸式恢復(fù)
    GlobalContext.get().window?.setWindowLayoutFullScreen(false)
  }
}

3、使用方式總結(jié)

  1. 直接設(shè)置setWindowLayoutFullScreen(true),會(huì)導(dǎo)致全部頁面內(nèi)容到狀態(tài)欄,需要手動(dòng)添加狀態(tài)欄高度,可以考慮封裝好一個(gè)。
  2. 在頁面顯示前(aboutToAppear)獲取窗口(windowStage.getMainWindowSync())設(shè)置setWindowLayoutFullScreen(true)實(shí)現(xiàn)沉浸式,頁面銷毀(aboutToDisappear)設(shè)置setWindowLayoutFullScreen(false)回歸正常。
    但是這樣做有個(gè)不好影響就是上一個(gè)頁面會(huì)有向下動(dòng)的視覺,體驗(yàn)不是很好。

二、expandSafeArea()

  • 控制組件擴(kuò)展其安全區(qū)域。

1、未設(shè)置expandSafeArea

@Entry
@Component
struct ImmersivePage {
  build() {
    Column() {
      Text('未設(shè)置 expandSafeArea 沉浸式')
        .fontSize(50)
        .fontColor(Color.Red)
    }
    .backgroundColor(Color.Orange)
    .height('100%')
    .width('100%')
  }
}

2、設(shè)置expandSafeArea背景色沉浸

對(duì)父容器設(shè)置才是背景色沉浸,如果對(duì)Text設(shè)置會(huì)連帶文字一起沉浸到狀態(tài)欄。

@Entry
@Component
struct ImmersivePage {
  build() {
    Column() {
      Text('設(shè)置 expandSafeArea 沉浸式')
        .fontSize(50)
        .fontColor(Color.Red)
    }
    .expandSafeArea()//設(shè)置沉浸式
    .backgroundColor(Color.Orange)
    .height('100%')
    .width('100%')
  }
}

3、設(shè)置expandSafeArea圖片沉浸

@Entry
@Component
struct ImmersivePage {
  build() {
    Stack() {
      Image($rawfile('img.png'))
        .expandSafeArea()//設(shè)置沉浸式
      Text('設(shè)置 expandSafeArea 沉浸式')
        .fontSize(50)
        .fontColor(Color.White)
    }
    .height('100%')
    .width('100%')
  }
}
未設(shè)置沉浸式 設(shè)置沉浸式

4、多層組件也能設(shè)置expandSafeArea沉浸,只要父組件沒有限制其到狀態(tài)欄

@Entry
@Component
struct ImmersivePage {
  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      this.LayoutBuilder()
      Text('設(shè)置 expandSafeArea 沉浸式')
        .fontSize(50)
        .fontColor(Color.White)
    }
    .height('100%')
    .width('100%')
  }

  @Builder
  LayoutBuilder() {
    Column() {
      Image($rawfile('img.png'))
        .expandSafeArea() //設(shè)置沉浸式
    }
  }
}

5、多個(gè)組件也能設(shè)置expandSafeArea沉浸

@Entry
@Component
struct ImmersivePage {
  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      this.LayoutBuilder()
      Text('設(shè)置 expandSafeArea 沉浸式')
        .fontSize(50)
        .fontColor(Color.White)
        .expandSafeArea() //設(shè)置沉浸式1
    }
    .height('100%')
    .width('100%')
  }

  @Builder
  LayoutBuilder() {
    Column() {
      Image($rawfile('img.png'))
        .expandSafeArea() //設(shè)置沉浸式2
    }
  }
}

6、使用方式總結(jié)

  1. expandSafeArea設(shè)置沉浸式更靈活,可以根據(jù)情況對(duì)其中一個(gè)或多個(gè)組件設(shè)置沉浸式
  2. expandSafeArea設(shè)置沉浸式不會(huì)導(dǎo)致頁面上下抖動(dòng)

7、說明

設(shè)置expandSafeArea屬性進(jìn)行組件繪制擴(kuò)展時(shí),組件不能設(shè)置固定寬高尺寸(百分比除外)。
安全區(qū)域不會(huì)限制內(nèi)部組件的布局和大小,不會(huì)裁剪內(nèi)部組件。
當(dāng)父容器是滾動(dòng)容器時(shí),設(shè)置expandSafeArea屬性不生效。
設(shè)置expandSafeArea()時(shí),不傳參,走默認(rèn)值處理;設(shè)置expandSafeArea([],[])時(shí),相當(dāng)于入?yún)⑹强諗?shù)組,此時(shí)設(shè)置expandSafeArea屬性不生效。
組件設(shè)置expandSafeArea之后生效的條件為:
1.type為SafeAreaType.KEYBOARD時(shí)默認(rèn)生效,組件不避讓鍵盤。
2.設(shè)置其他type,組件的邊界與安全區(qū)域重合時(shí)組件能夠延伸到安全區(qū)域下。例如:設(shè)備頂部狀態(tài)欄高度100,那么組件在屏幕中的絕對(duì)位置需要為0 <= y <= 100。
組件延伸到安全區(qū)域下,在安全區(qū)域處的事件,如點(diǎn)擊事件等可能會(huì)被系統(tǒng)攔截,優(yōu)先給狀態(tài)欄等系統(tǒng)組件響應(yīng)。
滾動(dòng)類容器內(nèi)的組件不建議設(shè)置expandSafeArea屬性,如果設(shè)置,需要按照組件嵌套關(guān)系,將當(dāng)前節(jié)點(diǎn)到滾動(dòng)類祖先容器間所有直接節(jié)點(diǎn)設(shè)置expandSafeArea屬性,否則expandSafeArea屬性在滾動(dòng)后可能會(huì)失效

三、Navigation()+NavDestination()

Navigation組件是路由導(dǎo)航的根視圖容器,一般作為Page頁面的根容器使用,其內(nèi)部默認(rèn)包含了標(biāo)題欄、內(nèi)容區(qū)和工具欄,其中內(nèi)容區(qū)默認(rèn)首頁顯示導(dǎo)航內(nèi)容(Navigation的子組件)或非首頁顯示(NavDestination的子組件),首頁和非首頁通過路由進(jìn)行切換。

作為子頁面的根容器,用于顯示Navigation的內(nèi)容區(qū)。

該組件從API Version 11開始默認(rèn)支持安全區(qū)避讓特性(默認(rèn)值為:expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])),開發(fā)者可以重寫該屬性覆蓋默認(rèn)行為,API Version 11之前的版本需配合expandSafeArea屬性實(shí)現(xiàn)安全區(qū)避讓。

@Builder
export function ImmersivePageBuilder() {
  ImmersivePage()
}

@Component
export struct ImmersivePage {
  pathStack: NavPathStack = new NavPathStack()

  build() {
    NavDestination() {
      Stack({ alignContent: Alignment.TopStart }) {
        Text('設(shè)置 NavDestination 沉浸式')
          .fontSize(50)
          .fontColor(Color.White)
      }
      .height('100%')
      .width('100%')
    }
    .hideTitleBar(true) //設(shè)置沉浸式
    .backgroundColor(Color.Orange) //設(shè)置沉浸式
    .backgroundImage($rawfile('img.png'))//圖片設(shè)置沉浸式,容易圖片拉伸
    .backgroundImageSize({ width: '100%', height: '100%' })//圖片設(shè)置沉浸式,容易圖片拉伸
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack
    })
  }
}
背景色沉浸式 圖片沉浸式

使用方式總結(jié)

  1. 默認(rèn)還是使用expandSafeArea實(shí)現(xiàn)沉浸式。
  2. 推薦在這使用顏色沉浸式,用圖片容易造成拉伸,確定用圖片可以單獨(dú)對(duì)圖片使用expandSafeArea沉浸式。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容