DEV Community

Cover image for Page-level Popup, Return to Desktop API, Cumbersome Portrait-Landscape Switching, Status Bar Color Setting
kouwei qing
kouwei qing

Posted on

Page-level Popup, Return to Desktop API, Cumbersome Portrait-Landscape Switching, Status Bar Color Setting

[Daily HarmonyOS Next Knowledge] Page-level Popup, Return to Desktop API, Cumbersome Portrait-Landscape Switching, Status Bar Color Setting, Screen Always-On Setting

1. Can HarmonyOS uiContext.getPromptAction().openCustomDialog implement a page-level popup?

Can uiContext.getPromptAction().openCustomDialog achieve a page-level popup? Or is there a way to open a page-level popup within a page? The scenario is opening a popup on Page A, where clicking a button in the popup opens a new Page B. When returning from Page B to Page A, the opened popup should still be present.

Currently, no component directly supports this effect. You can simulate the popup by referencing the following demo:

import router from '@ohos.router';

@Entry
@Component
struct Index {
  @State textValue: string = 'Hello World'
  @State visible: Visibility = Visibility.None

  build() {
    Stack() {
      Row() {
        Column() {
          Text('Hello World')
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
          Button('click')
            .onClick(() => {
              console.log("hit me!")
              if (this.visible == Visibility.Visible) {
                this.visible = Visibility.None
              } else {
                this.visible = Visibility.Visible
              }
            })
            .backgroundColor(0x777474)
            .fontColor(0x000000)
        }
        .width('100%')
      }
      .height('100%')
      .backgroundColor("#36D")
      Column() {
        GridRow({
          columns:{xs:1 ,sm: 4, md: 8, lg: 12},
          breakpoints: { value: ["400vp", "600vp", "800vp"],
            reference: BreakpointsReference.WindowSize },
        })
        {
          GridCol({
            span:{xs:1 ,sm: 2, md: 4, lg: 8},
            offset:{xs:0 ,sm: 1, md: 2, lg: 2}
          })
         }
       }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2. HarmonyOS return to desktop API?

The return-to-desktop API hangs the app in the background.

You can try obtaining the main window object through windowStage and then minimizing the main window with minimize.

Reference document: https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-window

3. Is implementing portrait-landscape switching in HarmonyOS too cumbersome?

The current experience is poor, requiring the rotation function to be written in the onPageShow of each page (Entry).

You can currently customize a utility class to uniformly manage the display mode of all pages. Refer to this demo:

Index7gongju.ets

import Stack from '@ohos.util.Stack';
import { uiObserver, window } from '@kit.ArkUI';
import { common, UIAbility } from '@kit.AbilityKit';
class MyPage {
  id?: string
  name?: ResourceStr
  path?: string
  type?: string
  lifeCricle?: number
}
interface pageTracking {
  page: MyPage
  // onshown timestamp
  starttime: number
  //停留时间
  statetime: number
}
// Window identifier (string)
let mypagestack: Record<string, Stack<pageTracking>> = {};
let windows: Record<string, window.Window> = {};
let pageOrientations: Record<string, window.Orientation> = {
  "Index": window.Orientation.UNSPECIFIED,
  "Logon": window.Orientation.PORTRAIT,
  "Detail": window.Orientation.LANDSCAPE,
  "Page2": window.Orientation.PORTRAIT_INVERTED,
  "Page3": window.Orientation.LANDSCAPE_INVERTED,
}
// Require mainWindow parameters
// The page path of each window must be a chain; default to main window if not passed
export function observerAll(curWindow: window.Window, windowName ?: string) {
  // Determine if empty (mainWindow)
  if (!windowName || windowName == 'mainWindow') {
    windowName = 'mainWindow'
  }
  let name = windowName as string
  windows[name] = curWindow;
  let myObserve = curWindow.getUIContext().getUIObserver();
  mypagestack[name] = new Stack<pageTracking>();
  // Listen for navDestination component lifecycle changes
  myObserve.on('navDestinationUpdate', (info) => {
    // Map to mypage
    let mypage = new MyPage
    mypage.id = info.navDestinationId
    mypage.name = info.name
    mypage.path = info.param?.toString()
    mypage.type = 'NavDestination'
    mypage.lifeCricle = info.state
    //
    tracking(mypage, name)
  })
  // Listen for page lifecycle changes
  myObserve.on('routerPageUpdate', (info) => {
    // enterPageLoaded = true;
    let mypage = new MyPage
    mypage.id = String(info.index)
    // The name field of router additionally returns the path; take the last name
    mypage.name = info.name.split('/').pop()
    mypage.path = info.path
    mypage.type = 'page'
    mypage.lifeCricle = navState(info.state)
    tracking(mypage, name)
  })
}

// Use mypage for tracking and store lifecycle information
function tracking(mypage: MyPage, windowname: string) {
  let stack: Stack<pageTracking> = mypagestack[windowname]
  let pagetracking: pageTracking;
  // 1. Store page information (abouttoappear) and print all current paths and stack order
  // If the stack has one element and it is a navd page, only modify the page type
  // Do not push to stack; instead, change the type of the top stack element to navPage
  if (mypage.lifeCricle == 2) {
    let firstPage = stack.peek()
    if (stack.length == 1 && firstPage.page.type == 'NavDestination') {
      firstPage = stack.pop()
      firstPage.page.type = 'navPage'
      stack.push(firstPage)
    } else {
      stack.push({
        page: mypage,
        starttime: Date.now(),
        statetime: 0,
      })
      let pagesPath = windowname + ':'
      stack.forEach((pagetraking) => {
        pagesPath += '->' + pagetraking.page.name?.toString()
      })
      console.log(pagesPath)
    }
  }
  // 2. Update page information: onshown (refresh start time)
  else if (mypage.lifeCricle == 0) {
    pagetracking = stack.pop();
    pagetracking.starttime = Date.now()
    stack.push(pagetracking)
    // Change orientation:
    let defaultOrientation = window.Orientation.PORTRAIT
    if (!!pageOrientations[mypage.name as string]) {
      defaultOrientation = pageOrientations[mypage.name as string];
    }
    windows[windowname].setPreferredOrientation(defaultOrientation)

  }
  // 3. Update page information: onhidden (accumulate and refresh stay time)
  else if (mypage.lifeCricle == 1) {
    pagetracking = stack.pop();
    pagetracking.statetime = Date.now() - pagetracking.starttime
    stack.push(pagetracking)
  }
  // 4. Output page information (abouttodistoappear) and delete page information
  else if (mypage.lifeCricle == 3) {
    let pagesPath = windowname + ':'
    //
    // let time=Date.now()-stack.pop().starttime
    // console.log('zyf'+)

    // Display current page stay time

    // stack.forEach((pagetraking) => {
    //   // let time=Date.now()-pagetraking.starttime
    //   // console.log('zyf'+pagetraking.page.name?.toString() + time + 'ms');
    //   console.log('zyf'+pagetraking.page.name?.toString() + pagetraking.statetime + 'ms');
    // })
    let popPage = stack.pop()
    console.log(popPage.page.name?.toString() + ' statetime ' + popPage.statetime + 'ms')
    console.log('popPage :' + popPage.page.name)
    stack.forEach((pagetraking) => {
      pagesPath += '->' + pagetraking.page.name?.toString()
    })
    console.log(pagesPath);
  }
}

// Unify NavDestination and page lifecycles
function navState(state: number): number {
  if (state == 0) {
    return 2
  } else if (state == 1) {
    return 3
  } else if (state == 2) {
    return 0
  } else if (state == 3) {
    return 1
  } else if (state == 4) {
    return 100
  } else {
    return 4
  }
}
Enter fullscreen mode Exit fullscreen mode

Then reference this utility class in Ability and call it in onWindowStageCreate. Refer to the following code:

import { observerAll } from '../pages/Index7gongju';
onWindowStageCreate(windowStage: window.WindowStage): void {

  // Main window is created, set main page for this ability
  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

  windowStage.loadContent('pages/Logon', (err) => {
  if (err.code) {
  hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
  return;
}
try {
  let mainWindow = windowStage.getMainWindowSync()
  observerAll(mainWindow)
} catch (error) {
  console.error(error, "    zzzzzz")
}

hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
});
}
Enter fullscreen mode Exit fullscreen mode

4. How to set the status bar to a background image or color in HarmonyOS?

Refer to the following code:

import { BusinessError } from '@ohos.base';
import { window } from '@kit.ArkUI';

@Entry
@Component
struct  chuangkou{
  build() {
    Button("窗口设置").width(100).height(100)
      .onClick(()=>{
        let SystemBarProperties: window.SystemBarProperties = {
          statusBarColor: '#ffee5610',
        };
        let windowClass: window.Window | undefined = undefined;
        try {
          let promise = window.getLastWindow(getContext());
          promise.then((data) => {
            windowClass = data;
            windowClass.setWindowSystemBarProperties(SystemBarProperties)
            console.info('Succeeded in obtaining the top window. Data: '+ JSON.stringify(data));
          }).catch((err: BusinessError) => {
            console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(err));
          });
        } catch (exception) {
          console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(exception));
        }
      })
  }
}
Enter fullscreen mode Exit fullscreen mode

Reference link: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-window-V5#setwindowsystembarproperties9

5. How to set the screen to always on and set the screen brightness to maximum in HarmonyOS?

Refer to the following code to set the screen to always on via a click event, or configure it through other methods based on business needs:

import { BusinessError } from '@ohos.base';
import { window } from '@kit.ArkUI';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct WebPage {
  private context = getContext(this) as common.UIAbilityContext;
  controller: webView.WebviewController = new webView.WebviewController();
  build() {
    Column() {
      Button('keeplight')
        .onClick(() => {
          // 1. Get the app's main window.
          let windowClass: window.Window | undefined = undefined;
          try {
            window.getLastWindow(this.context, (err: BusinessError, data) => {
              const errCode: number = err.code;
              if (errCode) {
                console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(err));
                return;
              }
              windowClass = data;
              console.info('Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));
              try {
                windowClass.setWindowKeepScreenOn(true, (err: BusinessError) => {
                  const errCode: number = err.code;
                  if (errCode) {
                    console.error('Failed to set the screen to be always on. Cause: ' + JSON.stringify(err));
                    return;
                  }
                  console.info('Succeeded in setting the screen to be always on.');
                });
              } catch (exception) {
                console.error('Failed to set the screen to be always on. Cause: ' + JSON.stringify(exception));
              }
            });
          } catch (exception) {
            console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(exception));
          }
        })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Console output when clicking the button:

05-15 14:48:04.050   12178-12178  A03d00/JSAPP                   com.examp...lication  I     Succeeded in obtaining the top window. Data: {}
05-15 14:48:04.059   12178-12178  A03d00/JSAPP                   com.examp...lication  I     Succeeded in setting the screen to be always on.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)