Zum Inhalt springen

Overlay Order, Dialog Positioning, Event Bus, PageMap Display, Multi-Table Multi-Item Types

[Daily HarmonyOS Next Knowledge] Overlay Order, Dialog Positioning, Event Bus, PageMap Display, Multi-Table Multi-Item Types

1. HarmonyOS WebView layout with input fields causes bottom text to be pushed up, leading to layout overlap?

The layering of WebView can be controlled via the z-index.

Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-universal-attributes-z-order-V5

zIndex

zIndex(value: number)

Sets the stacking order of components.

Parameters:

Parameter Name Type Required Description
value number Yes Defines the stacking order of sibling components in the same container. A larger zIndex value means a higher stacking order, causing the component to overlay those with smaller values. When dynamically changing zIndex without adding/removing sibling nodes, the order is stabilized based on the previous hierarchy.

Example (Setting component stacking order):

// xxx.ets
@Entry
@Component
struct ZIndexExample {
  build() {
    Column() {
      Stack() {
        // Stack overlays components; by default, later-defined components are on top. Components with higher zIndex values appear in front of those with lower values.
        Text('1, zIndex(2)')
          .size({ width: '40%', height: '30%' }).backgroundColor(0xbbb2cb)
          .zIndex(2)
        Text('2, default zIndex(1)')
          .size({ width: '70%', height: '50%' }).backgroundColor(0xd2cab3).align(Alignment.TopStart)
          .zIndex(1)
        Text('3, zIndex(0)')
          .size({ width: '90%', height: '80%' }).backgroundColor(0xc1cbac).align(Alignment.TopStart)
      }.width('100%').height(200)
    }.width('100%').height(200)
  }
}

2. HarmonyOS custom Dialog is positioned at the bottom of the page, but there is a large gap between the popped soft keyboard and the dialog?

Reference code:

import window from '@ohos.window'
import { data } from '@kit.TelephonyKit'

@Entry
@Component
export struct LightPublishMine {
  private window?: window.Window
  @State keyboardHeightVp: number = 0
  @State navHeight: number = 0
  @State safeAreaTop: number = 0

  aboutToAppear() {
    window.getLastWindow(getContext(this)).then((win) => {
      this.window = win
      if (this.window) {
        this.navHeight = px2vp(this.window.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
          // Navigation bar height
          .bottomRect.height
        )
        this.safeAreaTop = px2vp(this.window.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height)
        this.window.on('keyboardHeightChange', (data) => {
          console.info('Succeeded in enabling the listener for keyboard height changes. 键盘 Data: ' + data);
          this.keyboardHeightVp = px2vp(data)
          console.info('Succeeded in enabling the listener for keyboard height changes. Data: ' + (this.keyboardHeightVp - this.navHeight));
          console.info('Succeeded in enabling the listener for keyboard height changes. 导航条Data: ' + this.navHeight);
        });
      }
    })
  }

  aboutToDisappear() {
    if (this.window) {
      this.window.off('keyboardHeightChange')
      this.window = undefined
    }
    this.keyboardHeightVp = 0
  }

  build() {
    Row() {
      Column() {
        TextInput().backgroundColor(Color.White)
        Blank().backgroundColor(Color.Red).height(this.keyboardHeightVp - this.navHeight).width('100%')
      }.width('100%')
    }
    .height('100%')
    .backgroundColor(Color.Green)
    .alignItems(VerticalAlign.Bottom)
    .expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM])
  }
}
@Entry
@Component
struct CustomDialogUser {
  dialogController: CustomDialogController = new CustomDialogController({
    builder: CommentInputDialog({}),
    alignment: DialogAlignment.Bottom,
    customStyle: true,
    offset: { dx: 0, dy: 100 }
  })
  build() {
    Column() {
      Button('click me')
        .onClick(() => {
          this.dialogController.open()
        })
    }.width('100%').height('100%').backgroundColor(Color.Red)
  }
}
// Set customStyle to true and add an offset to the internal Column of the dialog: .offset({ x: 0, y: 20 })

@CustomDialog
export struct CommentInputDialog{
  private statusBarHeight: number = (AppStorage.get('statusBarHeight') as number);
  controller?: CustomDialogController
  private commentContent: string = ''
  onTap: (content: string) => void = () => {
  };

  build() {
    Column(){
      Image($r('app.media.black_close_icon'))
        .width(26)
        .height(26)
        .onClick(() =>{
          this.controller?.close();
        })

      TextArea({ placeholder: '我来说两句...', text: this.commentContent})
        .placeholderColor($r('app.color.color909099'))
        .backgroundColor($r('app.color.colorF7F8F9'))
        .borderRadius(4)
        .placeholderFont({
          size: '17fp',
          family: CommonConstants.SI_YUAN
        })
        .backgroundColor(Color.White)
        .enterKeyType(EnterKeyType.Done)
        .defaultFocus(true)
        .onChange((value) => {
          this.commentContent = value;
        }).margin({top: 10, bottom: 10})
        .layoutWeight(1)

      Text('确认')
        .width(60)
        .height(30)
        .fontColor(Color.White)
        .fontSize('14fp')
        .fontFamily(CommonConstants.SI_YUAN)
        .textAlign(TextAlign.Center)
        .backgroundColor($r('app.color.colorF21333'))
        .borderRadius(15)
        .onClick(() =>{
          this.onTap(this.commentContent)
        })
    }
    .width(CommonConstants.FULL_PERCENT)
    .height(210 + this.statusBarHeight)
    .padding({left: 15, top: 15, right: 15, bottom: 10 + this.statusBarHeight })
    .alignItems(HorizontalAlign.End)
    .backgroundColor($r('app.color.colorF1F2F3'))
    .borderRadius({topLeft: 15, topRight: 15})
    .offset({ x: 0, y: 20}) // Set offset
  }
}

3. Does HarmonyOS ArkTS support a global notification mechanism similar to Vue’s event bus?

After calling router.back(), page data is not re-rendered. We need an event bus that:

  1. Triggers page data updates.
  2. Is not bound to the component lifecycle (callable from any location when the bus method is triggered).

Related documentation for global notifications:

4. In HarmonyOS, only the first two components in navDestination’s PageMap are displayed, while the third and subsequent ones are not?

When using Navigation with navDestination(this.PageMap), only the first and second components in PageMap are displayed, while the third component is not shown after navigation.

Solution: Use an if () {} else if () {} structure:

@Builder
PagesMap(name: string) {
  if (name === 'Page01') {
    Page01()
  }
  else if (name === 'Page02') {
    Page02()
  }
  else if (name === 'Page03') {
    Page03()
  }
  else if (name === 'Page04') {
    Page04()
  }
}

5. How to handle a list with over 10 item types in HarmonyOS?

Table-driven approach: For fixed-pattern if…else logic, use a mapping table to relate input values to processing functions.

Applicable scenario: Fixed-pattern if…else logic.

Implementation and example:

// Original code
if (param.equals(value1)) {
  doAction1(someParams);
} else if (param.equals(value2)) {
  doAction2(someParams);
} else if (param.equals(value3)) {
  doAction3(someParams);
}
// ...

// Refactored with table-driven approach
Map<?, Function<?> action> actionMappings = new HashMap<>(); // Replace ? with actual types

// During initialization
actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
actionMappings.put(value3, (someParams) -> { doAction3(someParams)});

// Omit null checks
actionMappings.get(param).apply(someParams);

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert