[Daily HarmonyOS Next Knowledge] Screenshot Prevention, Loading Different Views, Function Parameter Passing, Loading Effects, Immersive Bottom Status Bar
1. How to implement screenshot prevention in a pushed sub-page of HarmonyOS?
- After the user clicks Login, navigate to the login page via
Navigation.push
. - Implement screenshot prevention on the login page and disable it when exiting the login page.
Set the main window to privacy mode in the login page's callback. Enable privacy mode in the aboutToAppear
lifecycle and disable it when exiting the page. For details, refer to:
https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-arkui-3-V5
setWindowPrivacyMode
sets whether the window is in privacy mode, preventing screenshots or screen recordings. This API is suitable for scenarios requiring screenshot/recording restrictions.
Set the main window to privacy mode in the onWindowStageCreate
callback. Refer to the sample code:
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
onWindowStageCreate(windowStage: window.WindowStage): void {
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. How to display different views by clicking a button within a HarmonyOS page?
Reference code:
import { BusinessError } from "@ohos.base";
import { HashMap } from '@kit.ArkTS';
import map from '@hms.core.map.map';
@Component
struct Child {
@Builder
customBuilder() {
}
@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. What class should be used to receive functions as parameters in HarmonyOS?
Define the method with the following code structure:
get(url: string, callback: () => void) { }
4. How to implement showLoading and showToast in HarmonyOS?
Use promptAction.openCustomDialog
for custom popups:
// 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. Issues with immersive bottom status bar height changes in HarmonyOS
Inconsistent full-screen effects between page-level settings and JS settings:
window.getLastWindow(getContext()).then((win) => {
win.setWindowLayoutFullScreen(true)
})
Reference 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 {
this.statusArr = [true, true, false, false]
window.getLastWindow(getContext()).then((win) => {
this.curWindow = win;
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;
}
this.curWindow.setWindowLayoutFullScreen(this.statusArr[index])
this.marginBottom = this.statusArr[index] === true ? this.bottomRectHeight : 0
}
@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)
.width('100%')
.height('100%')
.onChange((index: number) => {
this.currentIndex = index
})
}
.margin({
bottom: this.marginBottom
})
}
}
Top comments (0)