DEV Community

Cover image for Obtaining Page Stack Objects, Canvas Animations, Security Buttons, Modifying Image Colors in Image Components
kouwei qing
kouwei qing

Posted on

Obtaining Page Stack Objects, Canvas Animations, Security Buttons, Modifying Image Colors in Image Components

【Daily HarmonyOS Next Knowledge】Obtaining Page Stack Objects, Canvas Animations, Security Buttons, Modifying Image Colors in Image Components, Setting Popups to Display Only on the Current Page

1. How to obtain the page stack object in HarmonyOS?

How to get the current page hierarchy and the page hierarchy object through the router, such as pages A - B - C, where page C can obtain the list of current page hierarchies and the corresponding page objects.

Currently, only information about the current page in the router page stack can be obtained, such as the index, path, page name, and the number of pages in the page stack. Obtaining the list of the page stack is not supported yet.

For navigation within and between modules, use Navigation as much as possible, as the router will stop evolving and may not add new capabilities in the future. The tight coupling caused by using Navigation for inter-module navigation can be solved by dynamic imports. The router does not support fine-grained operations on the page stack. For clearing the stack, such as A-B-B1, clearing page B from page B1 is not supported; only clear can be used to remove all pages except the current one. The router does not support skipping more than 32 pages, and the maximum capacity of the page stack is 32 pages. The router's routing stack only supports obtaining the properties of the top page, including only the current page path and file name. Navigation will continue to evolve, so if capabilities are insufficient, requirements can be planned further. In Navigation, you can use getAllPathName to obtain the names of all NavDestination pages in the stack (for details, refer to Example 2 in the link below: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-navigation-V5#getallpathname10)

// Index.ets
@Entry
@Component
struct NavigationExample {
  pageInfos: NavPathStack = new NavPathStack();
  isUseInterception: boolean = false;

  registerInterception() {
    this.pageInfos.setInterception({
      // Intercept before page navigation, allowing stack operations that take effect in the current navigation.
      willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
        operation: NavigationOperation, animated: boolean) => {
        if (!this.isUseInterception) {
          return;
        }
        if (typeof to === "string") {
          console.log("target page is navigation home");
          return;
        }
        // Redirect the target page, changing from pageTwo to pageOne.
        let target: NavDestinationContext = to as NavDestinationContext;
        if (target.pathInfo.name === 'pageTwo') {
          target.pathStack.pop();
          target.pathStack.pushPathByName('pageOne', null);
        }
      },
      // Callback after page navigation; stack operations in this callback refresh on the next navigation.
      didShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
        operation: NavigationOperation, isAnimated: boolean) => {
        if (!this.isUseInterception) {
          return;
        }
        if (typeof from === "string") {
          console.log("current transition is from navigation home");
        } else {
          console.log(`current transition is from  ${(from as NavDestinationContext).pathInfo.name}`);
        }
        if (typeof to === "string") {
          console.log("current transition to is navBar");
        } else {
          console.log(`current transition is to ${(to as NavDestinationContext).pathInfo.name}`);
        }
      },
      // Triggered when the Navigation single/double bar display state changes.
      modeChange: (mode: NavigationMode) => {
        if (!this.isUseInterception) {
          return;
        }
        console.log(`current navigation mode is ${mode}`);
      }
    });
  }

  build() {
    Navigation(this.pageInfos) {
      Column() {
        Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.pageInfos.pushPath({ name: 'pageOne' }); // Push the NavDestination page information specified by name onto the stack
          });
        Button('use interception', { stateEffect: true, type: ButtonType.Capsule })
          .width('80%')
          .height(40)
          .margin(20)
          .onClick(() => {
            this.isUseInterception = !this.isUseInterception;
            if (this.isUseInterception) {
              this.registerInterception();
            } else {
              this.pageInfos.setInterception(undefined);
            }
          });
      }
    }.title('NavIndex');
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Animation demo based on drawing.canvas in HarmonyOS?

