鸿蒙中富文本编辑与展示

富文本在鸿蒙系统如何展示和编辑的?在文章开头我们提出这个疑问,带着疑问来阅读这篇文章。

富文本用途可以展示图文混排的内容,在日常App 中非常常见,比如微博的发布与展示,朋友圈的发布与展示,都在使用富文本的编辑与展示。通常我们需要标注不同颜色文本,比如话题,#富文本编辑与展示#,@鸿蒙开发者等,这些都要在编辑时或者发布后展示时标注不同的字体颜色。

一、功能富文本编辑

我们如何实现上边这个富文本编辑器呢,在鸿蒙中通过RichEditor实现,由于官网对RichEditor示例太多,很多开发者找不到自己想要的结果,或者对应的使用实例,下面几个部分,基本满足大部分开发者需求的编写。首先上边有四个主要部分,

1、@某人 的实现;主要包括@某人的添加和删除,通过添加@某人,可以看到添加的时候对颜色进行标红,并设置字体大小。

复制代码
addAltInfo = (referInfo: ReferInfo) => {
  this.referInfos.push(referInfo)
  let tempText = `@${referInfo.mUserName} `
  this.richEditorController.addTextSpan(
    tempText,
    {
      style: {
        fontColor: $r("app.color.v5_theme_color"),
        fontSize: 15
      }
    }
  )
}

添加完删除时候我们需要判断是否以@开头,如果已@开头就把Span相关的全部删掉。否则就按照系统本身删除 即可。

复制代码
if (needValue.startsWith("@")) {
  // @时候删除全部
  for (let index = 0; index < this.referInfos.length; index++) {
    let referInfo = this.referInfos[index] as ReferInfo
    let altNickname = `@${referInfo.mUserName} `
    if (altNickname == needValue) {
      this.referInfos.splice(index, 1)
      this.richEditorController.deleteSpans({ start, end })
      deleteFlag = false
    }
  }
}

2、#话题内容# 的实现与@某人相似,通过#选的话题#,这样来设置添加文本的颜色,字体大小等

复制代码
addTopic = (topic: string) => {
  this.richEditorController.addTextSpan(
    topic,
    {
      style: {
        fontColor: $r("app.color.v5_theme_color"),
        fontSize: 15
      }
    }
  )
}

如果在删除时候,我们判断一下span内人字符串是已#开始,我们认为他是输入的话题,这时候我们需要把他的字体颜色改变为普通文本的颜色,这样就可以变成普通文本了。目前我是以#开始计算的,你也可以加上以#开始,并且#结束的时候才改变其颜色。我认为以#开始已经足够了。

复制代码
 if (needValue.startsWith("#")) {
  this.richEditorController.updateSpanStyle(
    {
      start: start,
      end: end,
      textStyle: {
        fontColor: $r("app.color.title"),
        fontSize: 15
      }
    }
  )
}

3、自定义表情实现,就是我们App 内自己定义一些相关的表情符号,选择对应的表情,以图片的形式存放在发布微博中。这里FaceID就是我们图片资源。可以设置图片的大小,根据自己需求设置大小。表情的删除因为是ImageSpan所以表情就一块删掉了,不用担心删除一半问题。直接按照系统方法走删除的逻辑就可以了。

复制代码
addFace = (faceId: Resource) => {
  this.richEditorController.addImageSpan(
    faceId,
    {
      imageStyle: {
        size: [16, 16]
      }
    }
  )
  this.addDefaultStyle()
}

4、基本文本文字输入我们有二种方案,第一种就是每次输入完之后加一个空格,来改变后边字体的颜色的字体大小,这样就不会每次跟着前边的字体大小和颜色了。还有一种就是在每次输入完更新输入的字体颜色,把自己输入改为默认颜色即可。二种目前都不是最优解,但是可以解决临时现在的问题,如果大家有好的办法我们一起交流。目前华为官网也没有很好的例子来实现。

