##HarmonyOS Next实战##HarmonyOS SDK应用服务##教育##
目标:封装工具类,实现沉浸式效果。
典型应用全屏窗口UI元素包括状态栏、应用界面和底部导航条,其中状态栏和导航条,通常在沉浸式布局下称为避让区;避让区之外的区域称为安全区。开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感,从而使用户获得最佳的UI体验。
开发应用沉浸式效果主要要考虑如下几个设计要素:
- UI元素避让处理:导航条底部区域可以响应点击事件,除此之外的可交互UI元素和应用关键信息不建议放到导航条区域。状态栏显示系统信息,如果与界面元素有冲突,需要考虑避让状态栏。
- 沉浸式效果处理:将状态栏和导航条颜色与界面元素颜色相匹配,不出现明显的突兀感。
实战:
import { Rect } from '@ohos.application.AccessibilityExtensionAbility';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { UIAbility } from '@kit.AbilityKit';
import { KeyboardAvoidMode } from '@kit.ArkUI';
export namespace StageModelKit {
export class StageModel {
static UIAbility: Map<string, UIAbility> = new Map<string, UIAbility>();
static UIAbilityContext: Map<string, Context> = new Map<string, Context>();
static WindowStage: Map<string, window.WindowStage> = new Map<string, window.WindowStage>();
/**
* 登记
* @param UIAbilityContext
* @param WindowStage
*/
static register(UIAbilityContext: Map<string, Context>, WindowStage: Map<string, window.WindowStage>) {
UIAbilityContext.forEach((value: Context, key: string, map: Map<string, Context>) => {
StageModel.UIAbilityContext.set(key, value)
})
WindowStage.forEach((value: window.WindowStage, key: string, map: Map<string, window.WindowStage>) => {
StageModel.WindowStage.set(key, value)
})
}
}
export class Window {
private windowStageName: string;
windowStage: window.WindowStage;
avoidArea: AvoidArea;
keyboardHeight: number;
constructor(windowStageName: string) {
this.windowStageName = windowStageName
this.windowStage = new Object() as window.WindowStage
const zeroRect: Rect = {
left: 0,
top: 0,
width: 0,
height: 0
}
this.avoidArea = new AvoidArea(zeroRect, zeroRect)
this.keyboardHeight = 0
}
init() {
//初始化 windowStage
const windowStage = StageModel.WindowStage.get(this.windowStageName)
if (windowStage) {
this.windowStage = windowStage
} else {
throw new Error(`[异常][未获取到windowStage,请检查StageModel和windowStageName是否正确引用] windowStage is ${JSON.stringify(windowStage)}`)
}
//初始化 avoidArea
const getWindow = this.windowStage.getMainWindowSync(); // 获取应用主窗口
const topRect = getWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect // 系统状态栏顶部区域
const bottomRect =
getWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect // 导航条底部区域
this.avoidArea = new AvoidArea(rect_px2vp(topRect), rect_px2vp(bottomRect))
}
/**
* 沉浸式效果
*/
setImmersiveEffect() {
this.watchAvoidArea()
this.watchKeyboardHeight()
this.setFullScreen()
// 设置虚拟键盘抬起时压缩页面大小为减去键盘的高度
this.windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE);
}
/**
* 监控避让区
*/
watchAvoidArea() {
this.windowStage.getMainWindowSync().on('avoidAreaChange', (data) => {
if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
let avoidArea = this.avoidArea as AvoidArea
avoidArea.topRect = rect_px2vp(data.area.topRect)
this.avoidArea = avoidArea
} else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
let avoidArea = this.avoidArea as AvoidArea
avoidArea.bottomRect = rect_px2vp(data.area.bottomRect)
this.avoidArea = avoidArea
}else if (data.type == window.AvoidAreaType.TYPE_KEYBOARD) {
// this.keyboardHeight = px2vp(data.area.bottomRect.height) //键盘高度
// DeepalLogUtils.debug(`[日志]watchAvoidArea, keyboardHeight=${JSON.stringify(this.keyboardHeight)}`);
}
});
}
/**
* 监控软键盘高度
*/
watchKeyboardHeight() {
this.windowStage.getMainWindowSync().on('keyboardHeightChange', (data: number) => {
this.keyboardHeight = px2vp(data);
});
}
/**
* 设置全屏
*/
setFullScreen() {
this.windowStage.getMainWindowSync()
.setWindowLayoutFullScreen(true)
.then(() => {
console.info('Succeeded in setting the window layout to full-screen mode.');
})
.catch((err: BusinessError) => {
console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
});
}
/**
* 取消全屏
*/
cancelFullScreen() {
this.windowStage.getMainWindowSync()
.setWindowLayoutFullScreen(false)
.then(() => {
console.info('Succeeded in setting the window layout to full-screen mode.');
})
.catch((err: BusinessError) => {
console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
});
}
/**
* 隐藏头部状态栏
*/
hideSystemTopStatusBar() {
this.windowStage.getMainWindowSync()
.setSpecificSystemBarEnabled('status', false)
.then(() => {
console.info('Succeeded in setting the status bar to be invisible.');
})
.catch((err: BusinessError) => {
console.error(`Failed to set the status bar to be invisible. Code is ${err.code}, message is ${err.message}`);
});
}
/**
* 显示头部状态栏
*/
showSystemTopStatusBar() {
this.windowStage.getMainWindowSync()
.setSpecificSystemBarEnabled('status', true)
.then(() => {
console.info('Succeeded in setting the status bar to be invisible.');
})
.catch((err: BusinessError) => {
console.error(`Failed to set the status bar to be invisible. Code is ${err.code}, message is ${err.message}`);
});
}
/**
* 隐藏底部导航条
*/
hideSystemBottomNavigationBar() {
this.windowStage.getMainWindowSync()
.setSpecificSystemBarEnabled('navigationIndicator', false)
.then(() => {
console.info('Succeeded in setting the navigation indicator to be invisible.');
})
.catch((err: BusinessError) => {
console.error(`Failed to set the navigation indicator to be invisible. Code is ${err.code}, message is ${err.message}`);
});
}
/**
* 显示底部区域
*/
showSystemBottomNavigationBar() {
this.windowStage.getMainWindowSync()
.setSpecificSystemBarEnabled('navigationIndicator', true)
.then(() => {
console.info('Succeeded in setting the navigation indicator to be invisible.');
})
.catch((err: BusinessError) => {
console.error(`Failed to set the navigation indicator to be invisible. Code is ${err.code}, message is ${err.message}`);
});
}
}
/**
* 避让区
*/
class AvoidArea {
topRect: Rect;
bottomRect: Rect;
constructor(topRect: Rect, bottomRect: Rect) {
this.topRect = topRect
this.bottomRect = bottomRect
}
}
/**
* 将矩形的px单位的数值转换为以vp为单位的数值
* @param rect
* @returns
*/
function rect_px2vp(rect: Rect): Rect {
return {
left: px2vp(rect.left),
top: px2vp(rect.top),
width: px2vp(rect.width),
height: px2vp(rect.height)
} as Rect
}
}
點(diǎn)擊查看更多內(nèi)容
為 TA 點(diǎn)贊
評論
評論
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章
正在加載中
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