当前位置: 首页 > news >正文

鸿蒙中富文本编辑与展示

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

                富文本用途可以展示图文混排的内容,在日常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 ReferInfolet 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).valueResourceStrif (valueResourceStr) {let index = FaceList.getRealIds().indexOf(valueResourceStr.toString())let faceStr = FaceList.faceNameStr[index]resultStr += faceStr}} else {let value = (result as RichEditorTextSpanResult).valueresultStr += 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 = strdata?.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组件展示分割的内容,本章节就介绍这些东西。后续章节我将依次从简入深,讲解鸿蒙的开发中遇到各种问题。欢迎大家一起交流。如果你在鸿蒙开发中遇到难点,不会的可以私信我,根据我最近的开发经历,已经基本踩完大部分坑,一起交流使我们共同进步。

    

相关文章:

鸿蒙中富文本编辑与展示

富文本在鸿蒙系统如何展示和编辑的&#xff1f;在文章开头我们提出这个疑问&#xff0c;带着疑问来阅读这篇文章。 富文本用途可以展示图文混排的内容&#xff0c;在日常App 中非常常见&#xff0c;比如微博的发布与展示&#xff0c;朋友圈的发布与展示&#xff0c;都在使用富文…...

Python Q-learning 算法详解与应用案例

目录 Python Q-learning 算法详解与应用案例引言一、Q-learning 的基本原理1.1 强化学习基础1.2 Q值及其更新1.3 Q-learning 的特性 二、Python 中 Q-learning 的面向对象实现2.1 QTable 类的实现2.2 Environment 类的实现2.3 Agent 类的实现 三、案例分析3.1 简单环境中的 Q-l…...

解决:如何在opencv中得到与matlab立体标定一样的矫正图?(python版opencv)

目的&#xff1a;采用一样的标定参数&#xff0c;matlab中和opencv中的立体矫正图像是一样的吗&#xff1f;不一样的话怎么让它们一样&#xff1f; 结论&#xff1a;不一样。后文为解决方案。 原因&#xff1a;注意matlab的标定结果在matlab中的用法和在opencv中的用法不一样&a…...

gin入门教程(4):路由与处理器

路由与处理器 在 Gin 框架中&#xff0c;路由和处理器是核心组成部分&#xff0c;负责将 HTTP 请求映射到相应的处理逻辑。 1. 定义路由 在 cmd/main.go 中&#xff0c;您可以定义不同的路由&#xff0c;例如&#xff1a; r.GET("/ping", func(c *gin.Context) {…...

【python+Redis】hash修改

文章目录 前请详解一、关于Update1. 语法2. 代码示例 二、完整代码 前请详解 Redis库数据 keyvalue1{“id”: 1, “name”: “xxx”, “age”: “18”, “sex”: “\u7537”}2{“id”: 2, “name”: “xxx”, “age”: “18”, “sex”: “\u5973”}3{“id”: 3, “name”: “…...

MAVlink协议 部分通用消息集解析

文章目录 MAVLink是一种非常轻量级的消息传输协议, 用于地面控制终端&#xff08;地面站&#xff09;与无人机之间 (以及机载无人机组件之间) 进行通信&#xff0c; 为一种设计用于资源受限系统及带宽受限链路的二进制遥测协议。 HEARTBEAT 检测信号消息显示系统或组件存在并正…...

c++实现跳表

原理 跳表&#xff08;Skip List&#xff09; 是一种随机化数据结构&#xff0c;用于高效查找、插入和删除&#xff0c;尤其适用于有序数据集合。相比链表&#xff0c;跳表通过多层索引结构加速查找&#xff0c;期望时间复杂度接近 O(log⁡n)。跳表的主要思想是&#xff1a; …...

新探索研究生英语读写教程pdf答案(基础级)

《新探索研究生英语读写教程》的设计和编写充分考虑国内研究生人才培养目标和研究生公共英语的教学需求&#xff0c; 教学内容符合研究生认知水平&#xff0c; 学术特征突出&#xff1b;教学设计紧密围绕学术阅读、学术写作和学术研究能力培养&#xff1b;教学资源立体多元&…...

管道与共享内存

一&#xff0c;命名管道 管道的限制就是他只能在有血缘关系&#xff08;父子进程&#xff09;的进程中&#xff0c;允许互相访问&#xff0c;这是有局限性的&#xff0c;所以我们想在毫无关系的进程中允许他们相互访问&#xff0c;这就是命名管道的定义。 总结&#xff1a;命名…...

ES 自定义排序方式

es默认score是根据query的相关度进行打分的&#xff0c;具体打分机制可以参见&#xff1a;官方文档。如果召回时既希望有相关性又能根据其他信息进行排序。 例如小红书搜索的时候&#xff0c;可能既希望有召回相关度又能根据热度信息&#xff08;如果喜欢、收藏等等参数去进行召…...

在vue中,编写一个li标签同时使用v-for和v-if,谁的优先级更高

在 Vue 中&#xff0c;v-if 和 v-for 是两个常用的指令&#xff0c;但它们的优先级不同。当二者一起使用时&#xff0c;v-for 的优先级高于 v-if。这意味着&#xff0c;v-for 会先执行&#xff0c;即使列表中的某些元素不满足 v-if 条件&#xff0c;它们仍会被遍历和渲染。 由…...

Java 后端开发面试题及其答案

以下是一些常见的 Java 后端开发面试题及其答案&#xff0c;涵盖了 Java 基础、面向对象、并发、多线程、框架等多个方面&#xff1a; 1. Java 中的基本数据类型有哪些&#xff1f; 答案&#xff1a; Java 中的基本数据类型有 8 种&#xff1a; int&#xff1a;32 位整数lon…...

C++,STL 045(24.10.24)

内容 1.对set容器的大小进行操作。 2.set容器的交换操作。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it <…...

二叉树习题其五【力扣】【算法学习day.12】

前言 书接上篇文章二叉树习题其四&#xff0c;这篇文章我们将基础拓展 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一…...

【数据库】Mysql的锁类型

Mysql中的锁机制主要是为了保证数据的一致性和完整性&#xff0c;在并发的情况下起着至关重要的作用。其中锁的类型主要是分为以下几种&#xff1a; 按照粒度分类 全局锁&#xff1a;对于整个数据库实例进行枷锁&#xff0c;加锁后整个实例就处于只读的状态。局锁通常用于需要…...

自媒体短视频制作素材下载网站推荐,让创作更简单

随着自媒体行业的火爆&#xff0c;视频质量要求也越来越高。想要找到无版权的高清视频素材并不容易&#xff0c;但别担心&#xff01;今天为大家整理了5个国内外高质量的素材网站&#xff0c;让你轻松获取自媒体短视频素材&#xff0c;快收藏起来吧&#xff01; 蛙学网 蛙学网是…...

Altium Designer 入门基础教程(五)

本文章继续接着《Altium Designer 入门基础教程&#xff08;四&#xff09;》的内容往下介绍&#xff1a; 七、AD画板的整个流程步骤 I.集成库的制作 AD元件库有2种&#xff1a;1、原理图元件库SCH.LIB 2、印刷电路板&#xff08;PCB&#xff09;元件库 PCB.LIB 印刷电路…...

Java题集练习3

Java题集练习3 1 什么时候用instanceof instanceOf关键字主要用于判断一个对象是否为某个类的子类或是接口的实例&#xff0c;通常用于类型转换和运行时类型判断的场景&#xff0c;比如继承和多态中。比如&#xff0c;创建一个Animal类及其子类Cat和Cat子类Hat&#xff0c;可…...

【部署篇】Haproxy-01安装部署(源码方式安装)

‌一、HAProxy概述‌ HAProxy是一款免费、快速且可靠的代理软件&#xff0c;提供高可用性、负载均衡&#xff0c;支持TCP和HTTP应用代理&#xff0c;HAProxy凭借其卓越的性能和灵活性&#xff0c;成为众多知名网站和系统的首选代理软件。‌ ‌核心特点‌&#xff1a; ‌高性能…...

开拓鸿蒙测试新境界,龙测科技引领自动化测试未来

在当今科技舞台上&#xff0c;鸿蒙 OS 以非凡先进性强势登场&#xff0c;打破传统操作系统格局&#xff0c;为软件测试领域带来全新机遇与艰巨挑战。 一、鸿蒙 OS 的辉煌崛起 &#xff08;一&#xff09;壮丽发展历程与卓越市场地位 鸿蒙 OS 的发展如波澜壮阔的史诗。2023 年…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...