• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 富文本(RichEditor)
2RichEditor是支持图文混排和文本交互式编辑的组件,通常用于响应用户的对于图文混合内容的输入操作,例如可以输入图片的评论区。具体用法参考[RichEditor](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md)。
3
4## 创建RichEditor组件
5RichEditor通过调用接口来创建,可以创建以下两种类型:
6
7### 创建不使用属性字符串构建的RichEditor组件
8```ts
9RichEditor(value: RichEditorOptions)
10```
11其中RichEditorOptions是富文本组件初始化选项。
12
13```ts
14controller: RichEditorController = new RichEditorController();
15options: RichEditorOptions = { controller: this.controller };
16
17RichEditor(this.options)
18    .onReady(() => {
19        this.controller.addTextSpan('创建不使用属性字符串构建的RichEditor组件。', {
20            style: {
21                fontColor: Color.Black,
22                fontSize: 15
23            }
24        })
25    })
26```
27![alt text](figures/richeditor_image_options.gif)
28
29### 创建使用属性字符串构建的RichEditor组件
30```ts
31RichEditor(options: RichEditorStyledStringOptions)
32```
33
34其中RichEditorStyledStringOptions是富文本组件初始化选项。属性字符串的使用方法请参考[属性字符串(StyledString/MutableStyledString)](arkts-styled-string.md)。
35
36```ts
37mutableStyledString: MutableStyledString = new MutableStyledString("创建使用属性字符串构建的RichEditor组件。",
38    [{
39        start: 0,
40        length: 5,
41        styledKey: StyledStringKey.FONT,
42        styledValue: this.fontStyle
43    }]);
44
45controller: RichEditorStyledStringController = new RichEditorStyledStringController();
46options: RichEditorStyledStringOptions = {controller: this.controller};
47
48RichEditor(this.options)
49    .onReady(() => {
50        this.controller.setStyledString(this.mutableStyledString);
51    })
52```
53![alt text](figures/richeditor_image_stylestringoptions.gif)
54
55## 设置属性
56
57### 设置自定义选择菜单
58
59通过[bindSelectionMenu](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#bindselectionmenu)设置自定义选择菜单。
60
61其中spanType是菜单的类型,默认值为文字类型;content是菜单的内容;responseType是菜单的响应类型,默认类型为长按;options是菜单的选项,可设置自定义选择菜单弹出或关闭时的回调。
62
63自定义菜单超长时,建议内部嵌套Scroll组件使用,避免键盘被遮挡。
64
65```ts
66RichEditor(this.options)
67    .onReady(() => {
68        this.controller.addTextSpan('组件设置了自定义菜单,长按可触发。', {
69            style: {
70                fontColor: Color.Black,
71                fontSize: 18
72            }
73        })
74    })
75    .bindSelectionMenu(RichEditorSpanType.TEXT, this.SystemMenu, ResponseType.LongPress, {
76        onDisappear: () => {
77            this.sliderShow = false
78        }
79    })
80    .width(300)
81    .height(300)
82
83@Builder
84SystemMenu() {
85    Column() {
86            Menu() {
87                    if (this.controller) {
88                        MenuItemGroup() {
89                            MenuItem({
90                                startIcon: this.theme.cutIcon,
91                                content: "剪切",
92                                labelInfo: "Ctrl+X",
93                            })
94                            MenuItem({
95                                startIcon: this.theme.copyIcon,
96                                content: "复制",
97                                labelInfo: "Ctrl+C"
98                            })
99                            MenuItem({
100                                startIcon: this.theme.pasteIcon,
101                                content: "粘贴",
102                                labelInfo: "Ctrl+V"
103                            })
104                        }
105                    }
106                }
107                .radius(this.theme.containerBorderRadius)
108                .clip(true)
109                .backgroundColor(Color.White)
110                .width(this.theme.defaultMenuWidth)
111        }
112        .width(this.theme.defaultMenuWidth)
113}
114```
115
116![alt text](figures/richeditor_image_bindselectionmenu.gif)
117
118### 设置输入框光标、手柄颜色
119
120通过[caretColor](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#caretcolor12)设置输入框光标、手柄颜色。
121
122```ts
123RichEditor(this.options)
124    .onReady(() => {
125        this.controller.addTextSpan('组件设置了光标手柄颜色。', {
126            style: {
127                fontColor: Color.Black,
128                fontSize: 15
129            }
130        })
131    })
132    .caretColor(Color.Orange)
133    .width(300)
134    .height(300)
135```
136
137![alt text](figures/richeditor_image_caretcolor.gif)
138
139### 设置无输入时的提示文本
140
141通过[placeholder](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#placeholder12)设置无输入时的提示文本。
142
143其中value为无输入时的提示文本;style为添加提示文本的字体样式,style缺省时默认跟随主题。
144
145```ts
146RichEditor(this.options)
147    .placeholder("此处为提示文本...", {
148        fontColor: Color.Gray,
149        font: {
150            size: 15,
151            weight: FontWeight.Normal,
152            family: "HarmonyOS Sans",
153            style: FontStyle.Normal
154        }
155    })
156    .width(300)
157    .height(300)
158```
159
160![alt text](figures/richeditor_image_placeholder.gif)
161
162更多属性使用请参考[RichEditor属性](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#属性)。
163
164## 添加事件
165### 添加组件初始化完成后可触发的回调
166
167通过[onReady](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onready)来添加组件初始化完成后可触发的回调。
168
169其中callback是订阅富文本组件初始化完成的回调。
170
171```ts
172RichEditor(this.options)
173    .onReady(() => {
174        this.controller.addTextSpan('onReady回调内容是组件内预置文本。', {
175            style: {
176                fontColor: Color.Black,
177                fontSize: 15
178            }
179        })
180    })
181```
182
183![alt text](figures/richeditor_image_onReady.gif)
184
185### 添加组件内容被选中时可触发的回调
186
187通过[onSelect](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onselect)来添加组件内容被选中时可触发的回调。
188
189在callback中,[RichEditorSelection](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorselection)为选中的所有内容信息。
190
191触发该回调有两种方式:可通过鼠标左键按下选择,松开左键后触发回调,也可通过手指选择,松开手指触发回调。
192
193```ts
194RichEditor(this.options)
195    .onReady(() => {
196        this.controller.addTextSpan('选中此处文本,触发onselect回调。', {
197            style: {
198                fontColor: Color.Black,
199                fontSize: 15
200            }
201        })
202    })
203    .onSelect((value: RichEditorSelection) => {
204        this.controller1.addTextSpan(JSON.stringify(value), {
205            style: {
206                fontColor: Color.Gray,
207                fontSize: 10
208            }
209        })
210    })
211    .width(300)
212    .height(50)
213Text('查看回调内容:').fontSize(10).fontColor(Color.Gray).width(300)
214RichEditor(this.options1)
215    .width(300)
216    .height(70)
217```
218
219![alt text](figures/richeditor_image_onSelect.gif)
220
221### 添加图文变化前和图文变化后可触发的回调
222
223通过[onWillChange](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onwillchange12)添加图文变化前可触发的回调。通过[onDidChange](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#ondidchange12)添加图文变化后可触发的回调。
224
225onWillChange的callback中:[RichEditorChangeValue](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorchangevalue12)为图文变化信息;boolean为true时,表示当前图文允许被更改。boolean为false时,表示当前图文不允许被更改。
226
227onDidChange的callback中:[OnDidChangeCallback](../reference/apis-arkui/arkui-ts/ts-text-common.md#ondidchangecallback12)为图文变化前后的内容范围。
228
229使用[RichEditorStyledStringOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorstyledstringoptions12)构建的RichEditor组件不支持这两种回调。
230
231```ts
232RichEditor(this.options)
233    .onReady(() => {
234        this.controller.addTextSpan('组件内图文变化前,触发回调。\n图文变化后,触发回调。', {
235            style: {
236                fontColor: Color.Black,
237                fontSize: 15
238            }
239        })
240    })
241    .onWillChange((value: RichEditorChangeValue) => {
242        this.controller1.addTextSpan('组件内图文变化前,触发回调:\n' + JSON.stringify(value), {
243            style: {
244                fontColor: Color.Gray,
245                fontSize: 10
246            }
247        })
248        return true;
249    })
250    .onDidChange((rangeBefore: TextRange, rangeAfter: TextRange) => {
251        this.controller1.addTextSpan('\n图文变化后,触发回调:\nrangeBefore:' + JSON.stringify(rangeBefore) + '\nrangeAfter:' + JSON.stringify(rangeBefore), {
252            style: {
253                fontColor: Color.Gray,
254                fontSize: 10
255            }
256        })
257        return true;
258    })
259    .width(300)
260    .height(50)
261Text('查看回调内容:').fontSize(10).fontColor(Color.Gray).width(300)
262RichEditor(this.options1)
263    .width(300)
264    .height(70)
265```
266
267![alt text](figures/richeditor_image_ondid.gif)
268
269### 添加输入法输入内容前和完成输入后可触发的回调
270
271通过[aboutToIMEInput](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#abouttoimeinput)添加输入法输入内容前可触发的回调。通过[onIMEInputComplete](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onimeinputcomplete)添加输入法完成输入后可触发的回调。
272
273aboutToIMEInput的callback中:[RichEditorInsertValue](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorinsertvalue)为输入法将要输入内容信息;boolean为true时,组件执行添加内容操作。boolean为false时,组件不执行添加内容操作。
274
275onIMEInputComplete的callback中:[RichEditorTextSpanResult](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditortextspanresult)为输入法完成输入后的文本Span信息。
276
277使用[RichEditorStyledStringOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorstyledstringoptions12)构建的RichEditor组件不支持这两种回调。
278
279```ts
280RichEditor(this.options)
281          .onReady(() => {
282            this.controller.addTextSpan('输入法输入内容前,触发回调。\n输入法完成输入后,触发回调。' , {
283              style: {
284                fontColor: Color.Black,
285                fontSize: 15
286              }
287            })
288          })
289          .aboutToIMEInput((value: RichEditorInsertValue) => {
290            this.controller1.addTextSpan('输入法输入内容前,触发回调:\n'+JSON.stringify(value), {
291              style: {
292                fontColor: Color.Gray,
293                fontSize: 10
294              }
295            })
296            return true;
297          })
298          .onIMEInputComplete((value: RichEditorTextSpanResult) => {
299            this.controller1.addTextSpan('输入法完成输入后,触发回调:\n'+ JSON.stringify(value), {
300              style: {
301                fontColor: Color.Gray,
302                fontSize: 10
303              }
304            })
305            return true;
306          })
307          .width(300)
308          .height(50)
309Text('查看回调内容:').fontSize(10).fontColor(Color.Gray).width(300)
310RichEditor(this.options1)
311    .width(300)
312    .height(70)
313```
314
315![alt text](figures/richeditor_image_aboutToIMEInput2.0.gif)
316
317### 添加完成粘贴前可触发的回调
318
319通过[onPaste](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onpaste11)添加完成粘贴前可触发的回调。
320
321其中callback用于定义用户粘贴事件。
322
323由于系统的默认粘贴,只支持纯文本的粘贴。所以开发者可以通过该方法,覆盖系统默认行为,实现图文的粘贴。
324
325```ts
326RichEditor(this.options)
327    .onReady(() => {
328        this.controller.addTextSpan('对此处文本进行复制粘贴操作可触发对应回调。', {
329            style: {
330                fontColor: Color.Black,
331                fontSize: 15
332            }
333        })
334    })
335    .onPaste(() => {
336        this.controller1.addTextSpan('触发onPaste回调\n', {
337            style: {
338                fontColor: Color.Gray,
339                fontSize: 10
340            }
341        })
342    })
343    .width(300)
344    .height(70)
345```
346
347### 添加完成剪切前可触发的回调
348
349通过[onCut](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#oncut12)添加完成剪切前可触发的回调。
350
351其中callback用于定义用户剪切事件。
352
353由于系统的默认剪切行为,只支持纯文本的剪切。所以开发者可以通过该方法,覆盖系统默认行为,实现图文的剪切。
354
355```ts
356RichEditor(this.options)
357    .onReady(() => {
358        this.controller.addTextSpan('对此处文本进行复制粘贴操作可触发对应回调。', {
359            style: {
360                fontColor: Color.Black,
361                fontSize: 15
362            }
363        })
364    })
365    .onCut(() => {
366        this.controller1.addTextSpan('触发onCut回调\n', {
367            style: {
368                fontColor: Color.Gray,
369                fontSize: 10
370            }
371        })
372    })
373    .width(300)
374    .height(70)
375```
376
377### 添加完成复制前可触发的回调
378
379通过[onCopy](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#oncopy12)添加完成复制前可触发的回调。
380
381其中callback用于定义用户复制事件。
382
383由于系统的默认复制行为,只支持纯文本的复制。所以开发者可以通过该方法,覆盖系统默认行为,实现图文的复制。
384
385```ts
386RichEditor(this.options)
387    .onReady(() => {
388        this.controller.addTextSpan('对此处文本进行复制粘贴操作可触发对应回调。', {
389            style: {
390                fontColor: Color.Black,
391                fontSize: 15
392            }
393        })
394    })
395    .onCopy(() => {
396        this.controller1.addTextSpan('触发onCopy回调\n', {
397            style: {
398                fontColor: Color.Gray,
399                fontSize: 10
400            }
401        })
402    })
403    .width(300)
404    .height(70)
405```
406
407![alt text](figures/richeditor_image_oncut_paste_copy.gif)
408
409
410更多事件使用请参考[RichEditor事件](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#事件)。
411
412## 设置用户预设的样式
413
414通过[setTypingStyle](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#settypingstyle11)设置用户预设的样式。
415
416其中value是预设样式。
417
418```ts
419RichEditor(this.options)
420    .onReady(() => {
421        this.controller.addTextSpan('点击按钮,改变组件预设样式。', {
422            style: {
423                fontColor: Color.Black,
424                fontSize: 15
425            }
426        })
427    })
428    .width(300)
429    .height(60)
430Button('setTypingStyle', {
431        buttonStyle: ButtonStyleMode.NORMAL
432    })
433    .height(30)
434    .fontSize(13)
435    .onClick(() => {
436        this.controller.setTypingStyle({
437            fontWeight: 'medium',
438            fontColor: Color.Pink,
439            fontSize: 15,
440            fontStyle: FontStyle.Italic,
441            decoration: {
442                type: TextDecorationType.Underline,
443                color: Color.Gray
444            }
445        })
446    })
447```
448
449![alt text](figures/richeditor_image_setTypingStyle.gif)
450
451## 设置组件内的内容选中时部分背板高亮
452
453通过[setSelection](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#setselection11)设置组件内的内容选中时部分背板高亮。
454
455其中selectionStart为选中开始位置,selectionEnd选中结束位置。当selectionStart和selectionEnd均为-1时表示全选。
456
457当组件内未获焦出现光标时,调用该接口不产生选中效果。
458
459```ts
460RichEditor(this.options)
461    .onReady(() => {
462        this.controller.addTextSpan('点击按钮在此处选中0-2位置的文本。', {
463            style: {
464                fontColor: Color.Black,
465                fontSize: 15
466            }
467        })
468    })
469    .width(300)
470    .height(60)
471Button('setSelection(0,2)', {
472        buttonStyle: ButtonStyleMode.NORMAL
473    })
474    .height(30)
475    .fontSize(13)
476    .onClick(() => {
477        this.controller.setSelection(0, 2)
478    })
479```
480
481![alt text](figures/richeditor_image_set_selection.gif)
482
483## 添加文本内容
484
485除了直接在组件内输入内容,也可以通过[addTextSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addtextspan)添加文本内容。
486
487其中value是文本内容;options是文本选项,用于添加文本的偏移位置和文本样式信息([RichEditorTextSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditortextspanoptions))。
488
489如果组件光标闪烁,插入后光标位置更新为新插入文本的后面。
490
491```ts
492RichEditor(this.options)
493    .onReady(() => {
494        this.controller.addTextSpan('点击按钮在此处添加text。', {
495            style: {
496                fontColor: Color.Black,
497                fontSize: 15
498            }
499        })
500    })
501    .width(300)
502    .height(100)
503Button('addTextSpan', {
504        buttonStyle: ButtonStyleMode.NORMAL
505    })
506    .height(30)
507    .fontSize(13)
508    .onClick(() => {
509        this.controller.addTextSpan('新添加一段文字。')
510    })
511```
512
513![alt text](figures/richeditor_image_add_text.gif)
514
515## 添加图片内容
516
517通过[addImageSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addimagespan)添加图片内容。
518
519其中value是图片内容;options是图片选项,用于添加图片的偏移位置和图片样式信息([RichEditorImageSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorimagespanoptions))。
520
521添加图片内容,如果组件光标闪烁,插入后光标位置更新为新插入图片的后面。
522
523```ts
524RichEditor(this.options)
525    .onReady(() => {
526        this.controller.addTextSpan('点击按钮在此处添加image。', {
527            style: {
528                fontColor: Color.Black,
529                fontSize: 15
530            }
531        })
532    })
533    .width(300)
534    .height(100)
535Button('addImageSpan', {
536        buttonStyle: ButtonStyleMode.NORMAL
537    })
538    .height(30)
539    .fontSize(13)
540    .onClick(() => {
541        this.controller.addImageSpan($r("app.media.startIcon"), {
542            imageStyle: {
543                size: ["57px", "57px"]
544            }
545        })
546    })
547```
548
549![alt text](figures/richeditor_image_add_image.gif)
550
551## 添加@Builder装饰器修饰的内容
552通过[addBuilderSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addbuilderspan11)添加@Builder装饰器修饰的内容。
553
554其中value是builder内容;options是builder选项,可通过[RichEditorBuilderSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorbuilderspanoptions11)设置此builder在RichEditor中的index(一个文字为一个单位)。
555
556```ts
557@Builder
558TextBuilder() {
559    Row() {
560            Image($r('app.media.startIcon')).width(50).height(50).margin(16)
561            Column() {
562                Text("文本文档.txt").fontWeight(FontWeight.Bold).fontSize(16)
563                Text("123.45KB").fontColor('#8a8a8a').fontSize(12)
564            }.alignItems(HorizontalAlign.Start)
565        }.backgroundColor('#f4f4f4')
566        .borderRadius("20")
567        .width(220)
568}
569
570Button('addBuilderSpan', {
571        buttonStyle: ButtonStyleMode.NORMAL
572    })
573    .height(30)
574    .fontSize(13)
575    .onClick(() => {
576        this.my_builder = () => {
577            this.TextBuilder()
578        }
579        this.controller.addBuilderSpan(this.my_builder)
580    })
581```
582![alt text](figures/richeditor_image_add_builder_span2.0.gif)
583
584## 添加SymbolSpan内容
585
586可通过[addSymbolSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addsymbolspan11)添加SymbolSpan内容。
587
588其中value是SymbolSpan组件内容;options是SymbolSpan组件选项,用于添加SymbolSpan组件的偏移位置和SymbolSpan组件样式信息( [RichEditorSymbolSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorsymbolspanoptions11) )。
589
590添加SymbolSpan内容,如果组件光标闪烁,插入后光标位置更新为新插入Symbol的后面。
591
592SymbolSpan内容暂不支持手势、复制、拖拽处理。
593
594```ts
595RichEditor(this.options)
596    .onReady(() => {
597        this.controller.addTextSpan('点击按钮在此处添加symbol。', {
598            style: {
599                fontColor: Color.Black,
600                fontSize: 15
601            }
602        })
603    })
604    .width(300)
605    .height(100)
606Button('addSymbolSpan', {
607        buttonStyle: ButtonStyleMode.NORMAL
608    })
609    .height(30)
610    .fontSize(13)
611    .onClick(() => {
612        this.controller.addSymbolSpan($r("sys.symbol.basketball_fill"), {
613            style: {
614                fontSize: 30
615            }
616        })
617    })
618```
619![alt text](figures/richeditor_image_add_SymbolSpan.gif)
620
621## 获取组件内span信息
622
623可通过[getSpans](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#getspans)获取组件内span信息。
624
625其中value是需要获取span范围。返回值为Array<[RichEditorTextSpanResult](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditortextspanresult) | [RichEditorImageSpanResult](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorimagespanresult)>,是文本和图片Span信息。
626
627```ts
628RichEditor(this.options)
629    .onReady(() => {
630        this.controller.addTextSpan('点击按钮获取此处span信息。', {
631            style: {
632                fontColor: Color.Black,
633                fontSize: 15
634            }
635        })
636    })
637    .width(300)
638    .height(50)
639Text('查看getSpans返回值:').fontSize(10).fontColor(Color.Gray).width(300)
640RichEditor(this.options1)
641    .width(300)
642    .height(50)
643Button('getSpans', {
644        buttonStyle: ButtonStyleMode.NORMAL
645    })
646    .height(30)
647    .fontSize(13)
648    .onClick(() => {
649        this.controller1.addTextSpan(JSON.stringify(this.controller.getSpans()), {
650            style: {
651                fontColor: Color.Gray,
652                fontSize: 10
653            }
654        })
655
656    })
657```
658![alt text](figures/richeditor_image_getspan.gif)
659<!--RP1--><!--RP1End-->