HarmonyOS 沉浸式状态实现的多种方式

1. HarmonyOS 沉浸式状态实现的多种方式

  HarmonyOS 沉浸式状态实现的多种方式在这里插入图片描述

1.1. 方法一

1.1.1. 实现讲解

(1)首先设置setWindowLayoutFullScreen(true)(设置全屏布局)。
  布局将从屏幕最顶部开始到最底部结束,此时状态栏和底部规避区域还在,且与页面重叠,所以还需要设置页面根容器顶部内边距为状态栏高度,底部内边距为规避区域高度,这样页面就不会重叠。
(2)页面隐藏(或销毁)周期函数内恢复非全屏布局设置setWindowLayoutFullScreen(false)
  全屏布局设置是全局生效的,一旦设置跳转到其他页面同样生效,对于其他页面不需要沉浸式状态栏需要恢复原样。
  全屏布局非全屏显示,区别在于状态栏、规避区域还在,页面布局从屏幕最顶端开始

1.1.2. 代码实现

ImmersePage .ets(页面)

import { window } from '@kit.ArkUI'
import { AppHelper, StatusBarBean } from 'zzslib';
import { AppUtil } from 'zzslib/src/main/ets/util/AppUtil';
@Entry
@Component
struct ImmersePage {@State statusHeight: number = 0 //状态栏高度@State bottomAvoidAreaHeight: number = 0 //手机底部规避区域高度@State windowClass: window.Window | null = null //窗口管理器appHelper = new AppHelper();aboutToAppear() {this.setStatusBar('#00007AFF')this.init()}onPageShow(): void {//设置全屏布局this.windowClass?.setWindowLayoutFullScreen(true)}onPageHide(): void {//取消全屏布局this.windowClass?.setWindowLayoutFullScreen(false)this.setStatusBar('#007AFF')}//初始化init() {window.getLastWindow(getContext(this), (err, windowClass) => {if (!err.code) {//保存窗口管理器this.windowClass = windowClass//获取状态栏高度this.statusHeight = px2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height)//获取手机底部规避区域高度this.bottomAvoidAreaHeight =px2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height)windowClass.setWindowLayoutFullScreen(true)}})}setStatusBar(statusBarBgColor: string) {let that = thislet statusBarBean = new StatusBarBean()statusBarBean.isFullScreen = falsestatusBarBean.statusBarBgColor = statusBarBgColorstatusBarBean.statusBarTitleColor = '#ffffff'that.appHelper.setStatusBar(statusBarBean)AppUtil.setStatusBar(true, true)}build() {Column() {//页面区域Column() {Text('沉浸式状态栏').fontColor('#fff')}.height('100%').width('100%').border({width: 1,color: 'red'})}.height('100%').width('100%').backgroundImage( $r('app.media.img_bg_page')).backgroundImageSize({ height: '100%', width: '100%' }).padding({ top: this.statusHeight, bottom: this.bottomAvoidAreaHeight })}
}

1.1.3在这里插入图片描述

. 运行效果:

