0

沉浸式界面开发—OpenHarmony

 9 months ago
source link: https://www.51cto.com/article/756199.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

沉浸式界面开发—OpenHarmony

作者:野生菌君 2023-05-30 14:50:20
沉浸式的设置最好放在Ability的OnWindowStageCreate的生命周期里,此时刚好可以获取窗口的信息,放在页面页面生命周期里会出现窗口大小不一致,影响体验。
2663ee679effbeec49903908350de2373ea9e1.png

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

沉浸式界面通常是指全屏显示,即当前画面占据整个屏幕。画面放大的同时,让用户摆脱无关信息的干扰,带给用户沉浸式的体验。常见的场景有:视频播放、游戏等。本例即为大家介绍如何开发沉浸式界面。

本例中的沉浸式界面有三种实现方式,对应效果如下:

方案一:颜色背景铺满

方案二:图片背景铺满

方案三:背景铺满的同时、状态栏不可见

沉浸式界面开发(OpenHarmony)-开源基础软件社区
沉浸式界面开发(OpenHarmony)-开源基础软件社区
沉浸式界面开发(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

表示系统默认区域。

TYPE_CUTOUT

表示刘海屏区域。

TYPE_SYSTEM_GESTURE9+

表示手势区域。

TYPE_KEYBOARD9+

表示软键盘区域

具体代码如下:

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%')
  }
}

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

责任编辑:jianghua 来源: 51CTO 开源基础软件社区

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK