DEV Community

Cover image for Pixel Unit Conversion, Dialog Declaration Issues, List Nesting, Byte Stream to Image
kouwei qing
kouwei qing

Posted on

Pixel Unit Conversion, Dialog Declaration Issues, List Nesting, Byte Stream to Image

【Daily HarmonyOS Next Knowledge】Pixel Unit Conversion, Dialog Declaration Issues, List Nesting, Byte Stream to Image, Builder Function State Not Triggering UI Changes

1. Which pixel unit should be used in HarmonyOS?

The UI provides an image with 750 pixels. When developing, for a button with a width of 100px/100dp, should we use px2vp(100), 100/2 = 50vp, or another approach?

For specific conversion between vp and px, refer to: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-pixel-units-V5#%E5%83%8F%E7%B4%A0%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2

Interface Description
vp2px(value: number): number Converts a value in vp units to px units.

Note:

Uses the virtual pixel ratio of the current UI instance's screen by default. If the UI instance is not created, uses the default screen's virtual pixel ratio.
px2vp(value: number): number Converts a value in px units to vp units.

Note:

Uses the virtual pixel ratio of the current UI instance's screen by default. If the UI instance is not created, uses the default screen's virtual pixel ratio.
fp2px(value: number): number Converts a value in fp units to px units.
px2fp(value: number): number Converts a value in px units to fp units.
lpx2px(value: number): number Converts a value in lpx units to px units.
px2lpx(value: number): number Converts a value in px units to lpx units.

2. Why can't CustomDialogController be declared outside a Component in HarmonyOS?

I want to create a project-wide LoadingDialog for convenient calling, such as globalDialogController.show().

The custom dialog CustomDialogController is only valid when used as a member variable of @CustomDialog and @Component structs and assigned within the @Component struct. Use promptAction.openCustomDialog for dialog rendering instead of CustomDialogController.

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

3. Can the HarmonyOS List component not be nested with the Grid component?

Rendering Grid components within ListItem of the List component is invalid.

Sample code for testing:

@Entry
@Component
struct Index6 {
  build() {
    Row() {
      Column() {
        List() {
          ListItem() {
            Text("I am a ListItem")
          }.height(200)
          ListItem() {
            Grid() {
              ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number) => {
                GridItem() {
                  Column() {
                    Text(`number:${item}`)
                  }
                  .backgroundColor(`#87${item}`)
                }
              })
            }
            .rowsTemplate('1fr 1fr 1fr 1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
            .rowsGap(30)
            .columnsGap(20)
            .backgroundColor("#987")
          }.height(200)
        }
      }
      .width('100%')
    }
    .height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

4. How to display image data in byte[] format in an Image component in HarmonyOS?

Convert the buffer to a PixelMap and then load it. Example:

let imageSource = image.createImageSource(buffer)
let options = {
  alphaType: 0,                    // Transparency
  editable: false,                 // Editable status
  pixelFormat: 3,                  // Pixel format
  scaleMode: 1,                    // Scaling mode
  size: { height: 100, width: 100 } // Created image size
}
imageSource.createPixelMap(options).then((pixelMap) => {
  this.image = pixelMap
})
Enter fullscreen mode Exit fullscreen mode

5. Why doesn't the state variable received by a HarmonyOS @builder function trigger internal UI changes?

The ChangePinPage interface invokes a custom keyboard. Modifying currentKeyboardType (keyboard type) in the custom keyboard's button component to switch between Chinese and English keyboards does not update the value of Text($\{$$.currentKeyboardType}) in CustomKeyboard.ets.

// xxxModel.ets
export class Tmp {
  inputController: TextInputController;
  currentKeyboardType: number;
  constructor(inputController: TextInputController, currentKeyboardType: number) {
    this.inputController = inputController;
    this.currentKeyboardType = currentKeyboardType
  }
}
# ChangePinPage.ets:
@Provide currentKeyboardType: number = Const.KEYBOARD_TYPE_NUMBER; 
...
TextInput()
.customKeyboard(KeyBoardWindow(new Tmp(this.oldPinController, this.currentKeyboardType)))
# CustomKeyboard.ets:
@Builder
export function KeyBoardWindow($$: Tmp) {
  Column() {
    Row() {
      Image($r("app.media.ic_keyboard_down"))// "Collapse" icon in the title row
        .onClick(() => {
          $$.inputController.stopEditing()
        })
      Text(`${$$.currentKeyboardType}`)
   }
}
// xxxChild.ets ...
@Consume currentKeyboardType: number;
...
this.currentKeyboardType = 2;
Enter fullscreen mode Exit fullscreen mode

For global @builder custom build functions using reference passing, if placed within Navigation()'s menus, state variable changes will not trigger UI refresh in the @builder method.

When passing parameters by reference, the parameters can be state variables, and state variable changes will trigger UI refresh in the @builder method.

Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-builder-V5

Related demo:

@Builder function ABuilder($$: { paramA1: string }) {
  Row() {
    Text(`UseStateVarByReference: ${$$.paramA1} `)
  }
}
@Entry
@Component
struct Parent {
  @State label: string = 'Hello';
  build() {
    Column() {
      // When calling ABuilder in the Parent component, pass this.label by reference to ABuilder
      ABuilder({ paramA1: this.label })
      Button('Click me').onClick(() => {
        // After clicking "Click me", the UI refreshes from "Hello" to "ArkUI"
        this.label = 'ArkUI';
      })
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)