1.1.3. 全局缓存窗口管理器

  当项目内多个页面需要设置全屏布局时,每个页面要重新获取窗口管理器、状态栏高度、底部规避区域高度就比较麻烦,可以在entryabili内获取到上述属性值(对象)并存储在全局对象globalThis上
  EntryAbility.ets

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {}onWindowStageCreate(windowStage: window.WindowStage): void {//添加如下代码windowStage.getMainWindow((err, data) => {if (!err.code) {//全局变量添加窗口对象globalThis.windowClass = data;//全局变量添加状态栏高度单位vpglobalThis.statusHeight = px2vp(data.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height)//全局添加底部规避区域高度单位vpglobalThis.bottomAvoidAreaHeight = px2vp(data.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height)}})//windowStage.loadContent('pages/Index', (err) => {if (err.code) {return;}});}}

  Index.ets(页面)

import { window } from '@kit.ArkUI'@Entry
@Component
struct Index {onPageShow(): void {//设置全屏布局globalThis.windowClass.setWindowLayoutFullScreen(true)}onPageHide(): void {//取消全屏布局globalThis.windowClass.setWindowLayoutFullScreen(false)}build() {Column() {//页面区域Column() {Text('沉浸式状态栏').fontColor('#fff')}.height('100%').width('100%').border({width: 1,color: 'red'})}.height('100%').width('100%').backgroundImage( $r('app.media.img_bg_page')).backgroundImageSize({ height: '100%', width: '100%' }).padding({ top: globalThis.statusHeight, bottom: globalThis.bottomAvoidAreaHeight })}
}

1.2. 方法二

1.2.1. 实现讲解

  通过NavDestination作为页面根容器,并隐藏标题栏即可快速实现沉浸式状态,NavDestination从api 11开始默认支持安全区避让特性,所以关于页面重叠问题就不需要解决

1.2.2. 代码实现

  Index.ets(页面)

@Entry
@Component
struct Index{build() {NavDestination(){//页面区域Column(){Text('沉浸式状态栏').fontColor('#fff')}.width('100%').height('100%').border({width:1,color:'red'})}.hideTitleBar(true).backgroundImage( $r('app.media.img_bg_page')).backgroundImageSize({height:'100%',width:'100%'})}
}

1.2.3. 运行效果:

在这里插入图片描述

1.3. 方法三

1.3.1. 实现讲解

  通过expandSafeArea属性支持组件不改变布局情况下扩展其绘制区域至安全区外

1.3.2. 代码实现

@Entry
@Component
struct Index {build() {Stack() {Image($r('app.media.img_bg_page')).height('100%').width('100%').expandSafeArea()//页面区域Column() {Text('沉浸式状态栏').fontColor('#fff')}.height('100%').width('100%').border({width: 1,color: 'red'})}.height('100%').width('100%')}
}

  如果只需要头部区域沉浸
在这里插入图片描述
  实现代码:

@Entry
@Component
struct Index {build() {Column() {Column() {Text('沉浸式状态栏').fontColor('#fff')}.height(100).width('100%').backgroundColor('#0A7EE6').expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])}.height('100%').width('100%')}
}

  如果想修改状态栏文字颜色可通过:setWindowSystemBarProperties实现

   window.getLastWindow(getContext(this), (err, windowClass) => {if (!err.code) {windowClass.setWindowSystemBarProperties({statusBarContentColor:"#ffffff"})}})

在这里插入图片描述

1.4.封装

1.4.1. 封装状态栏管理类

  我们在common目录中创建StatusBarManager.ts文件,完整的代码如下:

import window from '@ohos.window';
import HashMap from '@ohos.util.HashMap';
import { Log } from './Log';/*** 状态栏管理器*/
export class StatusBarManager {private readonly TAG = 'StatusBarManager';private readonly CONFIG_SYSTEM_BAR_HEIGHT = 'systemBarHeight';private static mInstance: StatusBarManager;private mWindowStage: window.WindowStage;private mConfig = new HashMap<string, any>();private constructor() {}public static get(): StatusBarManager {if (!this.mInstance) {this.mInstance = new StatusBarManager();}return this.mInstance;}/*** 存储windowStage实例* @param windowStage*/public storeWindowStage(windowStage: window.WindowStage) {this.mWindowStage = windowStage;}/*** 获取windowStage实例* @returns*/public getWindowStage(): window.WindowStage {return this.mWindowStage;}/*** 设置沉浸式状态栏* @param windowStage* @returns*/public setImmersiveStatusBar(windowStage: window.WindowStage): Promise<void> {let resolveFn, rejectFn;let promise = new Promise<void>((resolve, reject) => {resolveFn = resolve;rejectFn = reject;});// 1.获取应用主窗口。try {let windowClass = windowStage.getMainWindowSync();Log.info(this.TAG, 'Succeeded in obtaining the main window. Data: ' + JSON.stringify(windowClass));// 2.实现沉浸式效果:设置窗口可以全屏绘制。// 将UI内容顶入状态栏下方windowClass.setWindowLayoutFullScreen(true).then(() => {//3、设置状态栏 可见windowClass.setWindowSystemBarEnable(['status']).then(() => {//4、设置状态栏透明背景const systemBarProperties: window.SystemBarProperties = {statusBarColor: '#00000000'};//设置窗口内导航栏、状态栏的属性windowClass.setWindowSystemBarProperties(systemBarProperties).then(() => {Log.info(this.TAG, 'Succeeded in setting the system bar properties.');}).catch((err) => {Log.error(this.TAG, 'Failed to set the system bar properties. Cause: ' + JSON.stringify(err));});})//5、存储状态栏高度this.storeStatusBarHeight(windowClass);resolveFn();});} catch (err) {Log.error(this.TAG, 'Failed to obtain the main window. Cause: ' + JSON.stringify(err));rejectFn();}return promise;}/*** 关闭沉浸式状态栏* @param windowStage* @returns*/public hideImmersiveStatusBar(windowStage: window.WindowStage): Promise<void> {let resolveFn, rejectFn;let promise = new Promise<void>((resolve, reject) => {resolveFn = resolve;rejectFn = reject;});// 1.获取应用主窗口。try {let windowClass = windowStage.getMainWindowSync();Log.info(this.TAG, 'Succeeded in obtaining the main window. Data: ' + JSON.stringify(windowClass));windowClass.setWindowLayoutFullScreen(false).then(() => {//存储状态栏高度this.mConfig.set(this.CONFIG_SYSTEM_BAR_HEIGHT, 0);resolveFn();});} catch (err) {Log.error(this.TAG, 'Failed to obtain the main window. Cause: ' + JSON.stringify(err));rejectFn(err);}return promise;}/*** 获取状态栏高度进行保存* @param windowClass* @returns*/private storeStatusBarHeight(windowClass: window.Window) {try {const avoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);// 保存高度信息this.mConfig.set(this.CONFIG_SYSTEM_BAR_HEIGHT, avoidArea.topRect.height);Log.info(this.TAG, 'Succeeded in obtaining the area. Data:' + JSON.stringify(avoidArea));} catch (err) {Log.error(this.TAG, 'Failed to obtain the area. Cause:' + JSON.stringify(err));}}/*** 未开启沉浸式状态栏,偏移量为0,开启, 偏移量为状态栏高度* @returns*/public getSystemBarOffset(): number {let height = 0;if (this.mConfig.hasKey(this.CONFIG_SYSTEM_BAR_HEIGHT)) {height = this.mConfig.get(this.CONFIG_SYSTEM_BAR_HEIGHT) as number;}return height;}/*** 是否开启沉浸式状态栏* @returns*/public isOpenImmersiveStatusBar(): boolean {return this.getSystemBarOffset() > 0;}
}

1.4.2.StatusBarManager 管理类主要提供以下常用的方法:

(1)get- 获取管理类单例实例
(2)storeWindowStage- 存储windowStage实例
(3)该方法在UIAbility中进行调用。
(4)getWindowStage- 获取windowStage实例
(5)setImmersiveStatusBar- 设置沉浸式状态栏
(6)hideImmersiveStatusBar- 关闭沉浸式状态栏
(7)storeStatusBarHeight- (内部私有方法)获取状态栏高度进行保存
(8)getSystemBarOffset- 获取状态栏高度(沉浸式状态栏下需要调整的标题偏移量)
(9)isOpenImmersiveStatusBar- 是否开启沉浸式状态栏
  下面我们主要讲解下setImmersiveStatusBar方法,设置沉浸式状态栏,这个过程主要分为五个步骤:
(1)获取应用主窗口

let windowClass = windowStage.getMainWindowSync();

  我们通过传入的windowStage,同步获取一个主窗口实例。
(2)设置窗口可以全屏绘制

windowClass.setWindowLayoutFullScreen(true)

  我们将窗口设置为全屏模式。

(3)设置状态栏可见

windowClass.setWindowSystemBarEnable(['status'])

  在设置全屏后,状态栏不可见,我们需要的不是全屏效果,而是状态栏沉浸式效果,因此需要将状态栏设置为可见。
  这里入参是一个数组,可以设置状态栏、也可以设置底部导航栏。
(4)设置窗口内状态栏背景为透明

const systemBarProperties: window.SystemBarProperties = {statusBarColor: '#00000000'
};
windowClass.setWindowSystemBarProperties(systemBarProperties).then(() => {Log.info(this.TAG, 'Succeeded in setting the system bar properties.');}).catch((err) => {Log.error(this.TAG, 'Failed to set the system bar properties. Cause: ' + JSON.stringify(err));});

  状态栏设置为显示状态后,我们给状态栏的背景色设置为透明,这里才能达到沉浸式的效果。
(5)存储状态栏高度

const avoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
// 保存高度信息
this.mConfig.set(this.CONFIG_SYSTEM_BAR_HEIGHT, avoidArea.topRect.height);

  我们通过上述代码可以获取系统状态栏的高度,并将其保存起来,后续页面通过该高度来判断是否是开启了沉浸式状态栏。
  这样我们的状态栏管理类就封装完毕,下面我们来写下页面UI实现沉浸式页面状态栏效果。

1.4.3.完整代码

import { StatusBarManager } from '../../../utils/StatusBarManager';@Entry
@Component
struct Immerse3Page {@State showImmersiveStatusBar: boolean = false;@State titleBarPadding: number = 0;build() {Column() {Column() {Column() {Text('这是标题').fontSize(20).fontColor(Color.White)}.height(50).justifyContent(FlexAlign.Center)}.padding({ top: `${this.titleBarPadding}px` }).width('100%').backgroundColor('#ff007dfe')Column() {Text('点击开启沉浸式状态栏').fontSize(16)Button(this.showImmersiveStatusBar ? '关闭' : '开启').fontSize(16).margin({ top: 20 }).padding({ left: 50, right: 50 }).onClick(() => {if (this.showImmersiveStatusBar) {this.close();} else {this.open();}this.showImmersiveStatusBar = !this.showImmersiveStatusBar;})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}.height('100%')}private open() {let windowStage = StatusBarManager.get().getWindowStage();if (windowStage) {StatusBarManager.get().setImmersiveStatusBar(windowStage).then(() => {this.titleBarPadding = StatusBarManager.get().getSystemBarOffset();});}}private close() {let windowStage = StatusBarManager.get().getWindowStage();if (windowStage) {StatusBarManager.get().hideImmersiveStatusBar(windowStage).then(() => {this.titleBarPadding = 0;})}}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12152.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

在API接口数据获取过程中,如何确保数据的安全性和隐私性?

在API接口数据获取过程中&#xff0c;确保数据的安全性和隐私性至关重要。以下是一些关键措施&#xff0c;可以帮助开发者和管理者保护API接口的数据安全和隐私性&#xff1a; 身份认证和授权 身份认证&#xff1a;确认用户身份的过程&#xff0c;常用的身份认证方式包括用户…

C++常用的特性-->day05

友元的拓展语法 声明一个类为另外一个类的友元时&#xff0c;不再需要使用class关键字&#xff0c;并且还可以使用类的别名&#xff08;使用 typedef 或者 using 定义&#xff09;。 #include <iostream> using namespace std;// 类声明 class Tom; // 定义别名 using …

python-27-Python ORM系列之彻底搞明白ORM概念,对ORM进行封装结合FastAPI实现数据库的增删改查,联表查询等接口

python-27-Python ORM系列之彻底搞明白ORM概念&#xff0c;对ORM进行封装结合FastAPI实现数据库的增删改查&#xff0c;联表查询等接口 一.简介 在Python基础系列ORM部分为大家介绍了如何搭建MySQL数据和MySQL一些访问配置&#xff0c;同时也介绍了pymysql库的封装来实现对数…

从哈佛哲学系到蛋白质设计大师,David Baker:AlphaFold令我深刻认识到深度学习的力量

要说谁是引领蛋白质设计的世界级大师&#xff0c;美国华盛顿大学的 David Baker 教授可谓是当之无愧&#xff0c;作为该领域的顶级专家&#xff0c;Baker 在蛋白质方向发表研究论文 700 余篇&#xff0c;引用量累计超 17.7 万。今年 10 月&#xff0c;因其在蛋白质设计方面的卓…

【测试框架篇】单元测试框架pytest(2):用例编写

一、 前言 前面一章我们介绍了pytest环境安装和配置&#xff0c;并在pycharm里面实现了我们第一个pytest脚本。但是有些童鞋可能在编写脚本的时候遇到了问题&#xff0c;本文会讲一下我们编写pytest用例时需要遵守哪些既定的规则&#xff0c;同时这个规则也是可以修改的。 二…

实现LiDAR和多视角摄像头数据的对齐、可控X-DRIVE:用于驾驶场景的跨模态一致多传感器数据合成

Abstract 近年来&#xff0c;扩散模型在合成驾驶场景中的LiDAR点云或摄像头图像数据方面取得了进展。尽管这些模型在单一模态数据的边际分布建模方面取得成功&#xff0c;但对不同模态之间互相依赖关系的探索仍然不足&#xff0c;而这种依赖关系能够更好地描述复杂的驾驶场景。…

稳恒磁场(1)

物理概念 磁场是物质性的。 地磁场&#xff08;与地磁场正负极相反&#xff09;与磁偏角&#xff08;一般为0到11度&#xff09; 磁感应强度&#xff1a; 单位为特斯拉&#xff08;T&#xff09;&#xff0c;另一个常用单位是高斯&#xff08;G&#xff09;且1T 10^4 G 物…

自动驾驶系列—自动驾驶中的短距离感知:超声波雷达的核心技术与场景应用

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

多语言爬取淘宝价格信息 python 比价api接入指南

以下是爬取淘宝价格信息及接入淘宝比价 API 的一般步骤&#xff1a; 传统爬虫方式获取价格信息&#xff08;不建议大量使用&#xff0c;可能违反淘宝规定&#xff09;&#xff1a; 分析目标页面 URL&#xff1a;在淘宝搜索框输入关键词后&#xff0c;观察页面的 URL 结构。例如…

Java List——针对实习面试

目录 Java ListJava List的三种主要实现是什么&#xff1f;它们各自的特点是什么&#xff1f;Java List和Array&#xff08;数组&#xff09;的区别&#xff1f;Java List和Set有什么区别&#xff1f;ArrayList和Vector有什么区别&#xff1f;什么是LinkedList&#xff1f;它与…

如何在Linux系统中安装微信

官方版微信的安装 好消息是&#xff0c;现在微信已经发布了官方的Linux版本&#xff0c;大家可以直接通过官方网站下载并安装&#xff0c;避免了以前繁琐的第三方工具安装步骤。 1.1 下载官方版微信 微信&#xff0c;是一个生活方式 选择Linux-> X86 1.2 安装微信 提前…

java双向链表解析实现双向链表的创建含代码

双向链表 一.双向链表二.创建MyListCode类实现双向链表创建一.AddFirst创建&#xff08;头插法&#xff09;二.AddLast创建&#xff08;尾叉法&#xff09;三.size四.remove(指定任意节点的首位删除)五.removeAll(包含任意属性值的所有删除)六.AddIndex(给任意位置添加一个节点…

hhdb数据库介绍(2-2)

数据高可用服务 HHDB Server在计算节点、数据节点、配置库等层次提供全面的高可用保障。提供完善的心跳检测、故障切换对存储节点同步追平判断、全局自增序列在故障时自动跳号、客户端连接Hold等机制&#xff0c;保障数据服务的可用性与数据的一致性。 计算节点服务高可用 H…

精挑细选的100道软测高频面试题,面试前你肯定用得上

测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 2、我现在有个程序&#xff0c;发现在 Windows 上运行得很慢&#xff0c;怎么判别是程序存在问题还是软硬件系统存在问题&#xff1f; 3、测试的策略有哪些&#xff1f; 4、正交表测试用…

STM32获取SHT3X温湿度芯片数据

目录 一、概述 二、单次数据采集模式的测量 1、配置说明 2、代码实现方式 三、周期性数据采集模式的测量 1、配置说明 2、代码实现方式 四、完整代码下载链接 一、概述 SHT3X是Sensirion公司推出的一款高精度、完全校准的温湿度传感器&#xff0c;基于CMOSens技术。它提…

[原创]手把手教学之前端0基础到就业——day11( Javascript )

文章目录 day11(Javascript)01Javascript①Javascript是什么②JavaScript组成③ Javascript的书写位置1. 行内式 (不推荐)2 . 内部位置使用 ( 内嵌式 )3. 外部位置使用 ( 外链式 ) 02变量1. 什么是变量2. 定义变量及赋值3. 注意事项4. 命名规范 03输入和输出1) 输出形式12) 输出…

[JAVAEE] 面试题(五) - HashMap, Hashtable, ConcurrentHashMap

目录 一. Hashtable1.1 Hashtable效率低下的原因: 二. ConcurrentHashMap2.1 ConcurrentHashMap更高效的原因: 三. HashMap, Hashtable, ConcurrentHashMap 之间的区别 HashMap是线程不安全的. 在多线程环境下, 使用: HashtableConcurrentHashMap 来确保线程安全. 一. Hashta…

Vue 2 —Vue Router 页面导航和参数传递

当从A页面跳转到B页面的时候把数据也一起传递过去&#xff0c;可用Vue Router 功能&#xff1a; 一、. this.$router.push 方法 Vue Router 是 Vue.js 的官方路由管理器&#xff0c;允许你在应用中进行页面导航&#xff08;即跳转到不同的 URL 路径&#xff09;。 this.$rout…

Local Transfer 致力于更加便捷地共享传输文件

软件主页&#xff1a;https://illusionna.github.io/LocalTransfer

[AcWing算法基础课]动态规划之01背包

题目链接&#xff1a;01背包 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi&#xff0c;价值是 wi。求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。输出最大价值。 首先&#xff0c;我们…