一、前言
在很多业务场景里,我们都需要富文本编辑能力:公告编辑、工单备注、内容发帖、文档草稿等。ArkUI 提供的 RichEditor 组件,是官方原生富文本控件,不用额外引入第三方 Web 富文本,能直接在页面内完成文字编辑、插入图片、添加链接、修改文字样式。
不少同学初次上手 RichEditor,容易踩坑:图片插入后布局错乱、超链接点击不生效、样式修改只选中部分文字不生效、数据回显丢失格式。这些问题大多是对组件数据模型、编辑范围接口不熟悉导致。本文基于最新鸿蒙 API,讲解 RichEditor 核心用法,附带可直接运行完整代码。
二、RichEditor 基础概念
RichEditor 的内容由RichEditorSpan构成,一段富文本可以包含文本、图片、链接等不同类型的 Span。
- TextSpan:普通文本片段,控制字体、颜色、字号、粗斜体
- ImageSpan:图片片段,承载图文混排能力
- UrlSpan:超链接片段,可绑定跳转地址
所有的样式操作,都要先获取当前光标选中范围TextRange,再针对选中区域追加或者修改 Span 属性。RichEditor 本身是可编辑组件,用户可以直接在界面上输入、选中文字。
三、基础页面搭建
先搭建基础页面,放置 RichEditor 与一组操作按钮,用来切换样式、插入图片、添加链接。
bash
@Entry
@Component
struct RichEditorDemo {
@State richController: RichEditorController = new RichEditorController()
@State content: RichEditorSpan[] = [
new RichEditorTextSpan("欢迎使用RichEditor富文本编辑器\n", {fontSize: 18, fontColor: "#222222", fontWeight: FontWeight.Bold}),
new RichEditorTextSpan("原生组件实现图文混排、超链接与自定义样式\n", {fontSize: 14, fontColor: "#666666"})
]
build() {
Column() {
// 操作工具栏
Row() {
Button("加粗").onClick(() => this.setBold())
Button("变色").onClick(() => this.setTextColor())
Button("插入图片").onClick(() => this.insertImage())
Button("添加链接").onClick(() => this.insertUrl())
}
.width("100%")
.margin({bottom: 12})
.justifyContent(FlexAlign.SpaceAround)
RichEditor(this.content, this.richController)
.width("100%")
.height(400)
.border({width:1, color:"#eeeeee"})
.placeholder("请输入富文本内容...")
}
.padding(16)
.width("100%")
}
1. 文字加粗实现
获取当前选中区域,新建文本 Span 覆盖选中范围,设置 fontWeight。
bash
setBold() {
const range: TextRange = this.richController.getCaretOffset()
if (range.start === range.end) return
const selectSpans = this.richController.getSpansByRange(range)
selectSpans.forEach(span => {
if (span instanceof RichEditorTextSpan) {
span.fontWeight = FontWeight.Bold
}
})
}
- 修改文字颜色
bash
setTextColor() {
const range: TextRange = this.richController.getCaretOffset()
if (range.start === range.end) return
const spans = this.richController.getSpansByRange(range)
spans.forEach(span => {
if (span instanceof RichEditorTextSpan) {
span.fontColor = "#0066FF"
}
})
}
3. 插入图片,图文混排
示例使用资源目录图片,替换成沙箱文件路径即可实现拍照 / 相册图片插入。
bash
insertImage() {
const caretPos = this.richController.getCaretOffset().start
const imgSpan = new RichEditorImageSpan($r("sys.media.ohos_ic_public_photo"), {
imageWidth: 200,
imageHeight: 140
})
this.richController.insertSpan(caretPos, imgSpan)
}
- 插入超链接
bash
insertUrl() {
const range: TextRange = this.richController.getCaretOffset()
if (range.start === range.end) return
const urlSpan = new RichEditorUrlSpan("点击访问官网", "https://www.harmonyos.com", {
fontColor: "#0066FF",
textDecoration: TextDecoration.Underline
})
this.richController.replaceSpan(range, urlSpan)
}
}
四、富文本序列化与回显
实际业务中,需要把富文本内容保存、页面刷新后重新渲染。RichEditorSpan 数组可以直接转为 JSON 存储,读取后还原 Span 数组。
bash
// 导出富文本内容,保存到持久化存储
saveRichContent() {
const dataStr = JSON.stringify(this.content)
// 这里可以写入Preferences/RDB
console.info("富文本数据", dataStr)
}
// 读取JSON,回显富文本
restoreRichContent(jsonStr: string) {
const rawData = JSON.parse(jsonStr)
this.content = rawData.map((item: Record<string,any>) => {
if(item.type === "text"){
return new RichEditorTextSpan(item.text, item.style)
}else if(item.type === "image"){
return new RichEditorImageSpan(item.imageValue, item.style)
}else if(item.type === "url"){
return new RichEditorUrlSpan(item.text, item.url, item.style)
}
})
}
五、小结
RichEditor 原生富文本组件,省去 WebView 方案带来的包体积、通信调试成本。核心思路就是通过RichEditorController获取光标选区,增改 TextSpan、ImageSpan、UrlSpan 实现图文、链接、自定义样式。 基础的编辑、内容导出、回显逻辑可以直接复用上面代码,在此基础