Refer to: https://developer.huawei.com/consumer/cn/blog/topic/03797837883380062

3. Security button returns permission failure in HarmonyOS?

The security button returns a permission failure with result as TEMPORARY_AUTHORIZATION_FAILED. How to solve it?

// With default parameters, the icon, text, and background all exist
SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
  if (result === SaveButtonOnClickResult.SUCCESS) {}
});
Enter fullscreen mode Exit fullscreen mode

Using a URI to open a file allows continuous writing without time restrictions:

let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
Enter fullscreen mode Exit fullscreen mode

This requires corresponding permissions, which need to be defined in modules.json5:

{
  "name": "ohos.permission.WRITE_MEDIA",
  "reason": "$string:EntryAbility_desc",
  "usedScene": {
    "abilities": ["EntryAbility"],
    "when": "always"
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Can the color of an image be dynamically modified after setting a local resource file in the HarmonyOS Image component?

Refer to the following document: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-components-image-V5#colorfilter9

colorFilter(value: ColorFilter | DrawingColorFilter)

Sets a color filter effect for the image.

When this property is set, the renderMode property has no effect.

Parameter Name Type Required Description
value ColorFilter \ DrawingColorFilter Yes

Image description



2. Starting from API Version 12, the ColorFilter type from @ohos.graphics.drawing is supported as a parameter.

Note:
For API Version 11 and earlier, this property is not supported for SVG image sources.
Starting from API Version 12, the DrawingColorfilter type in this interface is supported for use in meta services, where SVG image sources must have a stroke property. |

5. How to set a popup to display only on the current page in HarmonyOS?

A popup is used as a notification prompt. When page A shows the popup and then navigates to page B, the popup still appears on page B. Can the popup be set to display only on page A?

The current behavior of popups is as described. You can use CustomDialog instead. Refer to the document: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-common-components-custom-dialog-V5

Sample demo:

import router from '@ohos.router';

@CustomDialog
export default struct UserPrivacyDialog {
  controller: CustomDialogController = new CustomDialogController({ builder: '' });
  cancel: Function = () => {};
  confirm: Function = () => {};
  visible: Visibility = Visibility.None;

  build() {
    Column() {
      Text('I am a popup');

      Button('jump')
        .onClick(() => {
          router.pushUrl({
            url: 'pages/Second'
          });
        })
        .backgroundColor(0xffffff)
        .fontColor(Color.Red);
    }
    .margin({ top: 22 })
    .justifyContent(FlexAlign.SpaceEvenly);
  }
}

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

  build() {
    Stack() {
      Row() {
        Column() {
          Button('click')
            .onClick(() => {
              if (this.visible === Visibility.Visible) {
                this.visible = Visibility.None;
              } else {
                this.visible = Visibility.Visible;
              }
            })
            .backgroundColor(0x777474)
            .fontColor(0x000000);
        }
        .width('100%');
      }
      .height('100%')
      .backgroundColor(0x885555);

      Text('')
        .onClick(() => {
          if (this.visible === Visibility.Visible) {
            this.visible = Visibility.None;
          } else {
            this.visible = Visibility.Visible;
          }
        })
        .width('100%')
        .height('100%') // Transparency can be adjusted
        .opacity(0.16)
        .backgroundColor(0x000000)
        .visibility(this.visible);

      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 }
          }) {
            Column() {
              Flex({ justifyContent: FlexAlign.SpaceAround }) {
                UserPrivacyDialog();
              }.margin({ bottom: 10 });
            }
            .backgroundColor(0xffffff)
            .visibility(this.visible)
            .clip(true)
            .borderRadius(20);
          }
        }
      }.width('95%'); // Set popup width
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Refer to componentUtils.getRectangleById: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-arkui-componentutils-V5#componentutilsgetrectanglebyid

getRectangleById(id: string): ComponentInfo

Obtains the component instance object by component ID and synchronously returns the obtained coordinates and size to the developer through the component instance object.

Top comments (0)