HarmonyOS鸿蒙Next中如何实现文本断行显示展开收起功能?

HarmonyOS鸿蒙Next中如何实现文本断行显示展开收起功能? 指定行数超出部分显示…展开,文本高亮,点击展开后显示全部文本同时显示收起按钮,点击后收起到指定行数。文本内容未超出指定行数时,显示原文本,没有展开收起按钮。

5 回复

这是一个很常见的需求,实现的大致思想是:

1、通过 getMeasureUtils().measureTextSize 可以计算文本在给定宽度和字体大小后的高度。

2、我们计算文本在指定行数所需要的高度,与文本实际所需的高度做对比。

3、如果实际高度大于指定高度,就将文本长度-1后,继续执行步骤2.

4、直到实际高度等于指定高度,就可以得出指定行数所需要显示的文本。

预览效果:

cke_18377.gif

完整的demo代码:

/**
 * @fileName : ExpandText.ets
 * @author : @cxy
 * @date : 2025/12/18
 * @description : 实现文本断行显示展开收起功能
 */
import { display, LengthMetrics } from '@kit.ArkUI'


@Component
export struct ExpandText {
  @State message: string = ''
  @State isCollapseStatus: boolean = false //是否是折叠状态
  @State breakContent: string = ''
  private content = '这个demo演示了限制文本行数,超出部分显示...展开,文本高亮,点击展开后显示全部文本并显示收起按钮,点击后收起到指定行。未超出时,显示原文本。'
  private expand: string = '展开'
  private collapse: string = '收起'
  private fSize: number = 15
  private limitLine: number = 2

  build() {
    Column() {
      Text() {
        Span(this.message)
        if (this.breakContent) {
          Span(this.isCollapseStatus ? this.expand : this.collapse)
            .fontColor(Color.Blue)
            .onClick(() => {
              this.isCollapseStatus = !this.isCollapseStatus
              this.message = this.isCollapseStatus ? this.breakContent : this.content
            })
        }
      }
      .lineSpacing(LengthMetrics.vp(8))
      .fontSize(this.fSize)
      .width('100%')
    }
    .width('100%')
    .padding(40)
  }

  onDidBuild(): void {
    this.handleContent()
  }

  private handleContent() {
    const context = this.getUIContext()
    const screen = display.getDefaultDisplaySync()
    const screenWidth = context.px2vp(screen.width)

    const width = screenWidth - 40 * 2
    const textSizeShowHeight = this.getContentHeight(this.content, width, this.fSize, this.limitLine)
    const isOver2Line = this.isOverMaxLines(this.content, width, textSizeShowHeight, this.fSize, this.limitLine)
    if (isOver2Line) {
      this.isCollapseStatus = true
      const text = this.content.slice(0, 70) //超过70字的部分去掉,减少不必要的递归
      this.breakContent = this.getBreakText(text, this.expand, width, textSizeShowHeight, this.fSize, this.limitLine)
      this.message = this.breakContent
    } else {
      this.isCollapseStatus = false
      this.message = this.content
    }
  }

  /**
   * 获取文本所需高度
   * @param content 文本内容
   * @param width 文本宽度
   * @param fontSize 文本字体大小
   * @param maxLines 文本显示行数
   * @returns 所占高度
   */
  private getContentHeight(content: string, width: number, fontSize: number, maxLines: number): number {
    const context = this.getUIContext()
    const textSizeShow: SizeOptions = context.getMeasureUtils().measureTextSize({
      textContent: content,
      constraintWidth: width,
      fontSize: fontSize,
      overflow: TextOverflow.Ellipsis,
      maxLines: maxLines
    })
    return textSizeShow.height as number || 0
  }

  /**
   * 判断文本内容是否超出指定行数
   * @param content 文本内容
   * @param width  文本宽度
   * @param height  指定行数后计算得到的高度
   * @param fontSize 文本字体
   * @param maxLines 指定行数
   * @returns
   */
  private isOverMaxLines(content: string, width: number, height: number, fontSize: number, maxLines: number): boolean {
    const textSizeShowHeight2 = this.getContentHeight(content, width, fontSize, 2000000)
    if (textSizeShowHeight2 > height) {
      return true
    }
    return false
  }

