【每日学点HarmonyOS Next知识】防截屏、加载不同View、函数传参、加载中效果、沉浸式底部状态栏
1、HarmonyOS 如何在一个 push 的子页面中实现防截屏功能?
1、用户点击登录后,Navigation.push 到登录页
2、如何在登录页中实现防截屏功能,并在退出登录页时,取消防截屏功能
可以在登录页回调中设置主窗口为隐私模式,在登陆页的aboutToAppear周期设置为隐私模式,当退出页面时,再退出隐私模式即可,详情请参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-arkui-3-V5
setWindowPrivacyMode设置窗口是否为隐私模式,设置为隐私模式的窗口,窗口内容将无法被截屏或录屏。此接口可用于禁止截屏/录屏的场景。
在onWindowStageCreate回调中设置主窗口为隐私模式,具体可参考示例代码:
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// 获取主窗口
windowStage.getMainWindow((err: BusinessError, data) => {
let errCode: number = err.code;
if (errCode) {
console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));
return;
}
let windowClass: window.Window = data;
console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));
// 设置窗口隐私模式
let isPrivacyMode: boolean = true;
try {
windowClass.setWindowPrivacyMode(isPrivacyMode, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to set the window to privacy mode. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in setting the window to privacy mode.');
});
} catch (exception) {
console.error('Failed to set the window to privacy mode. Cause:' + JSON.stringify(exception));
}
})
windowStage.loadContent('pages/Index', (err, data) => {
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. Data: %{public}s', JSON.stringify(data) ?? '');
});
}
2、HarmonyOS 如何在一个page里面,然后通过点击一个按钮,显示加载不同的view?
参考代码:
import { BusinessError } from "@ohos.base";
import { HashMap } from '@kit.ArkTS';
import map from '@hms.core.map.map';
@Component
struct Child {
@Builder
customBuilder() {
}
// 使用父组件@Builder装饰的方法初始化子组件@BuilderParam
@BuilderParam customBuilderParam: () => void = this.customBuilder;
build() {
Column() {
this.customBuilderParam()
}
}
}
@Entry
@Component
struct Index45 {
@State message: string = 'Hello World';
@State keys: number = 1
@Builder
component1() {
Column() {
Text('component0')
.width(100)
.backgroundColor(Color.Red)
}
.width('100%')
}
@Builder
component2() {
Column() {
Text('component1')
.width(100)
.backgroundColor(Color.Red)
}
.width('100%')
}
@Builder
component3() {
Column() {
Text('component2')
.width(100)
.backgroundColor(Color.Red)
}
.width('100%')
}
build() {
Column({ space: 30 }) {
Text('显示component1')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.keys = 0
})
Text('显示component2')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.keys = 1
})
Text('显示component3')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.keys = 2
})
if (this.keys === 0) {
Child({ customBuilderParam: this.component1 })
} else if (this.keys === 1) {
Child({ customBuilderParam: this.component2 })
} else {
Child({ customBuilderParam: this.component3 })
}
}
.height('100%')
.width('100%')
}
}
3、HarmonyOS 函数传参:function应该用什么类接收?
函数传参:function应该用什么类接收
定义方法可以参考以下代码:
get(url:string,callback:()=>void) { }
4、HarmonyOS showLoading 和 showToast 怎么实现?
可使用promptAction.openCustomDialog自定义弹窗:
//Index.ets
import {
changeDialogBuilder,
MyShowTest
}
from '../common/HttpUtils'import {
customDialogBuilder
}
from './testProm'let myShowTest = new MyShowTest()@Entry@Component struct Index {@State message: string = 'Hello World'onPageShow() : void {
changeDialogBuilder(customDialogBuilder.bind(this))
}
build() {
Row() {
Column() {
Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() = >{
myShowTest.showTest()
})
}.width('100%')
}.height('100%')
}
}
//testProm.ets
@Builder export
function customDialogBuilder() {
Column() {
Text('正在加载中').fontSize(16)
}.height(100).width(100).backgroundColor('#EEE')
}
//HttpUtils.ets
import promptAction from '@ohos.promptAction'let myDialogBuilder: CustomBuilder;
let customDialogId: number = 0 export
function changeDialogBuilder(builder: CustomBuilder) {
myDialogBuilder = builder
}
export class MyShowTest {
showTest() {
if (myDialogBuilder === undefined) {
return
}
promptAction.openCustomDialog({
builder: myDialogBuilder,
alignment: DialogAlignment.Center,
}).then((dialogId: number) = >{
customDialogId = dialogId
}) setTimeout(() = >{
promptAction.closeCustomDialog(customDialogId)
},
2000)
}
}
5、HarmonyOS 沉浸式设置底部状态栏高度变化问题?
在页面中设置全屏和js中设置全屏效果不一致
window.getLastWindow(getContext()).then((win) => {
win.setWindowLayoutFullScreen(true)
})
可参考demo
import { window } from '@kit.ArkUI'
@Entry
@Component
export struct ExpandSafeArea2 {
@State currentIndex: number = 0
@State isFullScreen: boolean = false
@State curWindow: window.Window | undefined = undefined
@State TabArr: string[] = ['首页', '推荐', '发现', '我的']
@State statusArr: boolean[] = []
private bottomRectHeight: number = 0
@State marginBottom: number = 0
aboutToAppear(): void {
//这里更新statusArr数据,实际上在加载h5的时候获取
this.statusArr = [true, true, false, false]
window.getLastWindow(getContext()).then((win) => {
this.curWindow = win;
// 根据status信息判断首个界面是否设置沉浸式
this.curWindow.setWindowLayoutFullScreen(true)
let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
let avoidArea = win.getWindowAvoidArea(type);
console.log(JSON.stringify(avoidArea.bottomRect))
this.bottomRectHeight = px2vp(avoidArea.bottomRect.height); // 获取到导航条区域的高度
this.handleFullScreen(this.currentIndex)
})
}
handleFullScreen(index: number) {
if (!this.curWindow || !this.statusArr.length) {
return;
}
// 对应tab的逻辑
this.curWindow.setWindowLayoutFullScreen(this.statusArr[index])
this.marginBottom = this.statusArr[index] === true ? this.bottomRectHeight : 0 // 沉浸式的时候添加底部margin
}
@Builder
tabBuilder(title: string, targetIndex: number) {
Column() {
Text(title)
.fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
}
build() {
Column() {
Tabs({ barPosition: BarPosition.End }) {
ForEach(this.TabArr, (tab: string, index: number) => {
TabContent() {
Text(tab + '沉浸状态:' + this.statusArr[index]).fontSize(30)
}
.backgroundColor(Color.Red)
.tabBar(this.tabBuilder(tab, 0))
.onWillShow(() => {
this.handleFullScreen(index)
})
})
}
.vertical(false)
.clip(false) //tabs包含的时候需要注意, clip默认是开启的。需要关闭不然子节点不能扩展安全区域。
.width('100%')
.height('100%')
.onChange((index: number) => {
this.currentIndex = index
})
}
.margin({
bottom: this.marginBottom
})
}
}