DEV Community

Cover image for Intercepting Touch Events, Disabling Side Swipe Back, Data-Driven UI, Text Ellipsis Trigger
kouwei qing
kouwei qing

Posted on

Intercepting Touch Events, Disabling Side Swipe Back, Data-Driven UI, Text Ellipsis Trigger

[Daily HarmonyOS Next Knowledge] Intercepting Touch Events, Disabling Side Swipe Back, Data-Driven UI, Text Ellipsis Trigger, Obtaining Component Screen Coordinates

1. How does a HarmonyOS child component intercept touch events?

When nesting a Scroll component within a page, attempting to intercept touch events via event.stopPropagation() in onTouch to prevent the Scroll from scrolling when the child component is swiped, but this approach is ineffective. How to handle this?

Stack() {
  Canvas(this.pickCanvas)
}.width('100%').height(200).onTouch((event: TouchEvent) => {
  event.stopPropagation()
})
Enter fullscreen mode Exit fullscreen mode

Try adding .hitTestBehavior(HitTestMode.Block) to the Canvas component.

Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-universal-attributes-hit-test-behavior-V5

This property sets the touch test mode. The ArkUI framework performs touch tests before event distribution to collect components that should respond to touch events. hitTestBehavior affects touch test results and subsequent event distribution (see HitTestMode enum for details).

Long-press the Canvas area to enter Canvas interaction; click outside Canvas to exit and enable Scroll scrolling.

Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-gestures-tapgesture-V5

@Entry
@Component
export struct PageE {
  @State isCheck: boolean = false;
  private scrollerView: Scroller = new Scroller()
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private chartCanvas: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex() {
      Scroll(this.scrollerView) {
        Column() {
          Text("Scroll Area").width("100%").height("40%").backgroundColor(0X330000FF)

          Stack() {
            Canvas(this.chartCanvas)
              .width('100%')
              .height('100%')
              .onReady(() => {
                let c = this.chartCanvas
                c.fillStyle = "#f00"
                c.fillRect(20, 20, c.width - 40, c.height - 40)
              })
              .onTouch((event: TouchEvent) => {
                console.log("111")
                // Use touch events for canvas drawing (e.g., chart dragging)
                // Expect no outer Scroll scrolling during canvas interaction
              })
              .hitTestBehavior(this.isCheck ? HitTestMode.Block : HitTestMode.Default)
              .gesture(
                LongPressGesture()
                  .onAction((event: GestureEvent) => {
                    console.log("111222")
                    if (!this.isCheck) {
                      this.isCheck = !this.isCheck
                    }
                  }), GestureMask.IgnoreInternal
              )
          }
          .backgroundColor("#ffff00").width('100%').height(200)

          Text("Scroll Area")
            .width("100%").height("40%").backgroundColor(0X330000FF)
        }
      }
      .priorityGesture(
        TapGesture()
          .onAction((event: GestureEvent) => {
            console.log("333333")
            if (this.isCheck) {
              this.isCheck = !this.isCheck
            }
          }), GestureMask.Normal
      )
      .width("100%").height("100%")
    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
  }
}
Enter fullscreen mode Exit fullscreen mode

2. How to disable side swipe back for popups on a HarmonyOS page?

Disabling side swipe back via .onBackPressed(() => true) on the page, but popups still respond to side swipes.

Use onWillDismiss.

Reference: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md#customdialogcontrolleroptions%E5%AF%B9%E8%B1%A1%E8%AF%B4%E6%98%8E

3. How does data from a HarmonyOS ViewModel drive UI updates?

How to use data from a ViewModel to drive UI updates (components can use @State and related decorators for UI updates).

Apply @ObjectLink and @Observed class decorators.

Reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-observed-and-objectlink-V5#%E5%9C%A8%E5%AD%90%E7%BB%84%E4%BB%B6%E4%B8%AD%E7%BB%99objectlink%E8%A3%85%E9%A5%B0%E7%9A%84%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC

4. How to detect if TextOverflow.Ellipsis is triggered for a HarmonyOS Text component?

Refer to the following demo:

import measure from '@ohos.measure'
@Entry
@Component
struct MeasurePage {
  @State rawTitle: string = "1月16日,国务院新闻办公室举行新闻发布会,介绍2024年春运形势及工作安排。从2月9日(除夕)00:00到2月17日(正月初八)24:00,免费9天。1月16日,国务院新闻办公室举行新闻发布会,介绍2024年春运形势及工作安排"
  @State title: string = this.rawTitle 
  @State suffixStr: string = ""
  expanded: Boolean = true
  titleWidth: number = 350
  needProcess: boolean = true
  ellipsis: string = "..."
  EXPAND_STR: string = "展开"
  COLLAPSE_STR: string = "收起"
  MAX_LINES: number = 2;
  fontSize: number = 16

  aboutToAppear(): void {
    this.process();
  }
  process(): void {
    if (this.expanded) {
      this.collapseText();
    } else {
      this.expandText();
    }
  }
  expandText(): void {
    if (this.needProcess) {
      this.suffixStr = this.COLLAPSE_STR; 
      this.expanded = true;
      this.title = this.rawTitle;
    }
  }
  collapseText(): void {
    if (!this.needProcess) {
      return;
    }
    let titleSize: SizeOptions = measure.measureTextSize({
      textContent: this.rawTitle,
      constraintWidth: this.titleWidth,
      fontSize: this.fontSize
    })
    let twoLineSize: SizeOptions = measure.measureTextSize({
      textContent: this.rawTitle,
      constraintWidth: this.titleWidth,
      fontSize: this.fontSize,
      maxLines: this.MAX_LINES
    })
    if ((titleSize.height as number) == (twoLineSize.height as number)) {
      this.needProcess = false;
      return;
    }
    let clipTitle: string = this.rawTitle
    this.suffixStr = this.EXPAND_STR;
    while ((titleSize.height as number) > (twoLineSize.height as number)) {
      this.expanded = true;
      clipTitle = clipTitle.substring(0, clipTitle.length - 1);
      titleSize = measure.measureTextSize({
        textContent: clipTitle + this.ellipsis,
        constraintWidth: this.titleWidth,
        fontSize: this.fontSize
      })
    }
    this.title = clipTitle + this.ellipsis
    this.expanded = false;
  }
  build() {
    Row() {
      Column() {
        Text(){
          Span(this.title)
        }
        .fontSize(this.fontSize)
        .id("title")
        .width(this.titleWidth)
        if (this.needProcess) {
          Text(this.suffixStr)
            .fontColor(Color.Orange)
            .onClick((event) => {
            this.process();
          })
        }
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)
    }
    .height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

5. How to obtain the screen coordinates of a view in HarmonyOS?

Detailed reference: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-universal-attributes-component-id-V5

Top comments (0)