DEV Community

HarmonyOS
HarmonyOS

Posted on

How to hide or show the overflowing part of a Text component when the text exceeds a specific length?

Read the original article:How to hide or show the overflowing part of a Text component when the text exceeds a specific length?

Problem Description

When displaying text in a Text component, if the text exceeds a certain length, there is often a need to hide or show the overflowing part. For example, when the maximum number of visible lines is 2 and the component width ratio is 0.4, how can this be achieved?

Background Knowledge

  • measureText method: Can calculate the width of text based on its content.
  • getAllDisplays method: Can retrieve display objects, where the width property represents the screen width.

Troubleshooting Process

  • Measured the actual width of the text using measureText.
  • Retrieved the screen width via getAllDisplays.
  • Compared the calculated allowed text width (Screen Width × Max Lines × Component Width Ratio) with the actual text width.
  • Determined whether the text needs to be truncated and whether an expand/collapse toggle is required.

Analysis Conclusion

The overflow occurs because the text exceeds the allowed width for the specified number of lines. To solve this, the text must be truncated dynamically, with an interactive element to expand or collapse the hidden portion.

Solution

First, calculate the allowed text length using the formula:

Allowed Text Length = Screen Width × Maximum Number of Lines × Component Width Ratio.

The screen width can be obtained using the getAllDisplays method.

Next, use the measureText method to measure the actual text width. Compare the “allowed text length” with the actual text width to determine whether hiding is needed.

If hiding is necessary, display only the portion of text within the allowed length, appending “...”. When the user clicks on “…”, expand the text to show the hidden portion, changing the indicator to “…Collapse”.

The code is as follows:

import { MeasureUtils } from '@kit.ArkUI';
import curves from '@ohos.curves';
import { BusinessError } from '@ohos.base';
import display from '@ohos.display';

@Entry
@Component
struct Index {
  // Long text
  @State longMessage: string = 'Walking on the bustling city streets, Mingkong felt extremely nervous. His heartbeat thumped like a drum in his chest, making it seem as if his disguise could be exposed at any moment. However, he remained calm, relying on his extraordinary courage and intelligence to successfully evade the enemy’s layers of blockade.\n' +
    '\n' +
    'Finally, Mingkong arrived at the lair of the hostile gang. At this moment, the guards were immersed in a celebratory atmosphere, completely unaware of the impending danger. Mingkong took a deep breath, suppressed his excitement, and quietly sneaked into this ancient building.'

  // Maximum number of visible lines
  @State lines: number = 2;

  // Long text state (expanded or collapsed)
  @State collapseText: string = '...'

  // Screen width (unit: px)
  screenWidth: number = 0;

  // Whether to show "expand" text (note: if the text is short, no need for "expand")
  @State isExpanded: boolean = false

  @State uiContext: UIContext = this.getUIContext();
  @State uiContextMeasure: MeasureUtils = this.uiContext.getMeasureUtils();

  // Measure text width (unit: px)
  @State textWidth: number = this.uiContextMeasure.measureText({
    textContent: this.longMessage,
    fontSize: 20
  })

  // Get all current display objects
  promise: Promise<Array<display.Display>> = display.getAllDisplays()

  aboutToAppear() {
    console.info(`Text width: ${this.textWidth}`)
    this.promise.then((data: Array<display.Display>) => {
      console.info(`All display information: ${JSON.stringify(data)}`)
      // Unit: pixels
      this.screenWidth = data[0]["width"]
      // Compare screen width * max lines * component width ratio with measured text width
      this.isExpanded = this.screenWidth * this.lines * 0.4 <= this.textWidth
    }).catch((err: BusinessError) => {
      console.error(`Failed to obtain all the display objects. Code: ${JSON.stringify(err)}`)
    })
  }

  build() {
    Row() {
      Column() {
        if (this.isExpanded) {
          Stack({ alignContent: Alignment.BottomEnd }) {
            Text(this.longMessage)
              .fontSize(20)
              .fontColor(Color.Black)
              .maxLines(this.lines)
              .width("40%")
            Row() {
              Text(this.collapseText)
                .fontSize(20)
                .backgroundColor(Color.White)
            }
            .justifyContent(FlexAlign.End)
            .onClick(() => {
              if (this.collapseText == '...') {
                this.collapseText = '...Collapse';
                // Expand animation
                animateTo({
                  duration: 150,
                  curve: curves.springMotion(0.5, 0.8),
                }, () => {
                  this.lines = -1; // Disable max lines limit
                })
              } else {
                this.collapseText = '...';
                // Collapse animation
                animateTo({
                  duration: 100,
                  curve: Curve.Friction,
                }, () => {
                  this.lines = 2; // Show only 2 lines
                })
              }
            })
          }
        } else {
          Text(this.longMessage)
            .fontSize(20)
            .fontColor(Color.Black)
        }
      }
      .width('100%')
    }
    .height('100%')
  }
}
Enter fullscreen mode Exit fullscreen mode

Verification Result

  • Text exceeding the allowed lines is correctly truncated.
  • "Expand" and "Collapse" toggles function as expected.
  • Both short and long texts render properly within the component.

  • This example supports API Version 19 Release and above.

  • This example supports HarmonyOS 5.1.1 Release SDK and above.

  • This example requires DevEco Studio 5.1.1 Release or above for compilation and execution.

Related Documents or Links

https://developer.huawei.com/consumer/en/doc/harmonyos-references/js-apis-display#displaygetalldisplays9

Written by Emine Inan

Top comments (0)