HarmonyOS 鸿蒙Next Text实现自定义省略文本

发布于 1周前 作者 bupafengyu 最后一次编辑是 5天前 来自 鸿蒙OS

image.png 常规的文本省略使用下面这两个属性即可

.textOverflow({ overflow: TextOverflow.Ellipsis }) .ellipsisMode(EllipsisMode.END) 但是无法实现省略符号的定义和颜色修改

一共有两个方案,推荐使用方案二

方案一:

1;Text里面放两个Span ,第一个Span 展示文本内容,第二个Span展示省略内容。

2;监听text内容发生省略之后,截取可以展示的内容,更新到第一个Span上 ,此时把第二个Span 在展示出来是不是就实现了呢?

只有实践才能检验真理,GO GO GO 上代码试一下

EllipsisEndText.ets

@Preview
@Component
export struct EllipsisEndText {
  @State showMore: boolean = false
  @Prop lineCount: number = 0
  @Prop textContext: string
  @Prop moreText: string
  @Prop moreTextColor: ResourceColor
  private controller: TextController = new TextController();
  private options: TextOptions = { controller: this.controller };

  build() {
    Text(undefined, this.options) {
      Span(this.textContext)
      if (this.showMore) {
        Span(this.moreText).fontColor(this.moreTextColor)
      }
    }
    .width('100%')
    .maxLines(this.lineCount)
    .wordBreak(WordBreak.BREAK_ALL)
    .textOverflow({ overflow: TextOverflow.Ellipsis })
    .ellipsisMode(EllipsisMode.END)
    .alignRules({
      top: { anchor: 'flex_row_id', align: VerticalAlign.Bottom },
    })
    .onAreaChange((oldValue: Area, newValue: Area) => {
      let layoutManager = this.options.controller.getLayoutManager()
      console.log('SwiperPage', `LineCount: ${layoutManager.getLineCount()}`)
      let lin = this.lineCount - 1 < 0 ? 0 : this.lineCount - 1
      console.log('SwiperPage', `Line : ${lin}`)
      let lineMetrics: LineMetrics = layoutManager.getLineMetrics(lin)
      if (lineMetrics) {
        console.log('SwiperPage', `LineMetrics: ${JSON.stringify(lineMetrics)}`)
        console.log('SwiperPage', `count_str.length: ${this.textContext.length}`)
        this.showMore = lineMetrics.endIndex < this.textContext.length - 1
        if (this.showMore) {
          this.textContext = this.textContext.slice(0, lineMetrics.endIndex - this.moreText.length + 2)
          console.log('SwiperPage', `this.showMore: ${this.textContext}`)
        }
        console.log('SwiperPage', `this.showMore: ${this.showMore}`)
        // setTimeout(()=>{
        //   this.showMore = true
        // },1000)
      }
    })

  }
}
import { EllipsisEndText } from '../component/EllipsisEndText';

@Entry
@Component
struct CommentTextPage {
  @State message: string = '与BREAK_ALL相同,对于Non-CJK的文本可在任意2个字符间断行,一行文本中有断行破发点(如空白符)时,优先按破发点换行,保障单词优先完整显示。若整一行文本均无断行破发点时,则在任意2个字符间断行。对于CJK与NORMAL效果一致。';

  build() {
    RelativeContainer() {
      EllipsisEndText({
        textContext: this.message,
        lineCount: 3,
        moreText: '···全部',
        moreTextColor: Color.Red
      })
        .id('CommentTextPageHelloWorld')
        .width('100%')
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
    }
    .height('100%')
    .width('100%')
  }
}

通过代码测试发现是可行的

方案二:

使用MeasureText.measureTextSize 实现

思路:测量文本的高度,

1;先测量出展示4的高度 height_4(如:manliness(4),测量4行时的高度)

2;在测量出不指定行数的高度 height_all(全部展示的高度)

3;判断 如果height_all 大于 height_4 ,就减去一个文本内容之后在加上自己自定义的省略文本继续测量。

4;重复3的操作,直到 height_all 不大于 height_4 的时候, 开始替换文本展示,即可实现。

image.pngcke_52912.png

代码如下:

import { EllipsisEndText } from '../component/EllipsisEndText';
import MeasureText from '@ohos.measure';

@Entry
@Component
struct CommentTextPage {
  @State message: string =
    '与BREAK_ALL相同,对于Non-CJK的文本可在任意2个字符间断行,一行文本中有断行破发点(如空白符)时,优先按破发点换行,保障单词优先完整显示。若整一行文本均无断行破发点时,则在任意2个字符间断行。对于CJK与NORMAL效果一致。';

  build() {
    RelativeContainer() {
      Text() {
        Span(this.message)
        Span('···查看全部')
          .fontColor(Color.Red)
      }
      .fontSize(20)
      .maxLines(2)
      .margin(20)
      .onAreaChange((oldValue: Area, newValue: Area) => {
        // 全部展示的时候需要展示的大小
        let allSize: SizeOptions = MeasureText.measureTextSize({
          textContent: this.message, // 被计算文本内容
          constraintWidth: newValue.width, // 被计算文本布局宽度
          fontSize: 20 // 被计算文本字体大小
        })

        // 两行的时候需要展示的大小
        let twoLineSize: SizeOptions = MeasureText.measureTextSize({
          textContent: this.message,
          constraintWidth: newValue.width,
          fontSize: 20,
          maxLines: 2  // 被计算文本最大行数
        })
        let clipText = this.message
        while (Number(allSize.height) > Number(twoLineSize.height)) {
          clipText = clipText.substring(0, clipText.length - 1); // 每次减少一个字符长度,再进行比较计算,直到符合高度要求
          allSize = MeasureText.measureTextSize({
            textContent: clipText + '···查看全部', // 按钮文字也要放入进行计算
            constraintWidth: newValue.width,
            fontSize: 20
          });
        }
        this.message = clipText

      })

    }
    .height('100%')
    .width('100%')
  }
}

大家有没有什么更好的方案呢?坐等学习!

1 回复

在HarmonyOS鸿蒙Next中,实现Text组件的自定义省略文本功能,可以通过结合textOverflow属性和maxLines方法来完成。以下是如何实现的步骤:

  1. 设置maxLines:首先,需要为Text组件设置maxLines属性,以确定文本的最大显示行数。例如,若希望文本只显示一行,则设置maxLines(1)
  2. 配置textOverflow:接着,利用textOverflow属性来控制文本超出显示范围时的处理方式。将其设置为TextOverflow.Ellipsis,意味着超出的文本部分将以省略号显示。
  3. 综合应用:将上述两个属性综合应用于Text组件,即可实现自定义省略文本的效果。

示例代码如下:

Text("这是一段很长的文本,需要被省略显示...")
    .maxLines(1)
    .textOverflow({ overflow: TextOverflow.Ellipsis })
    .width("100%") // 根据需要设置文本宽度

请确保您的HarmonyOS鸿蒙Next开发环境已正确配置,并且相关依赖已更新至最新版本。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部