沉浸式界面開發—OpenHarmony

場景說明
沉浸式界面通常是指全屏顯示,即當前畫面占據整個屏幕。畫面放大的同時,讓用戶擺脫無關信息的干擾,帶給用戶沉浸式的體驗。常見的場景有:視頻播放、游戲等。本例即為大家介紹如何開發沉浸式界面。
效果呈現
本例中的沉浸式界面有三種實現方式,對應效果如下:
方案一:顏色背景鋪滿 | 方案二:圖片背景鋪滿 | 方案三:背景鋪滿的同時、狀態欄不可見 |
運行環境
本例基于以下環境開發,開發者也可以基于其他適配的版本進行開發:
- IDE: DevEco Studio 3.1 Beta2
- SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release)
實現思路
如果一個應用想要獲得沉浸式的體驗,開發者可以通過以下三種方式進行實現:
- 顏色背景通鋪:使應用頁面的背景色和狀態欄、導航欄的背景色一致。可通過setWindowSystemBarProperties進行設置。
- 圖片背景通鋪:將狀態欄、導航欄的背景色設置為透明以便呈現應用界面的背景,同時通過 windowClass.on接口獲取到狀態欄、導航欄的區域信息,進行規避處理,以免狀態欄、導航欄的內容遮擋住應用內容。
- 隱藏導航欄和狀態欄:使用setWindowSystemBarEnable設置導航欄和狀態欄為隱藏狀態。
說明:
沉浸式的設置最好放在ability的onWindowStageCreate的生命周期里,此時剛好可以獲取窗口的信息,放在頁面頁面生命周期里會出現窗口大小不一致,影響體驗。
下文將分別介紹這三種方案的具體開發步驟。
開發步驟
顏色背景通鋪
此方案通過調用setWindowSystemBarProperties接口將狀態欄和導航欄的背景色設置為跟應用窗口相同的顏色,以達到界面全屏的效果。
具體代碼如下:
import window from '@ohos.window';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Type2 {
@State message: string = 'Hello World'
// 獲取UIAbility上下文
context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
async setSystemBar() {
// 獲取當前應用窗口
let windowClass:window.Window = await window.getLastWindow(context)
// 將狀態欄和導航欄的背景色設置為跟應用窗口相同的顏色
await windowClass.setWindowSystemBarProperties({
navigationBarColor: "#00FF00",
statusBarColor: "#00FF00",
navigationBarContentColor: "#00FF00",
statusBarContentColor: "#00FF00"
})
}
aboutToAppear() {
this.setSystemBar()
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}此方案的優勢在于不需要處理應用窗口和狀態欄、導航欄窗口的遮擋關系,因為此方案沒有使用setWindowLayoutFullScreen 接口設置沉浸式布局,所以三個窗口是平鋪的,不會重疊。劣勢在于無法將應用的背景圖等信息延伸到狀態欄、導航欄窗口中。適用于扁平化設計風格的應用。
圖片背景通鋪
這種方案可以實現圖片背景的通鋪,同時又能避免狀態欄和導航欄的內容跟應用內容相互遮擋,導致顯示效果異常。
為了能讓應用的有效顯示范圍避開系統的狀態欄和導航欄,以免內容重疊,我們可以通過windowClass.on(type: ‘avoidAreaChange’, callback: Callback<{AvoidAreaType, AvoidArea}>) 獲取系統規避區域的大小,并對這一塊區域做出相應的規避。
其中回調參數AvoidArea是規避區域,可以通過其獲取規避區域的具體范圍;AvoidAreaType是規避區域的類型其取值如下,示例中需要規避的狀態欄和導航欄屬于TYPE_SYSTEM類型。
名稱 | 值 | 說明 |
TYPE_SYSTEM | 0 | 表示系統默認區域。 |
TYPE_CUTOUT | 1 | 表示劉海屏區域。 |
TYPE_SYSTEM_GESTURE9+ | 2 | 表示手勢區域。 |
TYPE_KEYBOARD9+ | 3 | 表示軟鍵盤區域 |
具體代碼如下: |
page代碼
// index.ets
@Entry
@Component
struct Type3 {
@State message: string = 'Hello World'
@StorageLink("topHeight") topHeight: number = 0
@StorageLink("bottomHeight") bottomHeight: number = 0
build() {
Column() {
// 在界面頂部放置一個Row組件,用于占位
Row() {
}
.width("100%")
// 設置Row組件的高度為狀態欄的高度,可避免界面內容與狀態欄內容重疊
.height(px2vp(this.topHeight))
Row() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.position({ x: 0, y: 0 })
}
.width("100%")
.flexGrow(1)
// 在界面底部放置一個Row組件,用于占位
Row() {
}
.width("100%")
// 設置Row組件的高度為導航欄的高度,可避免界面內容與導航欄內容重疊
.height(px2vp(this.bottomHeight))
}
.backgroundImage($r("app.media.icon"))
.backgroundImageSize(ImageSize.Cover)
.width("100%")
.height("100%")
}
}ability代碼
// MainAbility.ts
import window from '@ohos.window';
async function enterImmersion(windowClass: window.Window) {
// 獲取狀態欄和導航欄的高度
windowClass.on("avoidAreaChange", ({ type, area }) => {
if (type == window.AvoidAreaType.TYPE_SYSTEM) {
// 將狀態欄和導航欄的高度保存在AppStorage中
AppStorage.SetOrCreate<number>("topHeight", area.topRect.height);
AppStorage.SetOrCreate<number>("bottomHeight", area.bottomRect.height);
}
})
// 設置窗口布局為沉浸式布局
await windowClass.setWindowLayoutFullScreen(true)
await windowClass.setWindowSystemBarEnable(["status", "navigation"])
// 設置狀態欄和導航欄的背景為透明
await windowClass.setWindowSystemBarProperties({
navigationBarColor: "#00000000",
statusBarColor: "#00000000",
navigationBarContentColor: "#FF0000",
statusBarContentColor: "#FF0000"
})
}
export default class MainAbility extends Ability {
...
async onWindowStageCreate(windowStage: window.WindowStage) {
let windowClass:window.Window = await windowStage.getMainWindow()
await enterImmersion(windowClass)
windowStage.loadContent('pages/page5')
}
...
}隱藏狀態欄、導航欄
隱藏狀態欄、導航欄可以達到完全沉浸的效果,使用setWindowSystemBarEnable接口即可實現。
具體代碼如下:
import window from '@ohos.window';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Type3 {
@State message: string = 'Hello World'
context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
async setSystemBar() {
let windowClass = await window.getLastWindow(context)
//設置導航欄,狀態欄不可見
await windowClass.setWindowSystemBarEnable([])
}
aboutToAppear() {
this.setSystemBar()
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.backgroundColor("#ffee33")
.height('100%')
}
}



































