#跟着坚果学鸿蒙#针对资源字符串使用Text和Span组件进行高亮或添加下划线处理

2025-05-12 14:04:29
132次阅读
0个评论

针对资源字符串使用Text和Span组件进行高亮或添加下划线处理

自定义处理方法

  • 新建StringUtils工具类
  // 获取资源字符串
  static fetchResStr(res: Resource): string {
    let str = getContext().resourceManager.getStringSync(res.id)
    return str
  }

  // 获取资源字符串 1个参数
  static fetchResStrWithParams1(res: Resource, params: string): string {
    let str = getContext().resourceManager.getStringSync(res.id, params)
    return str
  }

  // 获取资源字符串 2个参数
  static fetchResStrWithParams2(res: Resource, params1: string, params2: string): string {
    let str = getContext().resourceManager.getStringSync(res.id, params1, params2)
    return str
  }

  // 获取下划线和高亮字符串
  static fetchFormattedTextArray(
    wholeStr: string,
    highlightStrs: string[], // 需要高亮的文本
    highlightColor: ResourceColor,
    underlineStrs: string[] // 需要下划线的文本
  ): Array<TextViewModel> {

    let tempArray: Array<TextViewModel> = [];

    if (highlightStrs.length === 0 && underlineStrs.length === 0) {
      tempArray.push(new TextViewModel(wholeStr));
      return tempArray;
    }

    // 组合高亮和下划线关键词,构造正则表达式
    let regexPattern = [...highlightStrs, ...underlineStrs]
      .map(str => str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'))// 转义正则特殊字符
      .join('|');
    let regex = new RegExp(`(${regexPattern})`, 'g');

    // 使用正则拆分文本
    let parts = wholeStr.split(regex);

    parts.forEach((part) => {
      if (!part) {
        return;
      } // 跳过空字符串

      let viewModel = new TextViewModel(part);

      // 判断是否是高亮文本
      if (highlightStrs.includes(part)) {
        viewModel.isCanClick = true;
        viewModel.isHighLight = true;
        viewModel.fontColor = highlightColor;
      }

      // 判断是否是下划线文本
      if (underlineStrs.includes(part)) {
        viewModel.isDecorationStyle = true;
      }

      tempArray.push(viewModel);
    });

    return tempArray;
  }
}

export class TextViewModel {
  eventsBlock?: () => void
  // 字符串
  str: string
  // 字体大小
  fontSize?: number
  // 字体颜色
  fontColor?: ResourceColor
  // 字体类型
  fontWeight?: FontWeight
  // 是否可以点击
  isCanClick: boolean = false
  // 是否展示图片
  isShowImage: boolean = false
  // 是否需要下划线
  isDecorationStyle: boolean = false
  // 是否高亮
  isHighLight: boolean = false

  constructor(str: string) {
    this.str = str
  }
}

方法的使用

  • 示例: 现在对登鹳雀楼这首诗进行特殊处理,要求:
  1. 依山、欲穷、更、层高亮显示
  2. 入海流、千里、上一、楼添加下划线显示
  • 资源字符串

image.png

  • 字符串的处理
  @State str2: Array<TextViewModel> = []
  @State str3: Array<TextViewModel> = []
  @State str4: Array<TextViewModel> = []
  @State str : Array<TextViewModel[]> = []

  aboutToAppear(): void {
    let str1 = StringUtils.fetchResStr($r('app.string.poem1'))
    let str1_highLight = StringUtils.fetchResStr($r('app.string.poem1_highLight'))
    this.str1 = StringUtils.fetchFormattedTextArray(str1, [str1_highLight], [], Color.Orange)

    let str2 = StringUtils.fetchResStr($r('app.string.poem2'))
    let str2_underLine = StringUtils.fetchResStr($r('app.string.poem2_underLine'))
    this.str2 = StringUtils.fetchFormattedTextArray(str2, [], [str2_underLine], Color.Blue)

    let str3 = StringUtils.fetchResStr($r('app.string.poem3'))
    let str3_highLight = StringUtils.fetchResStr($r('app.string.poem3_HighLight'))
    let str3_underLine = StringUtils.fetchResStr($r('app.string.poem3_underLine'))
    this.str3 = StringUtils.fetchFormattedTextArray(str3, [str3_highLight], [str3_underLine], Color.Brown)

    let str4 = StringUtils.fetchResStr($r('app.string.poem4'))
    let str4_highLight1 = StringUtils.fetchResStr($r('app.string.poem4_HighLight1'))
    let str4_highLight2 = StringUtils.fetchResStr($r('app.string.poem4_HighLight2'))
    let str4_underLine1 = StringUtils.fetchResStr($r('app.string.poem4_underLine1'))
    let str4_underLine2 = StringUtils.fetchResStr($r('app.string.poem4_underLine2'))
    let str4_highLight_Array = [str4_highLight1, str4_highLight2]
    let str4_underLine_Array = [str4_underLine1, str4_underLine2]
    this.str4 = StringUtils.fetchFormattedTextArray(str4, str4_highLight_Array, str4_underLine_Array, Color.Red)

    this.str = [this.str1,this.str2,this.str3,this.str4]
  }
  • UI渲染(简单处理)
    Column() {
      Text($r('app.string.poem_title'))
        .id('title')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)


      Column() {
        ForEach(this.str,(strs:TextViewModel[])=>{
          Text() {
            ForEach(strs, (value: TextViewModel) => {
              Span(value.str)
                .fontWeight(FontWeight.Bold)
                .fontColor(value.fontColor ? value.fontColor : '#FF333333')
                .lineHeight(24)
                .decoration(value.isDecorationStyle ?
                  { type: TextDecorationType.Underline, color: '#ffff0739', style: TextDecorationStyle.SOLID } :
                  { type: TextDecorationType.None })
            })
          }
        })
      }
      .layoutWeight(1)
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .padding(16)
  }
  • 效果图

image.png

  • 总结
  1. 将资源字符串转为string类型,使用自定义方法获取需要的高亮/需要添加下划线的字符串数组
  2. 在UI层结合Text组件和Span组件进行渲染
  • 改进
  1. 可以在TextViewModel中添加新的属性,方便后期调用,比如下划线的颜色、下划线样式
  2. ForEach循环渲染出来的Text组件样式可以封装成一个通用样式,方便其他文件调用
  3. 可以根据实际业务需求自定义fetchFormattedTextArray的处理方法
收藏00

登录 后评论。没有帐号? 注册 一个。