DEV Community

Cover image for Screenshot Prevention, Loading Different Views, Function Parameter Passing, Loading Effects, Immersive Bottom Status Bar
kouwei qing
kouwei qing

Posted on

Screenshot Prevention, Loading Different Views, Function Parameter Passing, Loading Effects, Immersive Bottom Status Bar

[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?

  1. After the user clicks Login, navigate to the login page via Navigation.push.
  2. 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) ?? ''); 
    }); 
  }
Enter fullscreen mode Exit fullscreen mode

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%')
  }
}
Enter fullscreen mode Exit fullscreen mode

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) { }
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
})
Enter fullscreen mode Exit fullscreen mode

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
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)