当前位置: 首页 > 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 年…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

TJCTF 2025

还以为是天津的。这个比较容易&#xff0c;虽然绕了点弯&#xff0c;可还是把CP AK了&#xff0c;不过我会的别人也会&#xff0c;还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...

CppCon 2015 学习:REFLECTION TECHNIQUES IN C++

关于 Reflection&#xff08;反射&#xff09; 这个概念&#xff0c;总结一下&#xff1a; Reflection&#xff08;反射&#xff09;是什么&#xff1f; 反射是对类型的自我检查能力&#xff08;Introspection&#xff09; 可以查看类的成员变量、成员函数等信息。反射允许枚…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...