  /**
   * 获取折段后的文本
   * @param content 文本内容
   * @param tail 尾部拼接文本
   * @param width  文本宽度
   * @param height  指定行数后计算得到的高度
   * @param fontSize 文本字体
   * @param limitLines 限制行数
   * @returns
   */
  private getBreakText(content: string, tail: string, width: number, height: number, fontSize: number,
    limitLines: number): string {
    const isOver2Line = this.isOverMaxLines(content + '...' + tail, width, height, fontSize, limitLines)
    if (isOver2Line) {
      const newContent = content.slice(0, -1)
      return this.getBreakText(newContent, tail, width, height, fontSize, limitLines)
    }
    return content + '...'
  }
}

更多关于HarmonyOS鸿蒙Next中如何实现文本断行显示展开收起功能?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


赞👍大佬

这个厉害了

在HarmonyOS Next中,实现文本断行显示展开收起功能,主要使用Text组件的maxLines属性控制显示行数,结合onClick事件切换状态。

示例代码:

@State isExpanded: boolean = false

Text(长文本内容)
  .maxLines(this.isExpanded ? undefined : 3)
  .onClick(() => {
    this.isExpanded = !this.isExpanded
  })

通过点击文本切换isExpanded状态,实现展开收起效果。

在HarmonyOS Next中实现文本断行显示展开收起功能,可以通过Text组件结合TextOverflow和自定义状态管理来实现。以下是核心实现步骤:

  1. 基础布局与行数限制
    使用Text组件,通过maxLines属性限制最大显示行数,并设置textOverflowTextOverflow.Ellipsis实现超出部分显示“…”:

    Text(content)
        .maxLines(showAll ? undefined : maxLines) // 控制行数
        .textOverflow({ overflow: TextOverflow.Ellipsis })
    
  2. 展开/收起状态控制
    定义状态变量showAll(布尔类型)管理文本展开状态,点击操作时切换状态:

    [@State](/user/State) showAll: boolean = false
    
  3. 动态按钮与条件渲染
    通过if/else条件渲染展开/收起按钮,仅在文本实际行数超过限制时显示按钮:

    // 计算文本是否超出行数(需结合onAreaChange获取实际行数)
    if (isOverflow) {
        Button(showAll ? '收起' : '展开')
            .onClick(() => { this.showAll = !this.showAll })
    }
    
  4. 文本高亮支持
    若需高亮部分文本,可使用Span组件嵌套实现局部样式:

    Text() {
        Span('普通文本')
        Span('高亮文本').fontColor(Color.Red)
    }
    
  5. 完整示例代码结构

    [@Entry](/user/Entry)
    [@Component](/user/Component)
    struct ExpandableText {
        [@State](/user/State) showAll: boolean = false
        private isOverflow: boolean = false
        private maxLines: number = 2
        private content: string = '长文本内容...'
    
        build() {
            Column() {
                Text(this.content)
                    .maxLines(this.showAll ? undefined : this.maxLines)
                    .textOverflow({ overflow: TextOverflow.Ellipsis })
                    .onAreaChange((_, area) => {
                        // 根据实际渲染区域判断是否超出
                        this.isOverflow = area.height > this.maxLines * 字体行高
                    })
    
                if (this.isOverflow) {
                    Button(this.showAll ? '收起' : '展开')
                        .onClick(() => { this.showAll = !this.showAll })
                }
            }
        }
    }
    

关键注意事项

  • 精确判断文本是否溢出需通过onAreaChange回调计算实际渲染高度
  • 多行文本高度计算需考虑字体大小、行间距等样式因素
  • 若文本内容动态变化,需在变化后重新触发溢出判断

此方案通过状态驱动UI更新,符合ArkUI声明式开发范式,能有效实现需求中的交互效果。

回到顶部