复制代码
addDefaultStyle(text?: string) {
  let tempText = " "
  if (text) {
    tempText = text
  }
  this.richEditorController.addTextSpan(
    tempText,
    {
      style: {
        fontColor: $r("app.color.title"),
        fontSize: 15
      }
    }
  )
}

这种是在每次文本输入的时候改变文本的颜色。

复制代码
.onDidIMEInput((textRange: TextRange) => {
  this.richEditorController.updateSpanStyle({
    start: textRange.start,
    end: textRange.end,
    textStyle: {
      fontColor: $r("app.color.title"),
      fontSize: 15
    }
  })
})

5、实时获取文本输入的长度字数,以控制最大输入长度。实现方法就是通过getSpans()或者所有的文本,如果是ImageSpan替换成对应的字符串计算字符。其他的按照文本方式计算。直接累加字符串得到最后的文本。得到文本直接获取他的长度即可。

复制代码
getInputResult = (): string => {
  let resultStr: string = ""
  let resultList = this.richEditorController.getSpans()
  for (let result of resultList) {
    if (typeof (result as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
      let valueResourceStr = (result as RichEditorImageSpanResult).valueResourceStr
      if (valueResourceStr) {
        let index = FaceList.getRealIds().indexOf(valueResourceStr.toString())
        let faceStr = FaceList.faceNameStr[index]
        resultStr += faceStr
      }
    } else {
      let value = (result as RichEditorTextSpanResult).value
      resultStr += value
    }
  }
  return resultStr
}

6、对于输入框编辑器对文本的限制,我们可以通过将要输入内容是否还接收数据来实现,如果已经达到我们要求的最大长度我们可以将onWillChange设置成false来表示不在接收数据即可。

复制代码
.onWillChange((_changeValue) => {
  if (this.getInputResult().length >= this.maxLength) {
    return false
  }
  return true
})

通过监听onDidChange输入之后数据改变实现输入后数据的变化和输入长度展示。

复制代码
.onDidChange((_callback) => {
  this.inputDataChange(this.getInputResult())
})

通过上边几个部分的讲解,我们基本完成的富文本编辑在鸿蒙上边的实现,可以通过上边步骤实现类似微博的发布功能,主要包括文本输入,#话题选择#,@某人,文本删除的功能,基本满足的富文本编辑的需求,如果有不满足的你的需求,可以私信我,我们一起探讨,欢迎你的提起,我们一起进步,共同成长。

二、富文本的展示

富文本的展示指的什么,我们需要展示哪些内容;首先举个例子,文本中链接、#话题#、@鸿蒙开发者、表情图标等这些内容需要再展示时候标注特殊的颜色,点击时候我们需要跳转到对应的界面,在鸿蒙中我们怎么在一串文字文本中,对不同文字设置不同的颜色,并且在点击时候跳转对应的界面呢,展示文字中的图片呢,带着这些问题我们来看下边的内容。

首先鸿蒙提供了文本展示器Text,我们可以通过Text展示,但是如果想特殊标记颜色,我们就需要对文本进行分割了,分割出每段要展示的内容。这里我们以#话题#,链接为例进行分割。这里以通过正则表达式分割之后,以#结束的,我们认为是话题类型,否则认为是长链接。这里的分割内容是把#话题#,长链接分割分割出来。分割出来之后,我们通过字符串把整个文本进行分割成不同内容。最后分割成三种类型,普通文本、话题、长链接类型,然后根据类型,展示对应的问题,如果需要跳转点击文本时候进行跳转。@某人、表情符号分割和这个类似方式,这里不再重复表述。如有疑问请私信提出。

复制代码
export function splitContent(str: string): LinkTextModel[] {
  let data =
    str.match(/(#([^#]+)#)|(https?|rtsp):\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z0-9]{2,}(:[0-9]{1,5})?(\/[\S]*)?|(?<!\S)[a-zA-Z0-9\-]+(\.[a-zA-Z0-9]{2,})+(?!\S|\@)/gi);
  let result: LinkTextModel[] = [];
  let start = 0;
  let tempStr = str
  data?.forEach((value) => {
    let tempIndex = tempStr.indexOf(value)
    result.push({ type: LinkTextEnum.COMMON, content: tempStr.slice(start, tempIndex) })
    if (value.startsWith("#")) {
      result.push({ type: LinkTextEnum.TOPIC, content: value })
    } else {
      result.push({ type: LinkTextEnum.URl, content: value })
    }
    tempStr = tempStr.substring(tempIndex + value.length)
  });
  result.push({ type: LinkTextEnum.COMMON, content: tempStr })
  return result;
}

分割好的文本是一段一段的,我们需要把这些一段一段的展示出来。如下图所示,根据分割的类型展示不同颜色的问题。这里我们在Text里面用,Span展示文本,设置字体颜色。通过ImageSpan展示图标来展示表情。

复制代码
  Text() {
    ForEach(this.allTextList, (item: LinkTextModel) => {
      if (item.type === LinkTextEnum.TOPIC) {
        ForEach(splitFace(item.content), (item: LinkChildModel) => {
          if (item.type === LinkTextEnum.Face && item.faceId) {
            ImageSpan(item.faceId)
              .width(16)
              .height(16)
          } else {
            Span(item.content)
              .fontColor("#A34444")
              .onClick(() => {
                // 跳转话题详情
              })
          }
        })
​
      } else if (item.type === LinkTextEnum.URl) {
        Span(item.content)
          .fontColor("#A34444")
          .onClick(() => {
             // 跳转Web加载页面,加载web地址
          })
      } else if (item.type == LinkTextEnum.ALT) {
        Span(item.content)
          .fontColor("#A34444")
          .onClick(() => {
             // alt 分割跳转个人详情
          })
      } else {
        ForEach(splitFace(item.content), (item: LinkChildModel) => {
          if (item.type === LinkTextEnum.Face && item.faceId) {
            ImageSpan(item.faceId)
              .width(16)
              .height(16)
          } else {
            Span(item.content)
          }
        })
      }
    })
  }
  .fontSize(14)
  .fontColor("#333333")
  .width(CommonConstants.MATCH_PARENT)
  .margin({ top: 5 })
  .padding({ left: 12, right: 12 })
}

阅读本文章,我们已经了解了富文本编辑器的实现,可以按照步骤一步一步实现自己的富文本编辑器,也学会富文本的展示,通过正则表达式分割自己需要的内容,然后通过Text中的span、imagespan组件展示分割的内容,本章节就介绍这些东西。后续章节我将依次从简入深,讲解鸿蒙的开发中遇到各种问题。欢迎大家一起交流。如果你在鸿蒙开发中遇到难点,不会的可以私信我,根据我最近的开发经历,已经基本踩完大部分坑,一起交流使我们共同进步。

相关推荐
岳不谢12 小时前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
爱笑的眼睛1113 小时前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
K.P14 小时前
鸿蒙元服务从0到上架【第三篇】(第二招有捷径)
华为·harmonyos·鸿蒙系统
K.P15 小时前
鸿蒙元服务从0到上架【第二篇】
华为·harmonyos·鸿蒙系统
敲代码的小强18 小时前
Flutter项目兼容鸿蒙Next系统
flutter·华为·harmonyos
程序猿会指北18 小时前
纯血鸿蒙APP实战开发——Text实现部分文本高亮和超链接样式
移动开发·harmonyos·arkts·openharmony·arkui·组件化·鸿蒙开发
鸿蒙自习室1 天前
鸿蒙开发——关系型数据库的基本使用与跨设备同步
前端·数据库·华为·harmonyos·鸿蒙
SoraLuna1 天前
「Mac畅玩鸿蒙与硬件45」UI互动应用篇22 - 评分统计工具
开发语言·macos·ui·华为·harmonyos
资讯分享周1 天前
鸿蒙风起,未来已来——云学堂鸿蒙应用认证开营啦!
华为·harmonyos
Lincode121 天前
HarmonyOS--鸿蒙三方库--lottie
华为·harmonyos