HarmonyOS 表情符号用measure.measureText计算得到的宽度不对,怎么处理宽度问题

HarmonyOS
2025-01-09 15:45:05
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
zbw_apple

示例参考如下:

import measure from '@ohos.measure'

@Entry
@Component
struct TextPage2 {
  build() {
    Column() {
      ExpandableText({
        fontFamily: "FZBYS",
        fontColor: "#222222",
        fontSize: 16,
        maxLines: 5,
        tipFontColor: "#999999",
        needClose: true
      })
    }
  }
}

@Component
export struct ExpandableText {
  unicodeText: string =
    "跨设备的分布式操作,打破设备界限,多设备联动,为你革新全场景协同体验。典型场景有:媒体播控、应用接续、跨设备拖拽、跨设备剪贴板。"
  shortText: string = "OpenHarmony"
  // 无论是"\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}"还是"\ud83d\ude0a"都有问题
  // unicodeText:string = "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}"
  // unicodeText:string = "\ud83d\ude0a"
  textSpecial: string = "\ud83d\ude0a"
  // 文案
  private text: string = this.unicodeText
  // 文案字体大小
  private fontSize: number | string | Resource = 16
  // 文案色值
  private fontColor: ResourceColor = ''
  // 文案字体列表
  private fontFamily: string | Resource = ''
  // 展开或收起色值
  private tipFontColor: ResourceColor = ''
  // 展开或收起字体大小
  private tipFontSize: number | string | Resource = this.fontSize
  // 最大行数
  private maxLines: number = 3
  // 是否需要收起功能,默认不需要
  @Prop private needClose: boolean = false
  // 展开或收起状态
  @Prop private isExpand: boolean = false
  // 展开或收起点击回调
  private callback?: Callback<boolean>
  private readonly PREFIX = '···'
  private readonly EXPAND = '展开全部'
  private readonly CLOSE = '   收起'
  @State private componentWidth: number = 0
  @State private _text: string = ''

  private clipString(text: string): string {
    if (this.maxLines < 1 || !text || !this.componentWidth) {
      this._text = text
      return text
    }
    const componentWidth = vp2px(this.componentWidth)
    let clipStr: string = ""
    let singleLineTextWidth = componentWidth
    const clipStrWidth = measure.measureText({
      textContent: text,
      fontSize: this.fontSize,
      constraintWidth: componentWidth,
      wordBreak: WordBreak.BREAK_ALL,
      // maxLines:this.maxLines
    })
    if (clipStrWidth > singleLineTextWidth * this.maxLines) {
      const measureTruncateWidth: number = measure.measureText({
        textContent: this.PREFIX + this.EXPAND,
        fontSize: this.tipFontSize,
        constraintWidth: componentWidth,
      })
      for (let i = 0; i < text.length; i++) {
        clipStr += text[i]
        const clipStrWidth2 = measure.measureText({
          textContent: clipStr,
          fontSize: this.fontSize,
          constraintWidth: componentWidth,
          wordBreak: WordBreak.BREAK_ALL
        })
        if (clipStrWidth2 > (singleLineTextWidth * this.maxLines - 1.5 * measureTruncateWidth)) {
          clipStr = clipStr.substring(0, clipStr.length - 1)
          break
        }
      }
      this._text = clipStr
    } else {
      this._text = text
    }
    return this._text
  }

  build() {
    Column() {
      Text() {
        Span(this.isExpand ? this.text : this.clipString(this.text))
        if (!this.isExpand && this._text.length !== this.text.length) {
          Span(this.PREFIX)
        }
        Span(this.isExpand ? '' : (this._text.length === this.text.length ? '' : this.EXPAND))
          .onClick(() => {
            this.isExpand = !this.isExpand
            if (this.callback) {
              this.callback(this.isExpand)
            }
          }).fontColor(this.tipFontColor)
          .fontSize(this.tipFontSize)
          .fontWeight(FontWeight.Medium)
      }
      .width('100%')
      .backgroundColor(Color.Red)
      .onAreaChange((oldValue: Area, newValue: Area) => {
        this.componentWidth = newValue.width as number
      })
      .fontSize(this.fontSize)
      .fontColor(this.fontColor)
      .fontFamily(this.fontFamily)

      Row() {
        Text(this.CLOSE)
          .onClick(() => {
            this.isExpand = !this.isExpand
            if (this.callback) {
              this.callback(this.isExpand)
            }
          }).fontColor(this.tipFontColor)
          .fontSize(this.tipFontSize)
          .fontWeight(FontWeight.Medium)
      }.width('100%')
      .justifyContent(FlexAlign.End)
      .visibility(this.isExpand && this.needClose ? Visibility.Visible : Visibility.None)
    }.width('100%')
    .padding({ top: 100, left: 50, right: 23 })
  }
}
分享
微博
QQ
微信
回复
2025-01-09 19:19:47
相关问题
怎么设置元素最大宽度最小宽度
562浏览 • 1回复 待解决
有谁知道如何计算文本宽度
2440浏览 • 1回复 待解决
HarmonyOS Popup宽度问题
229浏览 • 1回复 待解决
HarmonyOS 屏幕宽度怎么获取
682浏览 • 1回复 待解决
HarmonyOS Flex组件宽度问题
706浏览 • 1回复 待解决
HarmonyOS Tabs组件宽度问题
232浏览 • 1回复 待解决
HarmonyOS Tabs组件tabBar宽度问题
968浏览 • 1回复 待解决
HarmonyOS 折叠屏webview宽度问题
752浏览 • 1回复 待解决
HarmonyOS Row 怎么设置中间最大宽度
225浏览 • 1回复 待解决
HarmonyOS 子控件设置宽度100%问题
458浏览 • 1回复 待解决