• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# RichEditor
2
3**RichEditor** is a component that supports interactive text editing and mixture of text and imagery.
4
5>  **NOTE**
6>
7>  This component is supported since API version 10. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## Child Components
11
12Not supported
13
14
15## APIs
16
17RichEditor(value: RichEditorOptions)
18
19**Atomic service API**: This API can be used in atomic services since API version 11.
20
21**System capability**: SystemCapability.ArkUI.ArkUI.Full
22
23**Parameters**
24
25| Name  | Type                                   | Mandatory  | Description       |
26| ----- | --------------------------------------- | ---- | ----------- |
27| value | [RichEditorOptions](#richeditoroptions) | Yes   | Options for initializing the component.|
28
29RichEditor(options: RichEditorStyledStringOptions)<sup>12+</sup>
30
31
32**Parameters**
33
34| Name  | Type                                   | Mandatory  | Description       |
35| ----- | --------------------------------------- | ---- | ----------- |
36| options | [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) | Yes   | Options for initializing the component.|
37
38## Attributes
39
40In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported.
41
42>  **NOTE**
43>
44>  The **align** attribute supports only the start, center, and end options.
45>
46>  The **borderImage** attribute is not supported.
47
48### customKeyboard
49
50customKeyboard(value: CustomBuilder, options?: KeyboardOptions)
51
52Sets a custom keyboard.
53
54When a custom keyboard is set, activating the text box opens the specified custom component, instead of the system input method.
55
56The custom keyboard's height can be set through the **height** attribute of the custom component's root node, and its width is fixed at the default value.
57
58The custom keyboard cannot obtain focus, but it blocks gesture events.
59
60By default, the custom keyboard is closed when the input component loses the focus.
61
62When a custom keyboard is set, the text box does not support camera input, even when the device supports.
63
64**Atomic service API**: This API can be used in atomic services since API version 11.
65
66**System capability**: SystemCapability.ArkUI.ArkUI.Full
67
68**Parameters**
69
70| Name               | Type                                       | Mandatory| Description                            |
71| --------------------- | ------------------------------------------- | ---- | -------------------------------- |
72| value                 | [CustomBuilder](ts-types.md#custombuilder8) | Yes  | Custom keyboard.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
73| options<sup>12+</sup> | [KeyboardOptions](#keyboardoptions12)       | No  | Whether to support keyboard avoidance.|
74
75### bindSelectionMenu
76
77bindSelectionMenu(spanType: RichEditorSpanType, content: CustomBuilder, responseType: ResponseType | RichEditorResponseType,
78    options?: SelectionMenuOptions)
79
80Sets the custom context menu on text selection. If the custom menu is too long, embed a [Scroll](./ts-container-scroll.md) component to prevent the keyboard from being blocked.
81
82**Atomic service API**: This API can be used in atomic services since API version 11.
83
84**System capability**: SystemCapability.ArkUI.ArkUI.Full
85
86**Parameters**
87
88| Name      | Type                                                        | Mandatory| Description                                                     |
89| ------------ | ------------------------------------------------------------ | ---- | --------------------------------------------------------- |
90| spanType     | [RichEditorSpanType](#richeditorspantype)                    | Yes  | Menu type.<br> Default value:<br>RichEditorSpanType.TEXT    |
91| content      | [CustomBuilder](ts-types.md#custombuilder8)                  | Yes  | Menu content.                                             |
92| responseType |  [ResponseType](ts-appendix-enums.md#responsetype8) \| [RichEditorResponseType](#richeditorresponsetype11) | Yes  | Response type of the menu.<br> Default value:<br>ResponseType.LongPress |
93| options      | [SelectionMenuOptions](#selectionmenuoptions10)              | No  | Menu options.                                             |
94
95### copyOptions
96
97copyOptions(value: CopyOptions)
98
99Specifies whether copy and paste is allowed for text content.
100
101If **copyOptions** is not set to **CopyOptions.None**, long-pressing the text content displays the context menu. If a custom context menu is defined through **bindSelectionMenu** or other approaches, it will be displayed.
102
103If **copyOptions** is set to **CopyOptions.None**, the copy, cut, translate, search, and AI-powered writer features are not available.
104
105**Atomic service API**: This API can be used in atomic services since API version 11.
106
107**System capability**: SystemCapability.ArkUI.ArkUI.Full
108
109**Parameters**
110
111| Name| Type                                            | Mandatory| Description                                                        |
112| ------ | ------------------------------------------------ | ---- | ------------------------------------------------------------ |
113| value  | [CopyOptions](ts-appendix-enums.md#copyoptions9) | Yes  | Whether copy and paste is allowed for text content.<br>Default value: **CopyOptions.LocalDevice**|
114
115### enableDataDetector<sup>11+</sup>
116
117enableDataDetector(enable: boolean)
118
119Enables recognition for special entities within the text.
120
121For this API to work, the target device must provide the text recognition capability.
122
123If **enableDataDetector** is set to **true** and **dataDetectorConfig** is not set, all types of entities will be recognized, and the **color** and **decoration** attributes of the recognized entities will be changed to the following styles:
124
125```ts
126color: '#ff007dff'
127decoration:{
128  type: TextDecorationType.Underline,
129  color: '#ff007dff',
130  style: TextDecorationStyle.SOLID
131}
132```
133
134Touching and right-clicking an entity with the mouse will pop up the corresponding entity operation menu based on the type of entity, while left-clicking an entity with the mouse will directly respond to the first option of the menu.
135
136This API does not work for the node text of **addBuilderSpan**.
137
138When **copyOption** is set to **CopyOptions.None**, the menu displayed after an entity is clicked does not provide the text selection or copy functionality.
139
140**Atomic service API**: This API can be used in atomic services since API version 12.
141
142**System capability**: SystemCapability.ArkUI.ArkUI.Full
143
144**Parameters**
145
146| Name| Type   | Mandatory| Description                             |
147| ------ | ------- | ---- | --------------------------------- |
148| enable  | boolean | Yes  | Whether to enable text recognition.<br>Default value: **false**|
149
150### dataDetectorConfig<sup>11+</sup>
151
152dataDetectorConfig(config: TextDataDetectorConfig)
153
154Configures text recognition settings.
155
156This API must be used together with [enableDataDetector](#enabledatadetector11). It takes effect only when **enableDataDetector** is set to **true**.
157
158When entities A and B overlap, the following rules are followed:
159
1601. If A ⊂ B, retain B. Otherwise, retain A.
161
1622. When A ⊄ B and B ⊄ A: If A.start < B.start, retain A; otherwise, retain B.
163
164**Atomic service API**: This API can be used in atomic services since API version 12.
165
166**System capability**: SystemCapability.ArkUI.ArkUI.Full
167
168**Parameters**
169
170| Name| Type                                                       | Mandatory| Description                                                        |
171| ------ | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ |
172| config | [TextDataDetectorConfig](ts-text-common.md#textdatadetectorconfig11) | Yes  | Text recognition configuration.|
173
174### enablePreviewText<sup>12+</sup>
175
176enablePreviewText(enable: boolean)
177
178Sets whether to enable preview text.
179
180**Atomic service API**: This API can be used in atomic services since API version 12.
181
182**System capability**: SystemCapability.ArkUI.ArkUI.Full
183
184**Parameters**
185
186| Name| Type   | Mandatory| Description                             |
187| ------ | ------- | ---- | --------------------------------- |
188| enable  | boolean | Yes  | Whether to enable preview text.<br>Default value: **true**|
189
190>  **NOTE**
191>
192>  This API is disabled by default in C API scenarios. To enable preview text in such scenarios, set [metadata](../../../../application-dev/quick-start/module-structure.md#internal-structure-of-the-metadata-attribute) in the **module.json5** file of the project as follows:
193> ```json
194> "metadata": [
195>  {
196>     "name": "can_preview_text",
197>     "value": "true",
198>  }
199> ]
200> ```
201
202### placeholder<sup>12+</sup>
203
204placeholder(value: ResourceStr, style?: PlaceholderStyle)
205
206Sets the placeholder text, which is displayed when there is no input.
207
208**Atomic service API**: This API can be used in atomic services since API version 12.
209
210**System capability**: SystemCapability.ArkUI.ArkUI.Full
211
212**Parameters**
213
214| Name| Type                                   | Mandatory| Description                                                   |
215| ------ | --------------------------------------- | ---- | ------------------------------------------------------- |
216| value  | [ResourceStr](ts-types.md#resourcestr)  | Yes  | Placeholder text.                                   |
217| style  | [PlaceholderStyle](#placeholderstyle12) | No  | Style of the placeholder text.<br>By default, the style follows the theme.|
218
219### caretColor<sup>12+</sup>
220
221caretColor(value: ResourceColor)
222
223Sets the color of the caret and selection handle in the text box.
224
225**Atomic service API**: This API can be used in atomic services since API version 12.
226
227**System capability**: SystemCapability.ArkUI.ArkUI.Full
228
229**Parameters**
230
231| Name| Type                                      | Mandatory| Description                                  |
232| ------ | ------------------------------------------ | ---- | -------------------------------------- |
233| value  | [ResourceColor](ts-types.md#resourcecolor) | Yes  | Color of the cursor and selection handle in the text box.<br>Default value: **'#007DFF'**|
234
235### selectedBackgroundColor<sup>12+</sup>
236
237selectedBackgroundColor(value: ResourceColor)
238
239Sets the background color of the selected text. If the opacity is not set, a 20% opacity will be used.
240
241**Atomic service API**: This API can be used in atomic services since API version 12.
242
243**System capability**: SystemCapability.ArkUI.ArkUI.Full
244
245**Parameters**
246
247| Name| Type                                      | Mandatory| Description                                      |
248| ------ | ------------------------------------------ | ---- | ------------------------------------------ |
249| value  | [ResourceColor](ts-types.md#resourcecolor) | Yes  | Background color of the selected text.<br>By default, a 20% opacity is applied.|
250
251### editMenuOptions<sup>12+</sup>
252
253editMenuOptions(editMenu: EditMenuOptions)
254
255Sets the extended options of the custom context menu on selection, including the text content, icon, and callback.
256
257**Atomic service API**: This API can be used in atomic services since API version 12.
258
259**Atomic service API**: This API can be used in atomic services since API version 12.
260
261**System capability**: SystemCapability.ArkUI.ArkUI.Full
262
263**Parameters**
264
265| Name| Type                                         | Mandatory| Description                                         |
266| ------ | --------------------------------------------- | ---- | --------------------------------------------- |
267| editMenu  | [EditMenuOptions](ts-text-common.md#editmenuoptions) | Yes  | Extended options of the custom context menu on selection.|
268
269### enterKeyType<sup>12+</sup>
270
271enterKeyType(value: EnterKeyType)
272
273Sets the Enter key type of the soft keyboard.
274
275**Atomic service API**: This API can be used in atomic services since API version 12.
276
277**System capability**: SystemCapability.ArkUI.ArkUI.Full
278
279**Parameters**
280
281| Name| Type  | Mandatory| Description                               |
282| ------ | ------ | ---- | ----------------------------------- |
283| value  | [EnterKeyType](ts-basic-components-textinput.md#enterkeytype) | Yes  | Type of the Enter key.<br>Default value: **EnterKeyType.NEW_LINE**|
284
285### enableKeyboardOnFocus<sup>12+</sup>
286
287enableKeyboardOnFocus(isEnabled: boolean)
288
289Sets whether to enable the input method when the **RichEditor** component obtains focus in a way other than clicking.
290
291
292**Atomic service API**: This API can be used in atomic services since API version 12.
293
294**System capability**: SystemCapability.ArkUI.ArkUI.Full
295
296**Parameters**
297
298| Name| Type| Mandatory| Description|
299| ------ | ------- | ---- | ----------------------------------------------------------- |
300| isEnabled  | boolean | Yes  | Whether to enable the input method when the component obtains focus in a way other than clicking.<br>Default value: **true**|
301
302### barState<sup>13+</sup>
303
304barState(state: BarState)
305
306Sets the scrollbar display mode when the **RichEditor** text box is editable.
307
308**Atomic service API**: This API can be used in atomic services since API version 13.
309
310**System capability**: SystemCapability.ArkUI.ArkUI.Full
311
312**Parameters**
313
314| Name| Type| Mandatory| Description|
315| ------ | ----------------------------------------- | ---- | ------------------------------------------------------ |
316| state | [BarState](ts-appendix-enums.md#barstate) | Yes  | Scrollbar display mode when the text box is editable.<br>Default value: **BarState.Auto**|
317
318### maxLength<sup>18+</sup>
319
320maxLength(maxLength: Optional\<number\>)
321
322Sets the maximum number of characters for text input.
323
324**Atomic service API**: This API can be used in atomic services since API version 18.
325
326**System capability**: SystemCapability.ArkUI.ArkUI.Full
327
328**Parameters**
329
330| Name| Type  | Mandatory| Description                                                        |
331| ------ | ------ | ---- | ------------------------------------------------------------ |
332| maxLength  | [Optional](ts-universal-attributes-custom-property.md#optional12)\<number> | Yes  | Maximum number of characters for text input.<br>Default value: **Infinity**, which means unlimited input. The **undefined** type is supported.<br>**NOTE**<br>If this attribute is not set or is set to an invalid value, the default value is used. If a decimal number is specified, the integer part is used.|
333
334### maxLines<sup>18+</sup>
335
336maxLines(maxLines: Optional\<number\>)
337
338Sets the maximum number of lines that the rich text can display. When **maxLines** is set, content that exceeds the specified number of lines can be scrolled to display. If both the component height and **maxLines** are set, the component height takes precedence.
339
340**Atomic service API**: This API can be used in atomic services since API version 18.
341
342**System capability**: SystemCapability.ArkUI.ArkUI.Full
343
344**Parameters**
345
346| Name| Type                                     | Mandatory| Description                                                        |
347| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
348| maxLines  | [Optional](ts-universal-attributes-custom-property.md#optional12)\<number> | Yes  | Maximum number of lines that the rich text can display. When it is set, content that exceeds the specified number of lines can be scrolled to display. If both the component height and **maxLines** are set, the component height takes precedence.<br>Default value: **Infinity**, which means unlimited lines. The **undefined** type is supported.<br>Value range: (0, +∞)|
349
350### enableHapticFeedback<sup>13+</sup>
351
352enableHapticFeedback(isEnabled: boolean)
353
354Sets whether haptic feedback is enabled.
355
356**Atomic service API**: This API can be used in atomic services since API version 13.
357
358**System capability**: SystemCapability.ArkUI.ArkUI.Full
359
360| Name| Type                                         | Mandatory | Description                                                                                 |
361| ------ | --------------------------------------------- |-----|-------------------------------------------------------------------------------------|
362| isEnabled  | boolean | Yes  | Whether haptic feedback is enabled.<br>**true** (default): Haptic feedback is enabled.<br>**false**: Haptic feedback is disabled.<br>Whether this parameter takes effect after being set to true depends on hardware support.|
363
364### keyboardAppearance<sup>15+</sup>
365
366keyboardAppearance(appearance: Optional\<KeyboardAppearance\>)
367
368Sets the keyboard appearance.
369
370**Atomic service API**: This API can be used in atomic services since API version 15.
371
372**System capability**: SystemCapability.ArkUI.ArkUI.Full
373
374**Parameters**
375
376| Name| Type| Mandatory| Description|
377| ------ | ----------------------------------------- | ---- | ------------------------------------------------------ |
378| appearance | [Optional](ts-universal-attributes-custom-property.md#optional12)\<[KeyboardAppearance](ts-text-common.md#keyboardappearance15)\> | Yes  | Keyboard appearance.<br>Default value: **KeyboardAppearance.NONE_IMMERSIVE**|
379
380### stopBackPress<sup>18+</sup>
381
382stopBackPress(isStopped: Optional&lt;boolean&gt;)
383
384Sets whether to prevent the back button press from being propagated to other components or applications.
385
386**Atomic service API**: This API can be used in atomic services since API version 18.
387
388**System capability**: SystemCapability.ArkUI.ArkUI.Full
389
390| Name| Type                                         | Mandatory | Description                                                                                 |
391| ------ | --------------------------------------------- |-----|-------------------------------------------------------------------------------------|
392| isStopped  | Optional&lt;boolean&gt; | No  | Whether to prevent the back button press from being propagated to other components or applications. Default value: **true**|
393
394## Events
395
396In addition to the [universal events](ts-component-general-events.md), [OnDidChangeCallback](ts-text-common.md#ondidchangecallback12), [StyledStringChangedListener](ts-text-common.md#styledstringchangedlistener12), [StyledStringChangeValue](ts-text-common.md#styledstringchangevalue12), and the following events are supported.
397
398### onReady
399
400onReady(callback:Callback\<void\>)
401
402Triggered when initialization of the component is completed.
403
404**Atomic service API**: This API can be used in atomic services since API version 11.
405
406**System capability**: SystemCapability.ArkUI.ArkUI.Full
407
408**Parameters**
409
410| Name  | Type                                   | Mandatory  | Description       |
411| ----- | --------------------------------------- | ---- | ----------- |
412| callback |Callback\<void\> | Yes   | Callback invoked when initialization of the **RichEditor** component is complete. |
413
414### onSelect
415
416onSelect(callback:Callback\<[RichEditorSelection](#richeditorselection)\>)
417
418Triggered when content is selected.<br>If a mouse device is used for selection, this callback is invoked when the left mouse button is double-clicked to select content and invoked again when the button is released.
419
420If a finger is used for selection, this callback is invoked by a long press and invoked again when the finger is released.
421
422This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
423
424**Atomic service API**: This API can be used in atomic services since API version 11.
425
426**System capability**: SystemCapability.ArkUI.ArkUI.Full
427
428**Parameters**
429
430| Name| Type                                       | Mandatory| Description                |
431| ------ | ------------------------------------------- | ---- | -------------------- |
432| callback | Callback\<[RichEditorSelection](#richeditorselection)\> | Yes  | Callback invoked when content is selected.<br/>[RichEditorSelection](#richeditorselection) indicates information about all the selected spans. |
433
434### aboutToIMEInput
435
436aboutToIMEInput(callback:Callback\<[RichEditorInsertValue](#richeditorinsertvalue), boolean\>)
437
438Triggered when content is about to be entered in the input method.
439
440This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
441
442**Atomic service API**: This API can be used in atomic services since API version 11.
443
444**System capability**: SystemCapability.ArkUI.ArkUI.Full
445
446**Parameters**
447
448| Name| Type                                       | Mandatory| Description                |
449| ------ | ------------------------------------------- | ---- | -------------------- |
450| callback | Callback\<[RichEditorInsertValue](#richeditorinsertvalue), boolean\> | Yes  | Callback invoked when content is about to be entered in the input method.<br>[RichEditorInsertValue](#richeditorinsertvalue) indicates whether content will be entered in the input method.<br>**true**: The component adds the content.<br>**false**: The component does not add the content. |
451
452### onDidIMEInput<sup>12+</sup>
453
454onDidIMEInput(callback:Callback\<TextRange>)
455
456Triggered when text input in the input method is complete.
457
458This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
459
460**Atomic service API**: This API can be used in atomic services since API version 12.
461
462**System capability**: SystemCapability.ArkUI.ArkUI.Full
463
464**Parameters**
465
466| Name| Type                                       | Mandatory| Description                |
467| ------ | ------------------------------------------- | ---- | -------------------- |
468| callback | Callback\<[TextRange](ts-text-common.md#textrange12)\> | Yes| Callback invoked when text input in the input method is complete.<br>**TextRange** indicates the text range for the current input. |
469
470
471### onIMEInputComplete
472
473onIMEInputComplete(callback:Callback\<[RichEditorTextSpanResult](#richeditortextspanresult)\>)
474
475Triggered when text input in the input method is complete.
476
477This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
478
479**Atomic service API**: This API can be used in atomic services since API version 11.
480
481**System capability**: SystemCapability.ArkUI.ArkUI.Full
482
483**Parameters**
484
485| Name| Type                                       | Mandatory| Description                |
486| ------ | ------------------------------------------- | ---- | -------------------- |
487| callback | Callback\<[RichEditorTextSpanResult](#richeditortextspanresult)\> | Yes| Callback invoked when text input in the input method is complete.<br/>[RichEditorTextSpanResult](#richeditortextspanresult) indicates the text span information after text input is complete. |
488
489### aboutToDelete
490
491aboutToDelete(callback:Callback\<[RichEditorDeleteValue](#richeditordeletevalue), boolean\>)
492
493Triggered when content is about to be deleted in the input method.
494
495This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
496
497**Atomic service API**: This API can be used in atomic services since API version 11.
498
499**System capability**: SystemCapability.ArkUI.ArkUI.Full
500
501**Parameters**
502
503| Name| Type                                       | Mandatory| Description                |
504| ------ | ------------------------------------------- | ---- | -------------------- |
505| callback | Callback\<[RichEditorDeleteValue](#richeditordeletevalue), boolean\> | Yes| Callback invoked when content is about to be deleted in the input method. It is executed when a candidate word is touched in preview text.<br/>[RichEditorDeleteValue](#richeditordeletevalue) indicates the text or image span where the content to be deleted is located.<br>**true**: Content is deleted.<br>**false**: Content is not deleted. |
506
507### onDeleteComplete
508
509onDeleteComplete(callback:Callback\<void\>)
510
511Triggered when deletion in the input method is completed.
512
513This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
514
515**Atomic service API**: This API can be used in atomic services since API version 11.
516
517**System capability**: SystemCapability.ArkUI.ArkUI.Full
518
519**Parameters**
520
521| Name  | Type                                   | Mandatory  | Description       |
522| ----- | --------------------------------------- | ---- | ----------- |
523| callback |Callback\<void\> | Yes   | Callback invoked when deletion in the input method is completed.|
524
525### onPaste<sup>11+</sup>
526
527onPaste(callback: [PasteEventCallback](#pasteeventcallback12) )
528
529Triggered when the paste is about to be completed. You can use this API to override the default system behavior so that both images and text can be pasted.
530
531**Atomic service API**: This API can be used in atomic services since API version 12.
532
533**System capability**: SystemCapability.ArkUI.ArkUI.Full
534
535**Parameters**
536
537| Name| Type   | Mandatory| Description                         |
538| ------ | ------- | ---- | ----------------------------- |
539| callback | [PasteEventCallback](#pasteeventcallback12) | Yes  | Callback invoked when the paste is about to be completed.|
540
541### onSelectionChange<sup>12+</sup>
542
543onSelectionChange(callback:Callback\<[RichEditorRange](#richeditorrange)\>)
544
545Triggered when the content selection area changes or the caret position changes in the editing state. In the case of caret position changes, the start position of the content selection area is equal to the end position.
546
547**Atomic service API**: This API can be used in atomic services since API version 12.
548
549**System capability**: SystemCapability.ArkUI.ArkUI.Full
550
551**Parameters**
552
553| Name  | Type                                   | Mandatory  | Description       |
554| ----- | --------------------------------------- | ---- | ----------- |
555| callback |Callback\<[RichEditorRange](#richeditorrange)\> | Yes   | Callback invoked when the content selection area changes or the caret position changes in the editing state.<br/>[RichEditorRange](#richeditorrange) indicates the start and end positions of the content selection area. |
556
557### onEditingChange<sup>12+</sup>
558
559onEditingChange(callback: Callback\<boolean\>)
560
561Triggered when the editing state of all content in the component changes.
562
563**Atomic service API**: This API can be used in atomic services since API version 12.
564
565**System capability**: SystemCapability.ArkUI.ArkUI.Full
566
567**Parameters**
568
569| Name  | Type                                   | Mandatory  | Description       |
570| ----- | --------------------------------------- | ---- | ----------- |
571| callback | Callback\<boolean\> | Yes   | Callback invoked when the editing state of all content in the component changes. The value **true** indicates the editing state, and **false** indicates the non-editing state.|
572
573### onSubmit<sup>12+</sup>
574
575onSubmit(callback: SubmitCallback)
576
577Triggered when the Enter key on the soft keyboard is pressed.
578
579**Atomic service API**: This API can be used in atomic services since API version 12.
580
581**System capability**: SystemCapability.ArkUI.ArkUI.Full
582
583**Parameters**
584
585| Name| Type   | Mandatory| Description                         |
586| ------ | ------- | ---- | ----------------------------- |
587| callback | [SubmitCallback](#submitcallback12) | Yes  | Callback used to return the result.|
588
589### onWillChange<sup>12+</sup>
590
591onWillChange(callback: Callback\<RichEditorChangeValue, boolean\>)
592
593Triggered when any addition or deletion operation is about to be performed in the component.
594
595This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
596
597**Atomic service API**: This API can be used in atomic services since API version 12.
598
599**System capability**: SystemCapability.ArkUI.ArkUI.Full
600
601**Parameters**
602
603| Name| Type| Mandatory| Description|
604| -- | -- | -- | -- |
605| callback | Callback\<[RichEditorChangeValue](#richeditorchangevalue12) , boolean\> | Yes   | [RichEditorChangeValue](#richeditorchangevalue12) indicates the text and image change information. **boolean** indicates whether the current text and images are allowed to be changed. The value **true** means that the text and images are allowed to be changed, and **false** means the opposite.|
606
607### onDidChange<sup>12+</sup>
608
609onDidChange(callback: OnDidChangeCallback)
610
611Triggered after an addition or deletion operation is performed in the component. This callback is not executed if there is no actual addition or deletion of text.
612
613This callback is not supported when the **RichEditor** component constructed with [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) is used.
614
615**Atomic service API**: This API can be used in atomic services since API version 12.
616
617**System capability**: SystemCapability.ArkUI.ArkUI.Full
618
619**Parameters**
620
621| Name| Type| Mandatory| Description|
622| -- | -- | -- | -- |
623| callback | [OnDidChangeCallback](ts-text-common.md#ondidchangecallback12) | Yes| Content range before and after the text and image change.|
624
625### onCut<sup>12+</sup>
626
627onCut(callback: Callback\<CutEvent\>)
628
629Triggered when text is about to be cut. By default, only plain text can be cut. You can use this method to override the system's default behavior and implement the cutting of text and images.
630
631**Atomic service API**: This API can be used in atomic services since API version 12.
632
633**System capability**: SystemCapability.ArkUI.ArkUI.Full
634
635**Parameters**
636
637| Name  | Type                                   | Mandatory  | Description       |
638| ----- | --------------------------------------- | ---- | ----------- |
639| callback |Callback\<[CutEvent](#cutevent12)\> | Yes   | Custom cut event. |
640
641### onCopy<sup>12+</sup>
642
643onCopy(callback: Callback\<CopyEvent\>)
644
645Triggered when text is about to be copied. By default, only plain text can be copied. You can use this method to override the system's default behavior and implement the copying of text and images.
646
647**Atomic service API**: This API can be used in atomic services since API version 12.
648
649**System capability**: SystemCapability.ArkUI.ArkUI.Full
650
651**Parameters**
652
653| Name  | Type                                   | Mandatory  | Description       |
654| ----- | --------------------------------------- | ---- | ----------- |
655| callback |Callback\<[CopyEvent](#copyevent12)\> | Yes   | Custom copy event. |
656
657## RichEditorInsertValue
658
659Describes the text to be inserted.
660
661**System capability**: SystemCapability.ArkUI.ArkUI.Full
662
663| Name          | Type    | Mandatory  | Description        |
664| ------------ | ------ | ---- | ---------- |
665| insertOffset | number | Yes   | Offset of the text to be inserted.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
666| insertValue  | string | Yes   | Content of the text to be inserted.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
667| previewText<sup>12+</sup> | string | No   | Content of the preview text to be inserted.<br> **Atomic service API**: This API can be used in atomic services since API version 12.|
668
669
670## RichEditorDeleteValue
671
672Provides information about the delete operation and the deleted content.
673
674**Atomic service API**: This API can be used in atomic services since API version 11.
675
676**System capability**: SystemCapability.ArkUI.ArkUI.Full
677
678| Name                   | Type                                      | Mandatory  | Description                 |
679| --------------------- | ---------------------------------------- | ---- | ------------------- |
680| offset                | number                                   | Yes   | Offset of the deleted content.         |
681| direction             | [RichEditorDeleteDirection](#richeditordeletedirection) | Yes   | Direction of the delete operation.           |
682| length                | number                                   | Yes   | Length of the deleted content.            |
683| richEditorDeleteSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult) \| [RichEditorImageSpanResult](#richeditorimagespanresult)> | Yes   | Information about the deleted text or image span.|
684
685
686## RichEditorDeleteDirection
687
688Enumerates the directions of the delete operation.
689
690**Atomic service API**: This API can be used in atomic services since API version 11.
691
692**System capability**: SystemCapability.ArkUI.ArkUI.Full
693
694| Name    | Description      |
695| -------- | ---------- |
696| BACKWARD | Backward.|
697| FORWARD  | Forward.|
698
699
700## RichEditorTextSpanResult
701
702Provides the text span information.
703
704**System capability**: SystemCapability.ArkUI.ArkUI.Full
705
706| Name                           | Type                                      | Mandatory  | Description                    |
707| ----------------------------- | ---------------------------------------- | ---- | ---------------------- |
708| spanPosition                  | [RichEditorSpanPosition](#richeditorspanposition) | Yes   | Span position.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
709| value                         | string                                   | Yes   | Content of the text span or symbol ID.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
710| textStyle                     | [RichEditorTextStyleResult](#richeditortextstyleresult) | Yes   | Text span style.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
711| offsetInSpan                  | [number, number]                         | Yes   | Start and end positions of the valid content in the text span.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
712| valueResource<sup>11+</sup>   | [Resource](ts-types.md#resource)         | No   | Content of the **SymbolSpan** component.<br>**Atomic service API**: This API can be used in atomic services since API version 12.       |
713| symbolSpanStyle<sup>11+</sup> | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | No   | Style of the **SymbolSpan** component.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
714| paragraphStyle<sup>12+</sup>  | [RichEditorParagraphStyle](#richeditorparagraphstyle11)  | No  | Paragraph style.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
715| previewText<sup>12+</sup>      | string                                   | No   | Content of the preview text.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
716| urlStyle<sup>18+</sup>  | [RichEditorUrlStyle](#richeditorurlstyle18)   | No  | URL information.<br>Default value: **undefined**<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
717
718
719## RichEditorSpanPosition
720
721Provides the span position information.
722
723**Atomic service API**: This API can be used in atomic services since API version 11.
724
725**System capability**: SystemCapability.ArkUI.ArkUI.Full
726
727| Name       | Type              | Mandatory  | Description                         |
728| --------- | ---------------- | ---- | --------------------------- |
729| spanIndex | number           | Yes   | Span index.                   |
730| spanRange | [number, number] | Yes   | Start and end positions of the span content in the **RichEditor** component.|
731
732## RichEditorSpanType
733
734Provides the span type information.
735
736**System capability**: SystemCapability.ArkUI.ArkUI.Full
737
738| Name   | Value    | Description        |
739| ----- | ---- | ------------ |
740| TEXT  | 0 | Text span.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
741| IMAGE | 1 | Image span.<br>**Atomic service API**: This API can be used in atomic services since API version 11.  |
742| MIXED | 2 | Mixed span, which contains both text and imagery.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
743| BUILDER<sup>12+</sup> | 3 | Builder span.<br>**Atomic service API**: This API can be used in atomic services since API version 12. |
744| DEFAULT<sup>15+</sup> | 4 | Default type, used when no specific span type is specified.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
745
746## RichEditorResponseType<sup>11+</sup>
747
748Provides the response type of the menu.
749
750**System capability**: SystemCapability.ArkUI.ArkUI.Full
751
752| Name   | Value    | Description        |
753| ----- | ---- | ------------ |
754| RIGHT_CLICK  | 0 | The menu is displayed when the component is right-clicked.<br>**Atomic service API**: This API can be used in atomic services since API version 12.  |
755| LONG_PRESS | 1 | The menu is displayed when the component is long-pressed.<br>**Atomic service API**: This API can be used in atomic services since API version 12.  |
756| SELECT | 2 | The menu is displayed when the component is selected.<br>**Atomic service API**: This API can be used in atomic services since API version 12. |
757| DEFAULT<sup>15+</sup> | 3 | Default type, used when no specific response type is specified.<br>**Atomic service API**: This API can be used in atomic services since API version 15. |
758
759## RichEditorTextStyleResult
760
761Provides the text span style information returned by the backend.
762
763**System capability**: SystemCapability.ArkUI.ArkUI.Full
764
765| Name        | Type                                      | Mandatory  | Description          |
766| ---------- | ---------------------------------------- | ---- | ------------ |
767| fontColor  | [ResourceColor](ts-types.md#resourcecolor) | Yes   | Font color.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
768| fontSize   | number                                   | Yes   | Font size. The default unit is fp.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
769| fontStyle  | [FontStyle](ts-appendix-enums.md#fontstyle) | Yes   | Font style.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
770| fontWeight | number                                   | Yes   | Font weight.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
771| fontFamily | string                                   | Yes   | Font family.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
772| decoration | [DecorationStyleResult](ts-text-common.md#decorationstyleresult12) | Yes   | Text decorative line.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
773| textShadow<sup>12+</sup> |  Array&lt;[ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions)> | No   | Text shadow.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
774| lineHeight<sup>12+</sup> | number       | No   | Line height. The default unit is fp.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
775| letterSpacing<sup>12+</sup>| number       | No   | Letter spacing. The default unit is fp.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
776| fontFeature<sup>12+</sup> | string | No| Font feature.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
777| halfLeading<sup>18+</sup> | boolean | No| Whether half leading is enabled.<br>Half leading is the leading split in half and applied equally to the top and bottom edges. The value **true** means that half leading is enabled, and **false** means the opposite.<br>Default value: **false**<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
778| textBackgroundStyle<sup>18+</sup> | [TextBackgroundStyle](ts-basic-components-span.md#textbackgroundstyle11) | No   | Text background style.|
779
780>  **NOTE**
781>
782>  While **fontWeight** in **RichEditorTextStyle** sets the font weight, **fontWeight** in **RichEditorTextStyleResult** returns the set font weight after conversion to digits.
783>
784>  The table below lists the conversion mappings.
785>
786>  | fontWeight in RichEditorTextStyle | fontWeight in RichEditorTextStyleResult |
787>  | ---- | ----------------------------------- |
788>  | 100   | 0 |
789>  | 200   | 1 |
790>  | 300   | 2 |
791>  | 400   | 3 |
792>  | 500   | 4 |
793>  | 600   | 5 |
794>  | 700   | 6 |
795>  | 800   | 7 |
796>  | 900   | 8 |
797>  | Lighter   | 12 |
798>  | Normal   | 10 |
799>  | Regular   | 14 |
800>  | Medium   | 13 |
801>  | Bold   | 9 |
802>  | Bolder   | 11 |
803>
804>  The conversion mappings between the **fontWeight** parameters in **RichEditorSymbolSpanStyle** and **RichEditorSymbolSpanStyleResult** are the same as those between the **fontWeight** parameters in **RichEditorTextStyle** and **RichEditorTextStyleResult**.
805
806## RichEditorSymbolSpanStyleResult<sup>11+</sup>
807
808Provides the symbol span style information returned by the backend.
809
810**Atomic service API**: This API can be used in atomic services since API version 12.
811
812**System capability**: SystemCapability.ArkUI.ArkUI.Full
813
814| Name| Type| Mandatory| Description                              |
815| ------ | -------- | ---- | -------------------------------------- |
816| fontColor | Array\<[ResourceColor](ts-types.md#resourcecolor)\> | Yes| Color of the symbol span.<br> Default value: depending on the rendering strategy|
817| fontSize | number \| string \| [Resource](ts-types.md#resource) | Yes| Size of the symbol span. The default unit is fp.<br>The default value follows the theme.|
818| fontWeight | number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string  | Yes| Weight of the symbol span.<br>For the number type, the value ranges from 100 to 900, at an interval of 100. A larger value indicates a heavier font weight. The default value is **400**.<br>For the string type, only strings of the number type are supported, for example, **"400"**, **"bold"**, **"bolder"**, **"lighter"**, **"regular"**, and **"medium"**, which correspond to the enumerated values in **FontWeight**.<br>Default value: **FontWeight.Normal**|
819| renderingStrategy | [SymbolRenderingStrategy](ts-basic-components-symbolGlyph.md#symbolrenderingstrategy11)	| Yes| Rendering strategy of the symbol span.<br>Default value: **SymbolRenderingStrategy.SINGLE**<br>
820| effectStrategy | [SymbolEffectStrategy](ts-basic-components-symbolGlyph.md#symboleffectstrategy11)	| Yes| Effect strategy of the symbol span.<br>Default value: **SymbolEffectStrategy.NONE**<br>
821
822## RichEditorImageSpanResult
823
824Provides the image information returned by the backend.
825
826**Atomic service API**: This API can be used in atomic services since API version 11.
827
828**System capability**: SystemCapability.ArkUI.ArkUI.Full
829
830| Name              | Type                                                               | Mandatory | Description              |
831|------------------|-------------------------------------------------------------------|-----|------------------|
832| spanPosition     | [RichEditorSpanPosition](#richeditorspanposition)                 | Yes  | Span position.|
833| valuePixelMap    | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)                    | No  | Image content.|
834| valueResourceStr | [ResourceStr](ts-types.md#resourcestr)                            | No  | Image resource ID.|
835| imageStyle       | [RichEditorImageSpanStyleResult](#richeditorimagespanstyleresult) | Yes| Image style.|
836| offsetInSpan     | [number, number] | Yes| Start and end positions of the image in the span.|
837
838## RichEditorImageSpanStyleResult
839
840Provides the image span style information returned by the backend.
841
842**System capability**: SystemCapability.ArkUI.ArkUI.Full
843
844| Name           | Type                                      | Mandatory  | Description       |
845| ------------- | ---------------------------------------- | ---- | --------- |
846| size          | [number, number]                         | Yes   | Width and height of the image, in px. Default value: varies by the value of **objectFit**. If the value of **objectFit** is **Cover**, the image height is the component height minus the top and bottom paddings, and the image width is the component width minus the left and right paddings.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
847| verticalAlign | [ImageSpanAlignment](ts-appendix-enums.md#imagespanalignment10) | Yes   | Vertical alignment mode of the image.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
848| objectFit     | [ImageFit](ts-appendix-enums.md#imagefit) | Yes   | Scale mode of the image.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
849| layoutStyle<sup>12+</sup> | [RichEditorLayoutStyle](#richeditorlayoutstyle11)     | No  | Image layout style.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
850
851## RichEditorLayoutStyle<sup>11+</sup>
852
853**Atomic service API**: This API can be used in atomic services since API version 12.
854
855**System capability**: SystemCapability.ArkUI.ArkUI.Full
856
857|Name|Type|Mandatory|	Description|
858| -------------  | -----------------------            | ---- | ------------------------------------------------------------ |
859|margin	         |  [Dimension](ts-types.md#dimension10) \| [Margin](ts-types.md#margin)	                       |  No |	Margins in different directions of the component.<br>When the parameter is of the **Dimension** type, the four margins take effect.|
860|borderRadius	   |  [Dimension](ts-types.md#dimension10) \| [BorderRadiuses](ts-types.md#borderradiuses9)  |  No |	Radius of the rounded corners of the component.<br>If of the **Dimension** type, this parameter cannot be set in percentage.|
861
862## RichEditorOptions
863
864Defines the options for initializing the **RichEditor** component.
865
866**Atomic service API**: This API can be used in atomic services since API version 11.
867
868**System capability**: SystemCapability.ArkUI.ArkUI.Full
869
870| Name        | Type                                      | Mandatory  | Description     |
871| ---------- | ---------------------------------------- | ---- | ------- |
872| controller | [RichEditorController](#richeditorcontroller) | Yes   | Controller for the **RichEditor** component.|
873
874## RichEditorStyledStringOptions<sup>12+</sup>
875
876Defines the options for initializing the **RichEditor** component.
877
878**Atomic service API**: This API can be used in atomic services since API version 12.
879
880**System capability**: SystemCapability.ArkUI.ArkUI.Full
881
882| Name        | Type                                      | Mandatory  | Description     |
883| ---------- | ---------------------------------------- | ---- | ------- |
884| controller | [RichEditorStyledStringController](#richeditorstyledstringcontroller12) | Yes   | Controller for the **RichEditor** component.|
885
886## RichEditorChangeValue<sup>12+</sup>
887
888**Atomic service API**: This API can be used in atomic services since API version 12.
889
890**System capability**: SystemCapability.ArkUI.ArkUI.Full
891
892| Name                   | Type                                      | Mandatory  | Description                 |
893| --------------------- | ---------------------------------------- | ---- | ------------------- |
894| rangeBefore | [TextRange](ts-text-common.md#textrange12) | Yes   | Start and end indexes of the content to be replaced.|
895| replacedSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)> | Yes   | Information about the text span after the change.|
896| replacedImageSpans | Array<[RichEditorImageSpanResult](#richeditorimagespanresult)> | Yes   | Information about the image span after the change.|
897| replacedSymbolSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)> | Yes   | Information about the symbol span after the change.|
898
899## RichEditorBaseController<sup>12+</sup>
900
901Represents the base class of the **RichEditor** component controller.
902
903### getCaretOffset<sup>10+</sup>
904
905getCaretOffset(): number
906
907Obtains the current cursor position.
908
909**Atomic service API**: This API can be used in atomic services since API version 11.
910
911**System capability**: SystemCapability.ArkUI.ArkUI.Full
912
913**Return value**
914
915| Type    | Description       |
916| ------ | --------- |
917| number | Cursor position.|
918
919### setCaretOffset<sup>10+</sup>
920
921setCaretOffset(offset: number): boolean
922
923Sets the cursor position.
924
925**Atomic service API**: This API can be used in atomic services since API version 11.
926
927**System capability**: SystemCapability.ArkUI.ArkUI.Full
928
929**Parameters**
930
931| Name   | Type  | Mandatory  | Description               |
932| ------ | ------ | ---- | -------------------- |
933| offset | number | Yes   | Offset of the cursor. If it exceeds the range of all content, the setting will fail.|
934
935**Return value**
936
937| Type     | Description       |
938| ------- | --------- |
939| boolean | Whether the cursor position is set successfully.|
940
941### closeSelectionMenu<sup>10+</sup>
942
943closeSelectionMenu(): void
944
945Closes the custom or default context menu on selection.
946
947**Atomic service API**: This API can be used in atomic services since API version 11.
948
949**System capability**: SystemCapability.ArkUI.ArkUI.Full
950
951### getTypingStyle<sup>11+</sup>
952
953getTypingStyle(): RichEditorTextStyle
954
955Obtains the preset typing style.
956
957**Atomic service API**: This API can be used in atomic services since API version 12.
958
959**System capability**: SystemCapability.ArkUI.ArkUI.Full
960
961**Return value**
962
963| Type                                      | Description     |
964| ---------------------------------------- | ------- |
965| [RichEditorTextStyle](#richeditortextstyle) | Preset typing style.|
966
967### setTypingStyle<sup>11+</sup>
968
969setTypingStyle(value: RichEditorTextStyle): void
970
971Sets the preset typing style.
972
973**Atomic service API**: This API can be used in atomic services since API version 12.
974
975**System capability**: SystemCapability.ArkUI.ArkUI.Full
976
977**Parameters**
978
979| Name  | Type                                    | Mandatory  | Description |
980| ----- | ---------------------------------------- | ---- | ----- |
981| value | [RichEditorTextStyle](#richeditortextstyle) | Yes   | Preset typing style.|
982
983### setSelection<sup>11+</sup>
984
985setSelection(selectionStart: number, selectionEnd: number, options?: SelectionOptions): void
986
987Sets the range of content selection. The selected content is highlighted.
988
989If both **selectionStart** and **selectionEnd** are set to **-1**, the entire content is selected.
990
991If this API is called when the text box is not focused, the selected effect is not displayed.
992
993Since API version 12, on 2-in-1 devices, regardless of the value of **options**, calling the **setSelection** API will not display the menu. In addition, if there is already a menu present within the component, calling the **setSelection** API will close the menu.
994
995On non-2-in-1 devices, when **options** is set to **MenuPolicy.DEFAULT**, the following rules apply:
996
9971. If the component has a selection handle menu, calling the API will not close the menu, and the menu position will be adjusted.
998
9992. If the component has a menu without a selection handle, calling the API will not close the menu, and the menu position will remain unchanged.
1000
10013. If there is no menu within the component, calling the API will not display the menu.
1002
1003**Atomic service API**: This API can be used in atomic services since API version 12.
1004
1005**System capability**: SystemCapability.ArkUI.ArkUI.Full
1006
1007**Parameters**
1008
1009| Name           | Type  | Mandatory  | Description   |
1010| -------------- | ------ | ---- | ------- |
1011| selectionStart | number | Yes   | Start position of the selection.|
1012| selectionEnd   | number | Yes   | End position of the selection.|
1013| options<sup>12+</sup>   | [SelectionOptions](ts-types.md#selectionoptions12) | No   | Configuration of options.|
1014
1015### isEditing<sup>12+</sup>
1016
1017isEditing(): boolean
1018
1019Obtains the editing state of this **RichEditor** component.
1020
1021**Atomic service API**: This API can be used in atomic services since API version 12.
1022
1023**System capability**: SystemCapability.ArkUI.ArkUI.Full
1024
1025**Return value**
1026
1027| Type   | Description                         |
1028| ------- | ----------------------------- |
1029| boolean | Editing state. The value **true** indicates the editing state, and **false** indicates the non-editing state.|
1030
1031### stopEditing<sup>12+</sup>
1032
1033stopEditing(): void
1034
1035Exits the editing state.
1036
1037**Atomic service API**: This API can be used in atomic services since API version 12.
1038
1039**System capability**: SystemCapability.ArkUI.ArkUI.Full
1040
1041### getLayoutManager<sup>12+</sup>
1042
1043getLayoutManager(): LayoutManager
1044
1045Obtains a **LayoutManager** object.
1046
1047**Atomic service API**: This API can be used in atomic services since API version 12.
1048
1049**System capability**: SystemCapability.ArkUI.ArkUI.Full
1050
1051**Return value**
1052
1053| Type                                      | Description     |
1054| ---------------------------------------- | ------- |
1055| [LayoutManager](ts-text-common.md#LayoutManager12) | **LayoutManager** object.|
1056
1057### getPreviewText<sup>12+</sup>
1058
1059getPreviewText(): PreviewText
1060
1061Obtains the preview text.
1062
1063**Atomic service API**: This API can be used in atomic services since API version 12.
1064
1065**System capability**: SystemCapability.ArkUI.ArkUI.Full
1066
1067**Return value**
1068
1069| Type                                      | Description     |
1070| ---------------------------------------- | ------- |
1071| [PreviewText](ts-text-common.md#previewtext12) | Preview text.|
1072
1073### getCaretRect<sup>18+</sup>
1074
1075getCaretRect(): RectResult | undefined
1076
1077Obtains the relative position of the cursor in the **RichEditor** component. If the cursor is not blinking, the API returns **undefined**.
1078
1079**Atomic service API**: This API can be used in atomic services since API version 18.
1080
1081**System capability**: SystemCapability.ArkUI.ArkUI.Full
1082
1083**Return value**
1084
1085| Type    | Description       |
1086| ------ | --------- |
1087| [RectResult](ts-types.md#rectresult10) \| undefined | Relative position of the cursor in the **RichEditor** component.|
1088
1089## RichEditorController
1090
1091Implements the **RichEditor** component controller. Inherits from [RichEditorBaseController](#richeditorbasecontroller12).
1092
1093### Objects to Import
1094
1095```
1096controller: RichEditorController = new RichEditorController()
1097```
1098
1099### addTextSpan
1100
1101addTextSpan(value: string, options?: RichEditorTextSpanOptions): number
1102
1103Adds a text span. If the cursor in the component is blinking, the cursor position is updated to be after the inserted text span.
1104
1105**Atomic service API**: This API can be used in atomic services since API version 11.
1106
1107**System capability**: SystemCapability.ArkUI.ArkUI.Full
1108
1109**Parameters**
1110
1111| Name    | Type                                    | Mandatory  | Description |
1112| ------- | ---------------------------------------- | ---- | ----- |
1113| value   | string                                   | Yes   | Text content.|
1114| options | [RichEditorTextSpanOptions](#richeditortextspanoptions) | No   | Text options.|
1115
1116**Return value**
1117
1118| Type    | Description                  |
1119| ------ | -------------------- |
1120| number | Position of the added text span.|
1121
1122### addImageSpan
1123
1124addImageSpan(value: PixelMap | ResourceStr, options?: RichEditorImageSpanOptions): number
1125
1126Adds an image span. If the cursor in the component is blinking, the cursor position is updated to be after the inserted image span.
1127
1128To avoid potential loading issues, do not directly add a network image.
1129
1130**Atomic service API**: This API can be used in atomic services since API version 11.
1131
1132**System capability**: SystemCapability.ArkUI.ArkUI.Full
1133
1134**Parameters**
1135
1136| Name    | Type                                    | Mandatory  | Description |
1137| ------- | ---------------------------------------- | ---- | ----- |
1138| value   | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)\|[ResourceStr](ts-types.md#resourcestr) | Yes   | Image content.|
1139| options | [RichEditorImageSpanOptions](#richeditorimagespanoptions) | No   | Image options.|
1140
1141**Return value**
1142
1143| Type    | Description                  |
1144| ------ | -------------------- |
1145| number | Position of the added image span.|
1146
1147### addBuilderSpan<sup>11+</sup>
1148
1149addBuilderSpan(value: CustomBuilder, options?: RichEditorBuilderSpanOptions): number
1150
1151Adds a custom builder span.
1152
1153> **NOTE**
1154>
1155> - This API adds a builder span to take up space in the layout. It calls the system **measure** method to calculate the actual length, width, and position.
1156> - You can use [RichEditorBuilderSpanOptions](#richeditorbuilderspanoptions11) to set the index of the builder in the **RichEditor** component (with one character as the unit).
1157> - This builder span is unfocusable, draggable, and equipped with certain universal attributes. It behaves similarly to an image span in terms of placeholder and deletion functionality, and it is treated as a single character in length.
1158> - Custom menus can be set using [bindSelectionMenu](#bindselectionmenu).
1159> - The information about the builder span cannot be obtained through [getSpans](#getspans), [getSelection](#getselection11), [onSelect](#onselect), or [aboutToDelete](#abouttodelete).
1160> - The builder span cannot be updated using [updateSpanStyle](#updatespanstyle) or [updateParagraphStyle](#updateparagraphstyle11).
1161> - Copying or pasting the builder span does not take effect.
1162> - The layout constraints of the builder span are passed in from the **RichEditor** component. If the size of the outermost component in the builder span is not set, the size of the **RichEditor** is used as the value of **maxSize**.
1163> - The gesture event mechanism of the builder span is the same as the universal gesture event mechanism. If transparent transmission is not set in the builder, only the child components in the builder respond.
1164> - If the cursor in the component is blinking, the cursor position is updated to be after the inserted image span.
1165
1166The following universal attributes are supported: [size](ts-universal-attributes-size.md#size), [padding](ts-universal-attributes-size.md#padding), [margin](ts-universal-attributes-size.md#margin), [aspectRatio](ts-universal-attributes-layout-constraints.md#aspectratio), [borderStyle](ts-universal-attributes-border.md#borderstyle), [borderWidth](ts-universal-attributes-border.md#borderwidth), [borderColor](ts-universal-attributes-border.md#bordercolor), [borderRadius](ts-universal-attributes-border.md#borderradius), [backgroundColor](ts-universal-attributes-background.md#backgroundcolor), [backgroundBlurStyle](ts-universal-attributes-background.md#backgroundblurstyle9), [opacity](ts-universal-attributes-opacity.md), [blur](ts-universal-attributes-image-effect.md#blur), [backdropBlur](ts-universal-attributes-background.md#backdropblur), [shadow](ts-universal-attributes-image-effect.md#shadow), [grayscale](ts-universal-attributes-image-effect.md#grayscale), [brightness](ts-universal-attributes-image-effect.md#brightness), [saturate](ts-universal-attributes-image-effect.md#saturate),
1167[contrast](ts-universal-attributes-image-effect.md#contrast), [invert](ts-universal-attributes-image-effect.md#invert), [sepia](ts-universal-attributes-image-effect.md#sepia), [hueRotate](ts-universal-attributes-image-effect.md#huerotate), [colorBlend](ts-universal-attributes-image-effect.md#colorblend7), [linearGradientBlur](ts-universal-attributes-image-effect.md#lineargradientblur12), [clip](ts-universal-attributes-sharp-clipping.md#clip12), [mask](ts-universal-attributes-sharp-clipping.md#mask12), [foregroundBlurStyle](ts-universal-attributes-foreground-blur-style.md#foregroundblurstyle), [accessibilityGroup](ts-universal-attributes-accessibility.md#accessibilitygroup), [accessibilityText](ts-universal-attributes-accessibility.md#accessibilitytext), [accessibilityDescription](ts-universal-attributes-accessibility.md#accessibilitydescription), [accessibilityLevel](ts-universal-attributes-accessibility.md#accessibilitylevel), [sphericalEffect](ts-universal-attributes-image-effect.md#sphericaleffect12), [lightUpEffect](ts-universal-attributes-image-effect.md#lightupeffect12), [pixelStretchEffect](ts-universal-attributes-image-effect.md#pixelstretcheffect12)
1168
1169**Atomic service API**: This API can be used in atomic services since API version 12.
1170
1171**System capability**: SystemCapability.ArkUI.ArkUI.Full
1172
1173**Parameters**
1174
1175| Name    | Type                                    | Mandatory  | Description      |
1176| ------- | ---------------------------------------- | ---- | ---------- |
1177| value   | [CustomBuilder](ts-types.md#custombuilder8) | Yes   | Custom component.    |
1178| options | [RichEditorBuilderSpanOptions](#richeditorbuilderspanoptions11) | No   | Builder options.|
1179
1180**Return value**
1181
1182| Type    | Description                    |
1183| ------ | ---------------------- |
1184| number | Position of the added builder span.|
1185
1186### addSymbolSpan<sup>11+</sup>
1187
1188addSymbolSpan(value: Resource, options?: RichEditorSymbolSpanOptions ): number
1189
1190Adds a symbol image. If the cursor in the component is blinking, the cursor position is updated to be after the inserted symbol span.
1191
1192Currently, gestures, copying, and dragging are not supported.
1193
1194**Atomic service API**: This API can be used in atomic services since API version 12.
1195
1196**System capability**: SystemCapability.ArkUI.ArkUI.Full
1197
1198**Parameters**
1199
1200| Name    | Type                                    | Mandatory  | Description |
1201| ------- | ---------------------------------------- | ---- | ----- |
1202| value   | [Resource](ts-types.md#resource)         | Yes   | Content of the symbol span.|
1203| options | [RichEditorSymbolSpanOptions](#richeditorsymbolspanoptions11) | No   | Options of the symbol span.|
1204
1205**Return value**
1206
1207| Type    | Description                   |
1208| ------ | --------------------- |
1209| number | Position of the added symbol span.|
1210
1211### updateSpanStyle
1212
1213updateSpanStyle(value: RichEditorUpdateTextSpanStyleOptions | RichEditorUpdateImageSpanStyleOptions | RichEditorUpdateSymbolSpanStyleOptions): void
1214
1215Updates the text, image, or symbol span style.<br>If only part of a span is updated, the span is split into multiple spans based on the updated part and the non-updated part.
1216
1217Calling this API will not close the custom context menu on selection by default.
1218
1219**Atomic service API**: This API can be used in atomic services since API version 11.
1220
1221**System capability**: SystemCapability.ArkUI.ArkUI.Full
1222
1223**Parameters**
1224
1225| Name| Type| Mandatory| Description                              |
1226| ------ | -------- | ---- | -------------------------------------- |
1227| value | [RichEditorUpdateTextSpanStyleOptions](#richeditorupdatetextspanstyleoptions) \| [RichEditorUpdateImageSpanStyleOptions](#richeditorupdateimagespanstyleoptions) \| [RichEditorUpdateSymbolSpanStyleOptions](#richeditorupdatesymbolspanstyleoptions11) | Yes| Style options of the text, image, or symbol span.|
1228
1229>  **NOTE**
1230>
1231>  If the value of **start** is greater than that of **end**, the value **0** will be used as **start** and infinity as **end**.
1232
1233### updateParagraphStyle<sup>11+</sup>
1234
1235updateParagraphStyle(value: RichEditorParagraphStyleOptions): void
1236
1237Updates the paragraph style.
1238
1239**Atomic service API**: This API can be used in atomic services since API version 12.
1240
1241**System capability**: SystemCapability.ArkUI.ArkUI.Full
1242
1243**Parameters**
1244
1245| Name   | Type                                      | Mandatory  | Description        |
1246| ----- | ---------------------------------------- | ---- | ---------- |
1247| value | [RichEditorParagraphStyleOptions](#richeditorparagraphstyleoptions11) | Yes   | Information about the paragraph style.|
1248
1249### getSpans
1250
1251getSpans(value?: RichEditorRange): Array<RichEditorImageSpanResult| RichEditorTextSpanResult>
1252
1253Obtains span information.
1254
1255**Atomic service API**: This API can be used in atomic services since API version 11.
1256
1257**System capability**: SystemCapability.ArkUI.ArkUI.Full
1258
1259**Parameters**
1260
1261| Name  | Type                               | Mandatory  | Description       |
1262| ----- | ----------------------------------- | ---- | ----------- |
1263| value | [RichEditorRange](#richeditorrange) | No   | Range of the target span.|
1264
1265**Return value**
1266
1267| Type                                      | Description          |
1268| ---------------------------------------- | ------------ |
1269| Array<[RichEditorTextSpanResult](#richeditortextspanresult) \| [RichEditorImageSpanResult](#richeditorimagespanresult)> | Text and image span information.|
1270
1271### deleteSpans
1272
1273deleteSpans(value?: RichEditorRange): void
1274
1275Deletes the text and image spans in a specified range.
1276
1277**Atomic service API**: This API can be used in atomic services since API version 11.
1278
1279**System capability**: SystemCapability.ArkUI.ArkUI.Full
1280
1281**Parameters**
1282
1283| Name  | Type                               | Mandatory  | Description               |
1284| ----- | ----------------------------------- | ---- | ------------------- |
1285| value | [RichEditorRange](#richeditorrange) | No   | Range of the target spans. If this parameter is left empty, all text and image spans will be deleted.|
1286
1287### getParagraphs<sup>11+</sup>
1288
1289getParagraphs(value?: RichEditorRange): Array\<RichEditorParagraphResult>
1290
1291Obtains the specified paragraphs.
1292
1293**Atomic service API**: This API can be used in atomic services since API version 12.
1294
1295**System capability**: SystemCapability.ArkUI.ArkUI.Full
1296
1297**Parameters**
1298
1299| Name  | Type                               | Mandatory  | Description      |
1300| ----- | ----------------------------------- | ---- | ---------- |
1301| value | [RichEditorRange](#richeditorrange) | No   | Range of the paragraphs to obtain.|
1302
1303**Return value**
1304
1305| Type                                      | Description      |
1306| ---------------------------------------- | -------- |
1307| Array\<[RichEditorParagraphResult](#richeditorparagraphresult11)> | Information about the selected paragraphs.|
1308
1309### getSelection<sup>11+</sup>
1310
1311getSelection(): RichEditorSelection
1312
1313Obtains the selected content. If no text is selected, the information about the span where the caret is located is returned.
1314
1315**Atomic service API**: This API can be used in atomic services since API version 12.
1316
1317**System capability**: SystemCapability.ArkUI.ArkUI.Full
1318
1319**Return value**
1320
1321| Type                                      | Description     |
1322| ---------------------------------------- | ------- |
1323| [RichEditorSelection](#richeditorselection) | Provides information about the selected content.|
1324
1325### fromStyledString<sup>12+</sup>
1326
1327fromStyledString(value: StyledString): Array\<RichEditorSpan>
1328
1329Converts a styled string into a span.
1330
1331**Atomic service API**: This API can be used in atomic services since API version 12.
1332
1333**System capability**: SystemCapability.ArkUI.ArkUI.Full
1334
1335**Parameters**
1336
1337| Name  | Type                               | Mandatory  | Description      |
1338| ----- | ----------------------------------- | ---- | ---------- |
1339| value | [StyledString](ts-universal-styled-string.md#styledstring) | Yes   | Styled string before conversion.|
1340
1341**Return value**
1342
1343| Type                                      | Description     |
1344| ---------------------------------------- | ------- |
1345| Array<[RichEditorSpan](#richeditorspan12)>  | Text and image span information.|
1346
1347**Error codes**
1348
1349For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md).
1350
1351| ID| Error Message                       |
1352| -------- | ------------------------------ |
1353| 401      | The parameter check failed.  |
1354
1355### toStyledString<sup>12+</sup>
1356
1357toStyledString(value: RichEditorRange): StyledString
1358
1359Converts the component content within the given range into a styled string.
1360
1361**Atomic service API**: This API can be used in atomic services since API version 12.
1362
1363**System capability**: SystemCapability.ArkUI.ArkUI.Full
1364
1365**Parameters**
1366
1367| Name  | Type                               | Mandatory  | Description      |
1368| ----- | ----------------------------------- | ---- | ---------- |
1369| value | [RichEditorRange](#richeditorrange) | Yes  | Source range.|
1370
1371**Return value**
1372
1373| Type                                      | Description      |
1374| ---------------------------------------- | -------- |
1375| [StyledString](ts-universal-styled-string.md#styledstring) | Styled string after conversion.|
1376
1377**Error codes**
1378
1379For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md).
1380
1381| ID| Error Message                       |
1382| -------- | ------------------------------ |
1383| 401      | The parameter check failed.  |
1384
1385
1386## RichEditorStyledStringController<sup>12+</sup>
1387
1388Represents the controller of the **RichEditor** component constructed using the styled string. Inherits from [RichEditorBaseController](#richeditorbasecontroller12).
1389
1390### Objects to Import
1391
1392```
1393controller: RichEditorStyledStringController = new RichEditorStyledStringController()
1394```
1395
1396### getSelection<sup>12+</sup>
1397
1398getSelection(): RichEditorRange
1399
1400Obtains the current selection range of the **RichEditor** component.
1401
1402**Atomic service API**: This API can be used in atomic services since API version 12.
1403
1404**System capability**: SystemCapability.ArkUI.ArkUI.Full
1405
1406**Return value**
1407
1408| Type                                      | Description     |
1409| ---------------------------------------- | ------- |
1410| [RichEditorRange](#richeditorrange) | Selection range.|
1411
1412### setStyledString<sup>12+</sup>
1413
1414setStyledString(styledString: StyledString): void
1415
1416Sets the styled string displayed in the **RichEditor** component.
1417
1418**Atomic service API**: This API can be used in atomic services since API version 12.
1419
1420**System capability**: SystemCapability.ArkUI.ArkUI.Full
1421
1422**Parameters**
1423
1424| Name  | Type  | Mandatory  | Description               |
1425| ----- | ------ | ---- | ------------------- |
1426| styledString | [StyledString](ts-universal-styled-string.md#styledstring) | Yes   | Styled string.<br>**NOTE**<br>The child class [MutableStyledString](ts-universal-styled-string.md#mutablestyledstring) of **StyledString** can also serve as the argument.|
1427
1428### getStyledString<sup>12+</sup>
1429
1430getStyledString(): MutableStyledString;
1431
1432Obtains the styled string displayed in the **RichEditor** component.
1433
1434**Atomic service API**: This API can be used in atomic services since API version 12.
1435
1436**System capability**: SystemCapability.ArkUI.ArkUI.Full
1437
1438**Return value**
1439
1440| Type   | Description                         |
1441| ------- | ----------------------------- |
1442| [MutableStyledString](ts-universal-styled-string.md#mutablestyledstring) | Styled string displayed in the **RichEditor** component.|
1443
1444### onContentChanged<sup>12+</sup>
1445
1446onContentChanged(listener: StyledStringChangedListener): void
1447
1448Triggered when text content changes. This callback is invoked when the text content is changed by the backend program.
1449
1450**Atomic service API**: This API can be used in atomic services since API version 12.
1451
1452**System capability**: SystemCapability.ArkUI.ArkUI.Full
1453
1454**Parameters**
1455
1456| Name  | Type  | Mandatory  | Description               |
1457| ----- | ------ | ---- | ------------------- |
1458| listener | [StyledStringChangedListener](ts-text-common.md#styledstringchangedlistener12) | Yes   | Callback listener for text content changes.|
1459
1460## RichEditorSelection
1461
1462Provides information about the selected content.
1463
1464**Atomic service API**: This API can be used in atomic services since API version 11.
1465
1466**System capability**: SystemCapability.ArkUI.ArkUI.Full
1467
1468| Name       | Type                                      | Mandatory  | Description     |
1469| --------- | ---------------------------------------- | ---- | ------- |
1470| selection | [number, number]                         | Yes   | Range of the selected.  |
1471| spans     | Array<[RichEditorTextSpanResult](#richeditortextspanresult)\| [RichEditorImageSpanResult](#richeditorimagespanresult)> | Yes   | Span information.|
1472
1473## RichEditorRange
1474
1475Defines the range of the **RichEditor**.
1476
1477**Atomic service API**: This API can be used in atomic services since API version 11.
1478
1479**System capability**: SystemCapability.ArkUI.ArkUI.Full
1480
1481| Name | Type  | Mandatory| Description                                                        |
1482| ----- | ------ | ---- | ------------------------------------------------------------ |
1483| start | number | No  | Start position of the span whose style needs to be updated. If this parameter is left empty or set to a negative value, the value **0** will be used. |
1484| end   | number | No  | End position of the span whose style needs to be updated. If this parameter is left empty or set to a value beyond the range, it indicates infinity.|
1485
1486
1487## RichEditorSpanStyleOptions
1488
1489Defines the text span style options.
1490
1491Inherits [RichEditorRange](#richeditorrange).
1492
1493**Atomic service API**: This API can be used in atomic services since API version 11.
1494
1495**System capability**: SystemCapability.ArkUI.ArkUI.Full
1496
1497## RichEditorUpdateTextSpanStyleOptions
1498
1499Defines the text span style options.
1500
1501Inherits [RichEditorSpanStyleOptions](#richeditorspanstyleoptions).
1502
1503**System capability**: SystemCapability.ArkUI.ArkUI.Full
1504
1505| Name     | Type                                       | Mandatory| Description      |
1506| --------- | ------------------------------------------- | ---- | ---------- |
1507| textStyle | [RichEditorTextStyle](#richeditortextstyle) | Yes  | Text style.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1508| urlStyle<sup>18+</sup>  | [RichEditorUrlStyle](#richeditorurlstyle18)   | No  | URL information.<br>Default value: **undefined**<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
1509
1510## RichEditorUpdateImageSpanStyleOptions
1511
1512Defines the image span style options.
1513
1514Inherits [RichEditorSpanStyleOptions](#richeditorspanstyleoptions).
1515
1516**Atomic service API**: This API can be used in atomic services since API version 11.
1517
1518**System capability**: SystemCapability.ArkUI.ArkUI.Full
1519
1520| Name        | Type                                      | Mandatory  | Description                             |
1521| ---------- | ---------------------------------------- | ---- | ------------------------------- |
1522| imageStyle | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | Yes   | Image style.                          |
1523
1524## RichEditorUpdateSymbolSpanStyleOptions<sup>11+</sup>
1525
1526Defines the symbol span style options.
1527
1528Inherits [RichEditorSpanStyleOptions](#richeditorspanstyleoptions).
1529
1530**Atomic service API**: This API can be used in atomic services since API version 12.
1531
1532**System capability**: SystemCapability.ArkUI.ArkUI.Full
1533
1534| Name       | Type                                                     | Mandatory| Description      |
1535| ----------- | --------------------------------------------------------- | ---- | ---------- |
1536| symbolStyle | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | Yes  | Style of the symbol span.|
1537
1538## RichEditorParagraphStyleOptions<sup>11+</sup>
1539
1540Defines the paragraph style options.
1541
1542Inherits [RichEditorSpanStyleOptions](#richeditorspanstyleoptions).
1543
1544**Atomic service API**: This API can be used in atomic services since API version 12.
1545
1546**System capability**: SystemCapability.ArkUI.ArkUI.Full
1547
1548| Name   | Type                                      | Mandatory  | Description                                |
1549| ----- | ---------------------------------------- | ---- | ---------------------------------- |
1550| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | Yes   | Paragraph style.                             |
1551
1552>  **NOTE**
1553>
1554>  Applicable scope of the API: spans involved in the specified range.
1555
1556
1557## RichEditorParagraphStyle<sup>11+</sup>
1558
1559Describes the paragraph style.
1560
1561**System capability**: SystemCapability.ArkUI.ArkUI.Full
1562
1563| Name           | Type                                      | Mandatory  | Description                |
1564| ------------- | ---------------------------------------- | ---- | ------------------ |
1565| textAlign     | [TextAlign](ts-appendix-enums.md#textalign) | No   | Horizontal alignment mode of the text. <br>Default value: **TextAlign.START**<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1566| leadingMargin | [Dimension](ts-types.md#dimension10) \| [LeadingMarginPlaceholder](#leadingmarginplaceholder11) | No   | Indent of the paragraph. It has no effect if the paragraph starts with an image or builder span. If of the **Dimension** type, this parameter cannot be set in percentage. Default value: **{"size":["0.00px","0.00px"]}**<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1567| wordBreak<sup>12+</sup> |  [WordBreak](ts-appendix-enums.md#wordbreak11) | No   | Word break rule.<br>Default value: **WordBreak.BREAK_WORD**<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1568| lineBreakStrategy<sup>12+</sup> | [LineBreakStrategy](ts-appendix-enums.md#linebreakstrategy12) | No| Line break rule.<br>Default value: **LineBreakStrategy.GREEDY**<br>This parameter takes effect when **wordBreak** is not set to **breakAll**. Hyphens are not supported.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1569| paragraphSpacing<sup>18+</sup> | number | No   | Spacing between paragraphs.<br>Unit: fp<br>Default value: **0**<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
1570
1571## LeadingMarginPlaceholder<sup>11+</sup>
1572
1573Describes the leading margin placeholder, which dictates the distance between the left edges of the paragraph and the component.
1574
1575**System capability**: SystemCapability.ArkUI.ArkUI.Full
1576
1577| Name      | Type                                      | Mandatory  | Description            |
1578| -------- | ---------------------------------------- | ---- | -------------- |
1579| pixelMap | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7) | Yes   | Image content.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1580| size     | \[[Dimension](ts-types.md#dimension10), [Dimension](ts-types.md#dimension10)\] | Yes   | Image size. This parameter cannot be set in percentage.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1581
1582## RichEditorParagraphResult<sup>11+</sup>
1583
1584Describes the returned paragraph information.
1585
1586**Atomic service API**: This API can be used in atomic services since API version 12.
1587
1588**System capability**: SystemCapability.ArkUI.ArkUI.Full
1589
1590| Name   | Type                                      | Mandatory  | Description     |
1591| ----- | ---------------------------------------- | ---- | ------- |
1592| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | Yes   | Paragraph style.  |
1593| range | \[number, number\]                       | Yes   | Start and end positions of the paragraph.|
1594
1595## RichEditorTextSpanOptions
1596
1597Describes the options for adding a text span.
1598
1599**System capability**: SystemCapability.ArkUI.ArkUI.Full
1600
1601| Name                          | Type                                      | Mandatory  | Description                        |
1602| ---------------------------- | ---------------------------------------- | ---- | -------------------------- |
1603| offset                       | number                                   | No   | Position of the text span to be added. If this parameter is omitted, the paragraph is added to the end of all content.<br>If the value specified is less than 0, the paragraph is placed at the beginning of all content. If the value is greater than the length of all content, the paragraph is placed at the end of all content.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1604| style                        | [RichEditorTextStyle](#richeditortextstyle) | No   | Style of the text span to be added. If this parameter is left empty, the default text style will be used.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1605| paragraphStyle<sup>11+</sup> | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | No   | Paragraph style.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1606| gesture<sup>11+</sup>        | [RichEditorGesture](#richeditorgesture11) | No   | Behavior-triggered callback. If this parameter is left empty, only the default system behavior is supported.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1607| urlStyle<sup>18+</sup>  | [RichEditorUrlStyle](#richeditorurlstyle18)   | No  | URL information.<br>Default value: **undefined**<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
1608
1609## RichEditorTextStyle
1610
1611Provides the text style information.
1612
1613**System capability**: SystemCapability.ArkUI.ArkUI.Full
1614
1615| Name                      | Type                                      | Mandatory  | Description                                      |
1616| ------------------------ | ---------------------------------------- | ---- | ---------------------------------------- |
1617| fontColor                | [ResourceColor](ts-types.md#resourcecolor) | No   | Font color.<br> Default value: **$r('sys.color.font_primary')**<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1618| fontSize                 | [Length](ts-types.md#length) \| number            | No   | Font size. If **Length** is of the number type, the unit fp is used. The default value is **16**. The value cannot be a percentage. If the font size is set to 0, the default font size is used.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1619| fontStyle                | [FontStyle](ts-appendix-enums.md#fontstyle) | No   | Font style.<br>Default value: **FontStyle.Normal**<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1620| fontWeight               | number \|  [FontWeight](ts-appendix-enums.md#fontweight) \| string | No   | Font weight.<br>For the number type, the value ranges from 100 to 900, at an interval of 100. A larger value indicates a heavier font weight. The default value is **400**.<br>For the string type, only strings of the number type are supported, for example, **"400"**, **"bold"**, **"bolder"**, **"lighter"**, **"regular"**, and **"medium"**, which correspond to the enumerated values in **FontWeight**.<br>Default value: **FontWeight.Normal**<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1621| fontFamily               | [ResourceStr](ts-types.md#resourcestr) | No   | Font family. The HarmonyOS Sans font and [register custom fonts](../js-apis-font.md) are supported.<br>Default font: **'HarmonyOS Sans'**<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1622| decoration               | [DecorationStyleInterface](ts-universal-styled-string.md#decorationstyleinterface) | No   | Style and color of the text decorative line.<br>Default value of **type**: **TextDecorationType.None**<br>Default value of **color**: same as the font color<br>Default value of **style**: **TextDecorationStyle.SOLID**<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1623| textShadow<sup>11+</sup> | [ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions) \| Array&lt;[ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions)> | No   | Text shadow. It supports input parameters in an array to implement multiple text shadows.<br>**NOTE**<br>Only the shadow blur radius, shadow color, and shadow offset can be set.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1624| lineHeight<sup>12+</sup>    | number \| string \| [Resource](ts-types.md#resource) | No    |Text line height. If the value is less than or equal to 0, the line height is not limited and the font size is adaptive. If the value is of the number type, the unit fp is used. The value cannot be a percentage.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1625| letterSpacing<sup>12+</sup> | number \| string             | No    | Letter spacing. If the value is negative, the text is compressed. A negative value too small may result in the text being compressed to 0 and no content being displayed. If the value is of the number type, the unit fp is used. The value cannot be a percentage.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1626| fontFeature<sup>12+</sup> | string | No| Font feature, for example, monospaced digits. If this parameter is not set, monospaced digits are used as the default value. If invalid characters are set, the default value is retrained.<br>Format: normal \| \<feature-tag-value\><br>Syntax for \<feature-tag-value\>: \<string\> \[ \<integer\> \| on \| off ]<br>There can be multiple **\<feature-tag-value\>** values, which are separated by commas (,).<br>For example, the input format for monospaced clock fonts is "ss01" on.<br>For details about the supported font features, see [Font Feature List](ts-basic-components-text.md#fontfeature12).<br>Font features are advanced typographic features, such as ligatures and monospace, for OpenType fonts. They are typically used in custom fonts and require the support of the font itself.<br>For more information about the font features, see [Low-level font feature settings control: the font-feature-settings property](https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop) and [The Complete CSS Demo for OpenType Features](https://sparanoid.com/lab/opentype-features/).<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1627| halfLeading<sup>18+</sup> | boolean | No   | Whether half leading is enabled.<br>Half leading is the leading split in half and applied equally to the top and bottom edges. The value **true** means that half leading is enabled, and **false** means the opposite.<br>Default value: **false**<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
1628| textBackgroundStyle<sup>18+</sup> | [TextBackgroundStyle](ts-basic-components-span.md#textbackgroundstyle11) | No   | Text background style.<br>Default value:<br>{<br>  color: Color.Transparent,<br>  radius: 0<br>} |
1629
1630## PlaceholderStyle<sup>12+</sup>
1631
1632Defines the style of the placeholder text.
1633
1634**Atomic service API**: This API can be used in atomic services since API version 12.
1635
1636**System capability**: SystemCapability.ArkUI.ArkUI.Full
1637
1638| Name                          | Type                                      | Mandatory  | Description                        |
1639| ---------------------------- | ---------------------------------------- | ---- | -------------------------- |
1640| font                         | [Font](ts-types.md#font)                    | No   | Style of the placeholder text.<br>The default value follows the theme.|
1641| fontColor                    | [ResourceColor](ts-types.md#resourcecolor)  | No   | Color of the placeholder text.<br>The default value follows the theme.|
1642
1643## RichEditorImageSpanOptions
1644
1645Defines the options for adding an image span.
1646
1647**System capability**: SystemCapability.ArkUI.ArkUI.Full
1648
1649| Name                   | Type                                      | Mandatory  | Description                        |
1650| --------------------- | ---------------------------------------- | ---- | -------------------------- |
1651| offset                | number                                   | No   | Position of the image span to be added. If this parameter is omitted, the paragraph is added to the end of all content.<br>If the value specified is less than 0, the paragraph is placed at the beginning of all content. If the value is greater than the length of all content, the paragraph is placed at the end of all content.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1652| imageStyle            | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | No   | Image style. If this parameter is left empty, the default image style will be used.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1653| gesture<sup>11+</sup> | [RichEditorGesture](#richeditorgesture11) | No   | Behavior-triggered callback. If this parameter is left empty, only the default system behavior is supported.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
1654| onHover<sup>14+</sup> | [OnHoverCallback](#onhovercallback14) | No   | Callback triggered on mouse hover. If this parameter is not specified, no corresponding action is taken.<br>**Atomic service API**: This API can be used in atomic services since API version 14.|
1655
1656## RichEditorImageSpanStyle
1657
1658Provides the image span style information.
1659
1660**System capability**: SystemCapability.ArkUI.ArkUI.Full
1661
1662| Name                       | Type                                      | Mandatory  | Description                                      |
1663| ------------------------- | ---------------------------------------- | ---- | ---------------------------------------- |
1664| size                      | [[Dimension](ts-types.md#dimension10), [Dimension](ts-types.md#dimension10)] | No   | Width and height of the image. Default value: varies by the value of **objectFit**. If the value of **objectFit** is **Cover**, the image height is the component height minus the top and bottom paddings, and the image width is the component width minus the left and right paddings. Values using percentage notation are not supported.<br>**Atomic service API**: This API can be used in atomic services since API version 11.                              |
1665| verticalAlign             | [ImageSpanAlignment](ts-appendix-enums.md#imagespanalignment10)| No   | Vertical alignment mode of the image.<br>Default value: **ImageSpanAlignment.BOTTOM**<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1666| objectFit                 | [ImageFit](ts-appendix-enums.md#imagefit) | No   | Scale mode of the image.<br> Default value: **ImageFit.Cover**<br>**Atomic service API**: This API can be used in atomic services since API version 11.      |
1667| layoutStyle<sup>11+</sup> | [RichEditorLayoutStyle](#richeditorlayoutstyle11) | No   | Image layout style. Default value: **{"borderRadius":"","margin":""}**<br><br>**Atomic service API**: This API can be used in atomic services since API version 12.                         |
1668
1669## RichEditorSymbolSpanOptions<sup>11+</sup>
1670
1671Defines offset position for adding the symbol span and the symbol span style.
1672
1673**Atomic service API**: This API can be used in atomic services since API version 12.
1674
1675**System capability**: SystemCapability.ArkUI.ArkUI.Full
1676
1677| Name    | Type                                      | Mandatory  | Description                        |
1678| ------ | ---------------------------------------- | ---- | -------------------------- |
1679| offset | number                                   | No   | Position of the symbol span to be added. If this parameter is omitted, the span is added to the end of all content.<br>If the value specified is less than 0, the paragraph is placed at the beginning of all content. If the value is greater than the length of all content, the paragraph is placed at the end of all content.|
1680| style  | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | No   | Style of the symbol span to be added. If this parameter is left empty, the default style will be used.    |
1681
1682## RichEditorSymbolSpanStyle<sup>11+</sup>
1683
1684Provides the symbol span style information.
1685
1686**Atomic service API**: This API can be used in atomic services since API version 12.
1687
1688**System capability**: SystemCapability.ArkUI.ArkUI.Full
1689
1690| Name| Type| Mandatory| Description                              |
1691| ------ | -------- | ---- | -------------------------------------- |
1692| fontColor | Array\<[ResourceColor](ts-types.md#resourcecolor)\> | No| Color of the symbol span.<br> Default value: varies depending on the rendering strategy.|
1693| fontSize | number \| string \| [Resource](ts-types.md#resource) | No| Size of the symbol span. The default unit is fp.<br>The default value follows the theme.|
1694| fontWeight | number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string | No| Font weight of the symbol span.<br>For the number type, the value ranges from 100 to 900, at an interval of 100. A larger value indicates a heavier font weight. The default value is **400**.<br>For the string type, only strings of the number type are supported, for example, **"400"**, **"bold"**, **"bolder"**, **"lighter"**, **"regular"**, and **"medium"**, which correspond to the enumerated values in **FontWeight**.<br>Default value: **FontWeight.Normal**|
1695| renderingStrategy | [SymbolRenderingStrategy](ts-basic-components-symbolGlyph.md#symbolrenderingstrategy11)	| No| Rendering strategy of the symbol span.<br>Default value: **SymbolRenderingStrategy.SINGLE**|
1696| effectStrategy | [SymbolEffectStrategy](ts-basic-components-symbolGlyph.md#symboleffectstrategy11)	| No| Effect strategy of the symbol span.<br>Default value: **SymbolEffectStrategy.NONE**|
1697
1698## RichEditorBuilderSpanOptions<sup>11+</sup>
1699
1700Defines the options for adding a builder span.
1701
1702**Atomic service API**: This API can be used in atomic services since API version 12.
1703
1704**System capability**: SystemCapability.ArkUI.ArkUI.Full
1705
1706| Name    | Type    | Mandatory  | Description                                   |
1707| ------ | ------ | ---- | ------------------------------------- |
1708| offset | number | No   | Position of the builder span to be added. If this parameter is omitted or set to an invalid value, the span is added to the end of all content.|
1709
1710## RichEditorSpan<sup>12+</sup>
1711
1712type RichEditorSpan = RichEditorImageSpanResult | RichEditorTextSpanResult
1713
1714Provides the span information of the **RichEditor** component.
1715
1716**Atomic service API**: This API can be used in atomic services since API version 12.
1717
1718**System capability**: SystemCapability.ArkUI.ArkUI.Full
1719
1720| Type  | Description      |
1721| ------ | ---------- |
1722| [RichEditorImageSpanResult](#richeditorimagespanresult) | Provides the image information returned by the backend.|
1723| [RichEditorTextSpanResult](#richeditortextspanresult) | Provides the text span style information returned by the backend.|
1724
1725## SelectionMenuOptions<sup>10+</sup>
1726
1727Provides the options of the custom context menu on selection.
1728
1729**System capability**: SystemCapability.ArkUI.ArkUI.Full
1730
1731| Name         | Type        | Mandatory  | Description           |
1732| ----------- | ---------- | ---- | ------------- |
1733| onAppear    | [MenuOnAppearCallback](#menuonappearcallback12) | No   | Callback invoked when the custom context menu on selection appears.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1734| onDisappear | Callback\<void\>  | No   | Callback invoked when the custom context menu on selection disappears.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
1735| menuType<sup>13+</sup> | [MenuType](ts-text-common.md#menutype13) | No| Type of the custom context menu on selection.<br>**Atomic service API**: This API can be used in atomic services since API version 13.<br>Default value: **MenuType.SELECTION_MENU**|
1736| onMenuShow<sup>15+</sup> | [MenuCallback](#menucallback15) | No|  Callback invoked when the custom context menu on selection is shown.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
1737| onMenuHide<sup>15+</sup> | [MenuCallback](#menucallback15) | No|  Callback invoked when the custom context menu on selection is hidden.<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
1738| previewMenuOptions<sup>18+</sup> | [PreviewMenuOptions](#previewmenuoptions18) | No|  Options of the preview menu.<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
1739
1740## PreviewMenuOptions<sup>18+</sup>
1741
1742Defines the options of the preview menu.
1743
1744**Atomic service API**: This API can be used in atomic services since API version 18.
1745
1746**System capability**: SystemCapability.ArkUI.ArkUI.Full
1747
1748| Name         | Type        | Mandatory  | Description           |
1749| ----------- | ---------- | ---- | ------------- |
1750| hapticFeedbackMode | [HapticFeedbackMode](ts-universal-attributes-menu.md#hapticfeedbackmode18)| No| Vibration effect when the menu is displayed.<br>Default value: **HapticFeedbackMode.DISABLED** (no vibration when the menu is displayed)|
1751
1752## PasteEvent<sup>11+</sup>
1753
1754Defines a custom paste event.
1755
1756**Atomic service API**: This API can be used in atomic services since API version 11.
1757
1758**System capability**: SystemCapability.ArkUI.ArkUI.Full
1759
1760| Name            | Type         | Mandatory  | Description                           |
1761| -------------- | ----------- | ---- | ----------------------------- |
1762| preventDefault | Callback\<void\> | No   | Prevents the default paste event.|
1763
1764## CutEvent<sup>12+</sup>
1765
1766Defines a custom cut event.
1767
1768**Atomic service API**: This API can be used in atomic services since API version 12.
1769
1770**System capability**: SystemCapability.ArkUI.ArkUI.Full
1771
1772| Name            | Type         | Mandatory  | Description                           |
1773| -------------- | ----------- | ---- | ----------------------------- |
1774| preventDefault | Callback\<void\>  | No   | Prevents the default cut event.|
1775
1776## CopyEvent<sup>12+</sup>
1777
1778Defines a custom copy event.
1779
1780**Atomic service API**: This API can be used in atomic services since API version 12.
1781
1782**System capability**: SystemCapability.ArkUI.ArkUI.Full
1783
1784| Name            | Type         | Mandatory  | Description                           |
1785| -------------- | ----------- | ---- | ----------------------------- |
1786| preventDefault | Callback\<void\>  | No   | Prevents the default copy event.|
1787
1788## RichEditorGesture<sup>11+</sup>
1789
1790Defines the behavior-triggered callbacks.
1791
1792**Atomic service API**: This API can be used in atomic services since API version 12.
1793
1794**System capability**: SystemCapability.ArkUI.ArkUI.Full
1795
1796| Name         | Type        | Mandatory  | Description           |
1797| ----------- | ---------- | ---- | ------------- |
1798| onClick    | Callback\<[ClickEvent](ts-universal-events-click.md#clickevent)\>| No   | Triggered when the user performs a click.<br>It is executed on completion of a single click.<br>On a double-click, the first click triggers the callback event.|
1799| onLongPress | Callback\<[GestureEvent](ts-gesture-settings.md#gestureevent)\>  | No   | Triggered when the user performs a long press.<br>It is executed on completion of a long press.|
1800
1801## KeyboardOptions<sup>12+</sup>
1802
1803Sets whether to support keyboard avoidance.
1804
1805**Atomic service API**: This API can be used in atomic services since API version 12.
1806
1807**System capability**: SystemCapability.ArkUI.ArkUI.Full
1808
1809| Name           | Type             | Mandatory  | Description                              |
1810| --------------- | ---------------  |---- | ------------------------------------  |
1811| supportAvoidance |  boolean      | No| Whether to support keyboard avoidance. The value **true** means to support keyboard avoidance, and **false** (default) means the opposite.|
1812
1813## SubmitCallback<sup>12+</sup>
1814
1815type SubmitCallback = (enterKey: EnterKeyType, event: SubmitEvent) => void
1816
1817Represents the callback invoked when the Enter key on the soft keyboard is pressed.
1818
1819**Atomic service API**: This API can be used in atomic services since API version 12.
1820
1821**System capability**: SystemCapability.ArkUI.ArkUI.Full
1822
1823**Parameters**
1824
1825| Name  | Type                                                        | Mandatory| Description                                                    |
1826| -------- | ------------------------------------------------------------ | ---- | -------------------------------------------------------- |
1827| enterKey | [EnterKeyType](ts-basic-components-textinput.md#enterkeytype)             | Yes  | Type of the Enter key. For details, see **EnterKeyType**.|
1828| event    | [SubmitEvent](ts-basic-components-textinput.md#submitevent11) | Yes  | Submit event, which provides a method to keep the text box in editing state. When **EnterKeyType** is set to **NEW_LINE**, the editing state is retained by default.        |
1829
1830## MenuOnAppearCallback<sup>12+</sup>
1831
1832type MenuOnAppearCallback = (start: number, end: number) => void
1833
1834Represents the callback invoked when the custom context menu on selection appears.
1835
1836**Atomic service API**: This API can be used in atomic services since API version 12.
1837
1838**System capability**: SystemCapability.ArkUI.ArkUI.Full
1839
1840**Parameters**
1841
1842| Name | Type                                            | Mandatory| Description                                                    |
1843| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- |
1844| start | number | Yes  | Start position of the selected content.|
1845| end    | number         | Yes  | End position of the selected content.        |
1846
1847## MenuCallback<sup>15+</sup>
1848
1849type MenuCallback = (start: number, end: number) => void
1850
1851Represents the callback invoked when the custom context menu on selection is shown or hidden.
1852
1853**Atomic service API**: This API can be used in atomic services since API version 15.
1854
1855**System capability**: SystemCapability.ArkUI.ArkUI.Full
1856
1857**Parameters**
1858
1859| Name | Type                                            | Mandatory| Description                                                    |
1860| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- |
1861| start | number | Yes  | Start position of the selected content.|
1862| end    | number         | Yes  | End position of the selected content.        |
1863
1864## PasteEventCallback<sup>12+</sup>
1865
1866type PasteEventCallback = (event?: PasteEvent) => void
1867
1868Represents the callback invoked when the paste is about to be completed.
1869
1870**Atomic service API**: This API can be used in atomic services since API version 12.
1871
1872**System capability**: SystemCapability.ArkUI.ArkUI.Full
1873
1874**Parameters**
1875
1876| Name    | Type                                            | Mandatory| Description                                                    |
1877| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- |
1878| event  | [PasteEvent](#pasteevent11) | No  | User paste event.|
1879
1880## OnHoverCallback<sup>14+</sup>
1881
1882type OnHoverCallback = (status: boolean, event: HoverEvent) => void
1883
1884Represents the callback invoked on mouse hover.
1885
1886**Atomic service API**: This API can be used in atomic services since API version 14.
1887
1888**System capability**: SystemCapability.ArkUI.ArkUI.Full
1889
1890**Parameters**
1891
1892| Name    | Type                                            | Mandatory| Description                                                    |
1893| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- |
1894| status  | boolean                            | Yes  | Whether the mouse pointer is hovering over the component. The value **true** means that the mouse pointer enters the component, and **false** means that the mouse pointer leaves the component.|
1895| event   | [HoverEvent](ts-universal-events-hover.md#hoverevent10) | Yes  | Event bubbling.|
1896
1897## RichEditorTextSpan
1898
1899Provides the text span information.
1900
1901**Atomic service API**: This API can be used in atomic services since API version 11.
1902
1903**System capability**: SystemCapability.ArkUI.ArkUI.Full
1904
1905| Name                           | Type                                      | Mandatory  | Description                    |
1906| ----------------------------- | ---------------------------------------- | ---- | ---------------------- |
1907| spanPosition                  | [RichEditorSpanPosition](#richeditorspanposition) | Yes   | Span position.|
1908| value                         | string                                   | Yes   | Text span content.|
1909| textStyle                     | [RichEditorTextStyle](#richeditortextstyle) | No   | Text span style.|
1910
1911## RichEditorImageSpan
1912
1913Image span information.
1914
1915**Atomic service API**: This API can be used in atomic services since API version 11.
1916
1917**System capability**: SystemCapability.ArkUI.ArkUI.Full
1918
1919| Name              | Type                                                               | Mandatory | Description              |
1920|------------------|-------------------------------------------------------------------|-----|------------------|
1921| spanPosition     | [RichEditorSpanPosition](#richeditorspanposition)                 | Yes  | Span position.|
1922| value            | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)\|[ResourceStr](ts-types.md#resourcestr)  | Yes  | Image content.|
1923| imageStyle       | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | No| Image style.|
1924
1925## RichEditorUrlStyle<sup>18+</sup>
1926
1927URL information.
1928
1929**Atomic service API**: This API can be used in atomic services since API version 18.
1930
1931**System capability**: SystemCapability.ArkUI.ArkUI.Full
1932
1933| Name   | Type                                        | Mandatory| Description   |
1934|---------|---------------------------------------------|------|---------|
1935| url     | [ResourceStr](ts-types.md#resourcestr)      | No  | URL.<br>Default value: **undefined**|
1936
1937## Example
1938
1939### Example 1: Updating the Text Style
1940This example demonstrates how to update the text style using the [updateSpanStyle](#updatespanstyle) API. After modifying the style, you can use [getSpans](#getspans) to obtain the updated style information of the text.
1941
1942```ts
1943// xxx.ets
1944@Entry
1945@Component
1946struct Index {
1947  controller: RichEditorController = new RichEditorController();
1948  options: RichEditorOptions = { controller: this.controller };
1949  private start: number = -1;
1950  private end: number = -1;
1951  @State message: string = "[-1, -1]"
1952  @State content: string = ""
1953
1954  build() {
1955    Column() {
1956      Column() {
1957        Text("selection range:").width("100%")
1958        Text() {
1959          Span(this.message)
1960        }.width("100%")
1961        Text("selection content:").width("100%")
1962        Text() {
1963          Span(this.content)
1964        }.width("100%")
1965      }
1966      .borderWidth(1)
1967      .borderColor(Color.Red)
1968      .width("100%")
1969      .height("20%")
1970
1971      Row() {
1972        Button("Update Style: Bold").onClick(() => {
1973          this.controller.updateSpanStyle({
1974            start: this.start,
1975            end: this.end,
1976            textStyle:
1977            {
1978              fontWeight: FontWeight.Bolder
1979            }
1980          })
1981        })
1982        Button("Obtain Selection").onClick(() => {
1983          this.content = "";
1984          this.controller.getSpans({
1985            start: this.start,
1986            end: this.end
1987          }).forEach(item => {
1988            if(typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined'){
1989              this.content += (item as RichEditorImageSpanResult).valueResourceStr;
1990              this.content += "\n"
1991            } else {
1992              if(typeof(item as RichEditorTextSpanResult)['symbolSpanStyle'] != 'undefined') {
1993                this.content += (item as RichEditorTextSpanResult).symbolSpanStyle?.fontSize;
1994                this.content += "\n"
1995              }else {
1996                this.content += (item as RichEditorTextSpanResult).value;
1997                this.content += "\n"
1998              }
1999            }
2000          })
2001        })
2002        Button("Delete Selection").onClick(() => {
2003          this.controller.deleteSpans({
2004            start: this.start,
2005            end: this.end
2006          })
2007          this.start = -1;
2008          this.end = -1;
2009          this.message = "[" + this.start + ", " + this.end + "]"
2010        })
2011      }
2012      .borderWidth(1)
2013      .borderColor(Color.Red)
2014      .width("100%")
2015      .height("10%")
2016
2017      Column() {
2018        RichEditor(this.options)
2019          .onReady(() => {
2020            this.controller.addTextSpan("012345",
2021              {
2022                style:
2023                {
2024                  fontColor: Color.Orange,
2025                  fontSize: 30
2026                }
2027              })
2028            this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"),
2029              {
2030                style:
2031                {
2032                  fontSize: 30
2033                }
2034              })
2035            this.controller.addImageSpan($r("app.media.icon"),
2036              {
2037                imageStyle:
2038                {
2039                  size: ["57px", "57px"]
2040                }
2041              })
2042            this.controller.addTextSpan("56789",
2043              {
2044                style:
2045                {
2046                  fontColor: Color.Black,
2047                  fontSize: 30
2048                }
2049              })
2050          })
2051          .onSelect((value: RichEditorSelection) => {
2052            this.start = value.selection[0];
2053            this.end = value.selection[1];
2054            this.message = "[" + this.start + ", " + this.end + "]"
2055          })
2056          .aboutToIMEInput((value: RichEditorInsertValue) => {
2057            console.log("---------------------- aboutToIMEInput ----------------------")
2058            console.log("insertOffset:" + value.insertOffset)
2059            console.log("insertValue:" + value.insertValue)
2060            return true;
2061          })
2062          .onIMEInputComplete((value: RichEditorTextSpanResult) => {
2063            console.log("---------------------- onIMEInputComplete ---------------------")
2064            console.log("spanIndex:" + value.spanPosition.spanIndex)
2065            console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]")
2066            console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]")
2067            console.log("value:" + value.value)
2068          })
2069          .aboutToDelete((value: RichEditorDeleteValue) => {
2070            console.log("---------------------- aboutToDelete --------------------------")
2071            console.log("offset:" + value.offset)
2072            console.log("direction:" + value.direction)
2073            console.log("length:" + value.length)
2074            value.richEditorDeleteSpans.forEach(item => {
2075              console.log("---------------------- item --------------------------")
2076              console.log("spanIndex:" + item.spanPosition.spanIndex)
2077              console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]")
2078              console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]")
2079              if (typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
2080                console.log("image:" + (item as RichEditorImageSpanResult).valueResourceStr)
2081              } else {
2082                console.log("text:" + (item as RichEditorTextSpanResult).value)
2083              }
2084            })
2085            return true;
2086          })
2087          .onDeleteComplete(() => {
2088            console.log("---------------------- onDeleteComplete ------------------------")
2089          })
2090          .placeholder("input...", {
2091            fontColor: Color.Gray,
2092            font: {
2093              size: 16,
2094              weight: FontWeight.Normal,
2095              family: "HarmonyOS Sans",
2096              style: FontStyle.Normal
2097            }
2098          })
2099          .borderWidth(1)
2100          .borderColor(Color.Green)
2101          .width("100%")
2102          .height("30%")
2103      }
2104      .borderWidth(1)
2105      .borderColor(Color.Red)
2106      .width("100%")
2107      .height("70%")
2108    }
2109  }
2110}
2111```
2112![richeditor](figures/richeditor.gif)
2113
2114### Example 2: Binding a Custom Keyboard
2115This example shows how to bind a custom keyboard to the component using [customKeyboard](#customkeyboard).
2116
2117```ts
2118// xxx.ets
2119@Entry
2120@Component
2121struct RichEditorExample {
2122  controller: RichEditorController = new RichEditorController()
2123
2124  // Create a custom keyboard component.
2125  @Builder CustomKeyboardBuilder() {
2126    Column() {
2127      Grid() {
2128        ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => {
2129          GridItem() {
2130            Button(item + "")
2131              .width(110).onClick(() => {
2132              this.controller.addTextSpan(item + '', {
2133                offset: this.controller.getCaretOffset(),
2134                style:
2135                {
2136                  fontColor: Color.Orange,
2137                  fontSize: 30
2138                }
2139              })
2140              this.controller.setCaretOffset(this.controller.getCaretOffset() + item.toString().length)
2141            })
2142          }
2143        })
2144      }.maxCount(3).columnsGap(10).rowsGap(10).padding(5)
2145    }.backgroundColor(Color.Gray)
2146  }
2147
2148  build() {
2149    Column() {
2150      RichEditor({ controller: this.controller })
2151        // Bind the custom keyboard.
2152        .customKeyboard(this.CustomKeyboardBuilder()).margin(10).border({ width: 1 })
2153        .height(200)
2154        .borderWidth(1)
2155        .borderColor(Color.Red)
2156        .width("100%")
2157    }
2158  }
2159}
2160```
2161
2162![customKeyboard](figures/richEditorCustomKeyboard.gif)
2163
2164### Example 3: Binding a Custom Menu
2165This example illustrates how to bind a custom menu to the component using [bindSelectionMenu](#bindselectionmenu).
2166
2167```ts
2168// xxx.ets
2169import { BusinessError, pasteboard } from '@kit.BasicServicesKit';
2170
2171export interface SelectionMenuTheme {
2172  imageSize: number;
2173  buttonSize: number;
2174  menuSpacing: number;
2175  editorOptionMargin: number;
2176  expandedOptionPadding: number;
2177  defaultMenuWidth: number;
2178  imageFillColor: Resource;
2179  backGroundColor: Resource;
2180  iconBorderRadius: Resource;
2181  containerBorderRadius: Resource;
2182  cutIcon: Resource;
2183  copyIcon: Resource;
2184  pasteIcon: Resource;
2185  selectAllIcon: Resource;
2186  shareIcon: Resource;
2187  translateIcon: Resource;
2188  searchIcon: Resource;
2189  arrowDownIcon: Resource;
2190  iconPanelShadowStyle: ShadowStyle;
2191  iconFocusBorderColor: Resource;
2192}
2193
2194export const defaultTheme: SelectionMenuTheme = {
2195  imageSize: 24,
2196  buttonSize: 48,
2197  menuSpacing: 8,
2198  editorOptionMargin: 1,
2199  expandedOptionPadding: 3,
2200  defaultMenuWidth: 256,
2201  imageFillColor: $r('sys.color.ohos_id_color_primary'),
2202  backGroundColor: $r('sys.color.ohos_id_color_dialog_bg'),
2203  iconBorderRadius: $r('sys.float.ohos_id_corner_radius_default_m'),
2204  containerBorderRadius: $r('sys.float.ohos_id_corner_radius_card'),
2205  cutIcon: $r("sys.media.ohos_ic_public_cut"),
2206  copyIcon: $r("sys.media.ohos_ic_public_copy"),
2207  pasteIcon: $r("sys.media.ohos_ic_public_paste"),
2208  selectAllIcon: $r("sys.media.ohos_ic_public_select_all"),
2209  shareIcon: $r("sys.media.ohos_ic_public_share"),
2210  translateIcon: $r("sys.media.ohos_ic_public_translate_c2e"),
2211  searchIcon: $r("sys.media.ohos_ic_public_search_filled"),
2212  arrowDownIcon: $r("sys.media.ohos_ic_public_arrow_down"),
2213  iconPanelShadowStyle: ShadowStyle.OUTER_DEFAULT_MD,
2214  iconFocusBorderColor: $r('sys.color.ohos_id_color_focused_outline'),
2215}
2216
2217@Entry
2218@Component
2219struct SelectionMenu {
2220  @State message: string = 'Hello World'
2221  @State textSize: number = 40
2222  @State sliderShow: boolean = false
2223  @State start: number = -1
2224  @State end: number = -1
2225  @State colorTransparent: Color = Color.Transparent
2226  controller: RichEditorController = new RichEditorController();
2227  options: RichEditorOptions = { controller: this.controller }
2228  private iconArr: Array<Resource> =
2229    [$r('app.media.icon'), $r("app.media.icon"), $r('app.media.icon'),
2230    $r("app.media.icon"), $r('app.media.icon')]
2231  @State iconBgColor: ResourceColor[] = new Array(this.iconArr.length).fill(this.colorTransparent)
2232  @State pasteEnable: boolean = false
2233  @State visibilityValue: Visibility = Visibility.Visible
2234  @State textStyle: RichEditorTextStyle = {}
2235  private fontWeightTable: string[] = ["100", "200", "300", "400", "500", "600", "700", "800", "900", "bold", "normal", "bolder", "lighter", "medium", "regular"]
2236  private theme: SelectionMenuTheme = defaultTheme;
2237
2238  aboutToAppear() {
2239    if (this.controller) {
2240      let richEditorSelection = this.controller.getSelection()
2241      if (richEditorSelection) {
2242        let start = richEditorSelection.selection[0]
2243        let end = richEditorSelection.selection[1]
2244        if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) {
2245          this.visibilityValue = Visibility.None
2246        } else {
2247          this.visibilityValue = Visibility.Visible
2248        }
2249      }
2250    }
2251    let sysBoard = pasteboard.getSystemPasteboard()
2252    if (sysBoard && sysBoard.hasDataSync()) {
2253      this.pasteEnable = true
2254    } else {
2255      this.pasteEnable = false
2256    }
2257  }
2258
2259  build() {
2260    Column() {
2261      Column() {
2262        RichEditor(this.options)
2263          .onReady(() => {
2264            this.controller.addTextSpan(this.message, { style: { fontColor: Color.Orange, fontSize: 30 } })
2265          })
2266          .onSelect((value: RichEditorSelection) => {
2267            if (value.selection[0] == -1 && value.selection[1] == -1) {
2268              return
2269            }
2270            this.start = value.selection[0]
2271            this.end = value.selection[1]
2272          })
2273          .bindSelectionMenu(RichEditorSpanType.TEXT, this.panel, ResponseType.LongPress, { onDisappear: () => {
2274            this.sliderShow = false
2275          }})
2276          .bindSelectionMenu(RichEditorSpanType.TEXT, this.panel, ResponseType.RightClick, { onDisappear: () => {
2277            this.sliderShow = false
2278          }})
2279          .borderWidth(1)
2280          .borderColor(Color.Red)
2281          .width(200)
2282          .height(200)
2283      }.width('100%').backgroundColor(Color.White)
2284    }.height('100%')
2285  }
2286
2287  PushDataToPasteboard(richEditorSelection: RichEditorSelection) {
2288    let sysBoard = pasteboard.getSystemPasteboard()
2289    let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, '')
2290    if (richEditorSelection.spans && richEditorSelection.spans.length > 0) {
2291      let count = richEditorSelection.spans.length
2292      for (let i = count - 1; i >= 0; i--) {
2293        let item = richEditorSelection.spans[i]
2294        if ((item as RichEditorTextSpanResult)?.textStyle) {
2295          let span = item as RichEditorTextSpanResult
2296          let style = span.textStyle
2297          let data = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_PLAIN, span.value.substring(span.offsetInSpan[0], span.offsetInSpan[1]))
2298          let prop = pasteData.getProperty()
2299          let temp: Record<string, Object> = {
2300            'color': style.fontColor,
2301            'size': style.fontSize,
2302            'style': style.fontStyle,
2303            'weight': this.fontWeightTable[style.fontWeight],
2304            'fontFamily': style.fontFamily,
2305            'decorationType': style.decoration.type,
2306            'decorationColor': style.decoration.color
2307          }
2308          prop.additions[i] = temp;
2309          pasteData.addRecord(data)
2310          pasteData.setProperty(prop)
2311        }
2312      }
2313    }
2314    sysBoard.clearData()
2315    sysBoard.setData(pasteData).then(() => {
2316      console.info('SelectionMenu copy option, Succeeded in setting PasteData.');
2317      this.pasteEnable = true;
2318    }).catch((err: BusinessError) => {
2319      console.error('SelectionMenu copy option, Failed to set PasteData. Cause:' + err.message);
2320    })
2321  }
2322
2323  PopDataFromPasteboard(richEditorSelection: RichEditorSelection) {
2324    let start = richEditorSelection.selection[0]
2325    let end = richEditorSelection.selection[1]
2326    if (start == end && this.controller) {
2327      start = this.controller.getCaretOffset()
2328      end = this.controller.getCaretOffset()
2329    }
2330    let moveOffset = 0
2331    let sysBoard = pasteboard.getSystemPasteboard()
2332    sysBoard.getData((err, data) => {
2333      if (err) {
2334        return
2335      }
2336      let count = data.getRecordCount()
2337      for (let i = 0; i < count; i++) {
2338        const element = data.getRecord(i);
2339        let tex: RichEditorTextStyle = {
2340          fontSize: 16,
2341          fontColor: Color.Black,
2342          fontWeight: FontWeight.Normal,
2343          fontFamily: "HarmonyOS Sans",
2344          fontStyle: FontStyle.Normal,
2345          decoration: { type: TextDecorationType.None, color: "#FF000000", style: TextDecorationStyle.SOLID }
2346        }
2347        if (data.getProperty() && data.getProperty().additions[i]) {
2348          const tmp = data.getProperty().additions[i] as Record<string, Object | undefined>;
2349          if (tmp.color) {
2350            tex.fontColor = tmp.color as ResourceColor;
2351          }
2352          if (tmp.size) {
2353            tex.fontSize = tmp.size as Length | number;
2354          }
2355          if (tmp.style) {
2356            tex.fontStyle = tmp.style as FontStyle;
2357          }
2358          if (tmp.weight) {
2359            tex.fontWeight = tmp.weight as number | FontWeight | string;
2360          }
2361          if (tmp.fontFamily) {
2362            tex.fontFamily = tmp.fontFamily as ResourceStr;
2363          }
2364          if (tmp.decorationType && tex.decoration) {
2365            tex.decoration.type = tmp.decorationType as TextDecorationType;
2366          }
2367          if (tmp.decorationColor && tex.decoration) {
2368            tex.decoration.color = tmp.decorationColor as ResourceColor;
2369          }
2370          if (tex.decoration) {
2371            tex.decoration = { type: tex.decoration.type, color: tex.decoration.color }
2372          }
2373        }
2374        if (element && element.plainText && element.mimeType === pasteboard.MIMETYPE_TEXT_PLAIN && this.controller) {
2375          this.controller.addTextSpan(element.plainText,
2376            {
2377              style: tex,
2378              offset: start + moveOffset
2379            }
2380          )
2381          moveOffset += element.plainText.length
2382        }
2383      }
2384      if (this.controller) {
2385        this.controller.setCaretOffset(start + moveOffset)
2386        this.controller.closeSelectionMenu()
2387      }
2388      if (start != end && this.controller) {
2389        this.controller.deleteSpans({ start: start + moveOffset, end: end + moveOffset })
2390      }
2391    })
2392  }
2393
2394  @Builder
2395  panel() {
2396    Column() {
2397      this.iconPanel()
2398      if (!this.sliderShow) {
2399        this.SystemMenu()
2400      } else {
2401        this.sliderPanel()
2402      }
2403    }.width(256)
2404  }
2405
2406  @Builder iconPanel() {
2407    Column() {
2408      Row({ space: 2 }) {
2409        ForEach(this.iconArr, (item:Resource, index ?: number) => {
2410          Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
2411            Image(item).fillColor(this.theme.imageFillColor).width(24).height(24).focusable(true).draggable(false)
2412          }
2413          .borderRadius(this.theme.iconBorderRadius)
2414          .width(this.theme.buttonSize)
2415          .height(this.theme.buttonSize)
2416          .onClick(() => {
2417            if (index as number == 0) {
2418              this.sliderShow = false
2419              if (this.controller) {
2420                let selection = this.controller.getSelection();
2421                let spans = selection.spans
2422                spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => {
2423                  if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') {
2424                    let span = item as RichEditorTextSpanResult
2425                    this.textStyle = span.textStyle
2426                    let start = span.offsetInSpan[0]
2427                    let end = span.offsetInSpan[1]
2428                    let offset = span.spanPosition.spanRange[0]
2429                    if (this.textStyle.fontWeight != 11) {
2430                      this.textStyle.fontWeight = FontWeight.Bolder
2431                    } else {
2432                      this.textStyle.fontWeight = FontWeight.Normal
2433                    }
2434                    this.controller.updateSpanStyle({
2435                      start: offset + start,
2436                      end: offset + end,
2437                      textStyle: this.textStyle
2438                    })
2439                  }
2440                })
2441              }
2442            } else if (index as number == 1) {
2443              this.sliderShow = false
2444              if (this.controller) {
2445                let selection = this.controller.getSelection();
2446                let spans = selection.spans
2447                spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => {
2448                  if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') {
2449                    let span = item as RichEditorTextSpanResult
2450                    this.textStyle = span.textStyle
2451                    let start = span.offsetInSpan[0]
2452                    let end = span.offsetInSpan[1]
2453                    let offset = span.spanPosition.spanRange[0]
2454                    if (this.textStyle.fontStyle == FontStyle.Italic) {
2455                      this.textStyle.fontStyle = FontStyle.Normal
2456                    } else {
2457                      this.textStyle.fontStyle = FontStyle.Italic
2458                    }
2459                    this.controller.updateSpanStyle({
2460                      start: offset + start,
2461                      end: offset + end,
2462                      textStyle: this.textStyle
2463                    })
2464                  }
2465                })
2466              }
2467            } else if (index as number == 2) {
2468              this.sliderShow = false
2469              if (this.controller) {
2470                let selection = this.controller.getSelection();
2471                let spans = selection.spans
2472                spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => {
2473                  if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') {
2474                    let span = item as RichEditorTextSpanResult
2475                    this.textStyle = span.textStyle
2476                    let start = span.offsetInSpan[0]
2477                    let end = span.offsetInSpan[1]
2478                    let offset = span.spanPosition.spanRange[0]
2479                    if (this.textStyle.decoration) {
2480                      if (this.textStyle.decoration.type == TextDecorationType.Underline) {
2481                        this.textStyle.decoration.type = TextDecorationType.None
2482                      } else {
2483                        this.textStyle.decoration.type = TextDecorationType.Underline
2484                      }
2485                    } else {
2486                      this.textStyle.decoration = { type: TextDecorationType.Underline, color: Color.Black, style: TextDecorationStyle.SOLID }
2487                    }
2488                    this.controller.updateSpanStyle({
2489                      start: offset + start,
2490                      end: offset + end,
2491                      textStyle: this.textStyle
2492                    })
2493                  }
2494                })
2495              }
2496            } else if (index as number == 3) {
2497              this.sliderShow = !this.sliderShow
2498            } else if (index as number == 4) {
2499              this.sliderShow = false
2500              if (this.controller) {
2501                let selection = this.controller.getSelection();
2502                let spans = selection.spans
2503                spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => {
2504                  if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') {
2505                    let span = item as RichEditorTextSpanResult
2506                    this.textStyle = span.textStyle
2507                    let start = span.offsetInSpan[0]
2508                    let end = span.offsetInSpan[1]
2509                    let offset = span.spanPosition.spanRange[0]
2510                    if (this.textStyle.fontColor == Color.Orange || this.textStyle.fontColor == '#FFFFA500') {
2511                      this.textStyle.fontColor = Color.Black
2512                    } else {
2513                      this.textStyle.fontColor = Color.Orange
2514                    }
2515                    this.controller.updateSpanStyle({
2516                      start: offset + start,
2517                      end: offset + end,
2518                      textStyle: this.textStyle
2519                    })
2520                  }
2521                })
2522              }
2523            }
2524          })
2525          .onTouch((event?: TouchEvent | undefined) => {
2526            if(event != undefined){
2527              if (event.type === TouchType.Down) {
2528                this.iconBgColor[index as number] = $r('sys.color.ohos_id_color_click_effect')
2529              }
2530              if (event.type === TouchType.Up) {
2531                this.iconBgColor[index as number] = this.colorTransparent
2532              }
2533            }
2534          })
2535          .onHover((isHover?: boolean, event?: HoverEvent) => {
2536            this.iconBgColor.forEach((icon:ResourceColor, index1) => {
2537              this.iconBgColor[index1] = this.colorTransparent
2538            })
2539            if(isHover != undefined) {
2540              this.iconBgColor[index as number] = $r('sys.color.ohos_id_color_hover')
2541            }
2542          })
2543          .backgroundColor(this.iconBgColor[index as number])
2544        })
2545      }
2546    }
2547    .clip(true)
2548    .width(this.theme.defaultMenuWidth)
2549    .padding(this.theme.expandedOptionPadding)
2550    .borderRadius(this.theme.containerBorderRadius)
2551    .margin({ bottom: this.theme.menuSpacing })
2552    .backgroundColor(this.theme.backGroundColor)
2553    .shadow(this.theme.iconPanelShadowStyle)
2554  }
2555
2556  @Builder
2557  SystemMenu() {
2558    Column() {
2559      Menu() {
2560        if (this.controller) {
2561          MenuItemGroup() {
2562            MenuItem({ startIcon: this.theme.cutIcon, content: "Cut", labelInfo: "Ctrl+X" })
2563              .onClick(() => {
2564                if (!this.controller) {
2565                  return
2566                }
2567                let richEditorSelection = this.controller.getSelection()
2568                this.PushDataToPasteboard(richEditorSelection);
2569                this.controller.deleteSpans({
2570                  start: richEditorSelection.selection[0],
2571                  end: richEditorSelection.selection[1]
2572                })
2573              })
2574            MenuItem({ startIcon: this.theme.copyIcon, content: "Copy", labelInfo: "Ctrl+C" })
2575              .onClick(() => {
2576                if (!this.controller) {
2577                  return
2578                }
2579                let richEditorSelection = this.controller.getSelection()
2580                this.PushDataToPasteboard(richEditorSelection);
2581                this.controller.closeSelectionMenu()
2582              })
2583            MenuItem({ startIcon: this.theme.pasteIcon, content: "Paste", labelInfo: "Ctrl+V" })
2584              .enabled(this.pasteEnable)
2585              .onClick(() => {
2586                if (!this.controller) {
2587                  return
2588                }
2589                let richEditorSelection = this.controller.getSelection()
2590                this.PopDataFromPasteboard(richEditorSelection)
2591              })
2592            MenuItem({ startIcon: this.theme.selectAllIcon, content: "Select all", labelInfo: "Ctrl+A" })
2593              .visibility(this.visibilityValue)
2594              .onClick(() => {
2595                if (!this.controller) {
2596                  return
2597                }
2598                this.controller.setSelection(-1, -1)
2599                this.visibilityValue = Visibility.None
2600              })
2601            MenuItem({ startIcon: this.theme.shareIcon, content: "Share", labelInfo: "" })
2602              .enabled(false)
2603            MenuItem({ startIcon: this.theme.translateIcon, content: "Translate", labelInfo: "" })
2604              .enabled(false)
2605            MenuItem({ startIcon: this.theme.searchIcon, content: "Search", labelInfo: "" })
2606              .enabled(false)
2607          }
2608        }
2609      }
2610      .onVisibleAreaChange([0.0, 1.0], () => {
2611        if (!this.controller) {
2612          return
2613        }
2614        let richEditorSelection = this.controller.getSelection()
2615        let start = richEditorSelection.selection[0]
2616        let end = richEditorSelection.selection[1]
2617        if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) {
2618          this.visibilityValue = Visibility.None
2619        } else {
2620          this.visibilityValue = Visibility.Visible
2621        }
2622      })
2623      .radius(this.theme.containerBorderRadius)
2624      .clip(true)
2625      .backgroundColor(Color.White)
2626      .width(this.theme.defaultMenuWidth)
2627    }
2628    .width(this.theme.defaultMenuWidth)
2629  }
2630
2631  @Builder sliderPanel() {
2632    Column() {
2633      Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
2634        Text('A').fontSize(15)
2635        Slider({ value: this.textSize, step: 10, style: SliderStyle.InSet })
2636          .width(210)
2637          .onChange((value: number, mode: SliderChangeMode) => {
2638            if (this.controller) {
2639              let selection = this.controller.getSelection();
2640              if (mode == SliderChangeMode.End) {
2641                if (this.textSize == undefined) {
2642                  this.textSize = 0
2643                }
2644                let spans = selection.spans
2645                spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => {
2646                  if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') {
2647                    this.textSize = Math.max(this.textSize, (item as RichEditorTextSpanResult).textStyle.fontSize)
2648                  }
2649                })
2650              }
2651              if (mode == SliderChangeMode.Moving || mode == SliderChangeMode.Click) {
2652                this.start = selection.selection[0]
2653                this.end = selection.selection[1]
2654                this.textSize = value
2655                this.controller.updateSpanStyle({
2656                  start: this.start,
2657                  end: this.end,
2658                  textStyle: { fontSize: this.textSize }
2659                })
2660              }
2661            }
2662          })
2663        Text('A').fontSize(20).fontWeight(FontWeight.Medium)
2664      }.borderRadius(this.theme.containerBorderRadius)
2665    }
2666    .shadow(ShadowStyle.OUTER_DEFAULT_MD)
2667    .backgroundColor(Color.White)
2668    .borderRadius(this.theme.containerBorderRadius)
2669    .padding(15)
2670    .height(48)
2671  }
2672}
2673```
2674> **NOTE**
2675>
2676> Icons in bold and italics are not preset in the system. The sample code uses the default icons. You need to replace the icons in **iconArr** with the desired icons.
2677
2678![selectionMenu](figures/richEditorSelectionMenu.png)
2679
2680### Example 4: Updating the Image Style
2681This example demonstrates how to update the image style using the [updateSpanStyle](#updatespanstyle) API.
2682
2683```ts
2684// xxx.ets
2685@Entry
2686@Component
2687struct Index {
2688  controller: RichEditorController = new RichEditorController();
2689  options: RichEditorOptions = { controller: this.controller };
2690  private start: number = -1;
2691  private end: number = -1;
2692  @State message: string = "[-1, -1]"
2693  @State content: string = ""
2694  @State paddingVal: number = 5
2695  @State borderRad: number = 4
2696
2697  build() {
2698    Column() {
2699      Column() {
2700        Text("selection range:").width("100%")
2701        Text() {
2702          Span(this.message)
2703        }.width("100%")
2704        Text("selection content:").width("100%")
2705        Text() {
2706          Span(this.content)
2707        }.width("100%")
2708      }
2709      .borderWidth(1)
2710      .borderColor(Color.Red)
2711      .width("100%")
2712      .height("20%")
2713
2714      Row() {
2715        Button("updateSpanStyle1")
2716          .fontSize(12)
2717          .onClick(() => {
2718            this.controller.updateSpanStyle({
2719              start: this.start,
2720              textStyle:
2721              {
2722                fontWeight: FontWeight.Bolder
2723              },
2724              imageStyle: {
2725                size: ["80px", "80px"],
2726                layoutStyle: {
2727                  borderRadius: undefined,
2728                  margin: undefined
2729                }
2730              }
2731            })
2732          })
2733
2734        Button("updateSpanStyle2")
2735          .fontSize(12)
2736          .onClick(() => {
2737            this.controller.updateSpanStyle({
2738              start: this.start,
2739              textStyle:
2740              {
2741                fontWeight: FontWeight.Bolder
2742              },
2743              imageStyle: {
2744                size: ["70px", "70px"],
2745                layoutStyle: {
2746                  borderRadius: { topLeft: '100px', topRight: '20px', bottomLeft: '100px', bottomRight: '20px' },
2747                  margin: { left: '30px', top: '20px', right: '20px', bottom: '20px' }
2748                }
2749              }
2750            })
2751          })
2752
2753        Button("updateSpanStyle3")
2754          .fontSize(12)
2755          .onClick(() => {
2756            this.controller.updateSpanStyle({
2757              start: this.start,
2758              textStyle:
2759              {
2760                fontWeight: FontWeight.Bolder
2761              },
2762              imageStyle: {
2763                size: ["60px", "60px"],
2764                layoutStyle: {
2765                  borderRadius: '-10px',
2766                  margin: '-10px'
2767                }
2768              }
2769            })
2770          })
2771      }
2772      .borderWidth(1)
2773      .borderColor(Color.Red)
2774      .width("100%")
2775      .height("10%")
2776
2777      Row() {
2778        Button('addImageSpan1')
2779          .fontSize(12)
2780          .onClick(() => {
2781            this.controller.addImageSpan($r('app.media.app_icon'), {
2782              imageStyle: {
2783                size: ["80px", "80px"],
2784                layoutStyle: {
2785                  borderRadius: '50px',
2786                  margin: '40px'
2787                }
2788              }
2789            })
2790          })
2791
2792        Button('addImageSpan2')
2793          .fontSize(12)
2794          .onClick(() => {
2795            this.controller.addImageSpan($r('app.media.app_icon'), {
2796              imageStyle: {
2797                size: ["100px", "100px"],
2798                verticalAlign: ImageSpanAlignment.BOTTOM,
2799                layoutStyle: {
2800                  borderRadius: undefined,
2801                  margin: undefined
2802                }
2803              }
2804            })
2805          })
2806
2807        Button('addImageSpan3')
2808          .fontSize(12)
2809          .onClick(() => {
2810            this.controller.addImageSpan($r('app.media.app_icon'), {
2811              imageStyle: {
2812                size: ["60px", "60px"],
2813                verticalAlign: ImageSpanAlignment.BOTTOM,
2814                layoutStyle: {
2815                  borderRadius: { topLeft: '10px', topRight: '20px', bottomLeft: '30px', bottomRight: '40px' },
2816                  margin: { left: '10px', top: '20px', right: '30px', bottom: '40px' }
2817                }
2818              }
2819            })
2820          })
2821      }
2822      .borderWidth(1)
2823      .borderColor(Color.Red)
2824      .width("100%")
2825      .height("10%")
2826
2827      Column() {
2828        RichEditor(this.options)
2829          .onReady(() => {
2830            this.controller.addTextSpan("0123456789",
2831              {
2832                style:
2833                {
2834                  fontColor: Color.Orange,
2835                  fontSize: 30
2836                }
2837              })
2838
2839            this.controller.addImageSpan($r("app.media.app_icon"),
2840              {
2841                imageStyle:
2842                {
2843                  size: ["60px", "60px"],
2844                  verticalAlign: ImageSpanAlignment.BOTTOM,
2845                  layoutStyle: {
2846                    borderRadius: { topLeft: '10px', topRight: '20px', bottomLeft: '30px', bottomRight: '40px' },
2847                    margin: { left: '10px', top: '20px', right: '30px', bottom: '40px' }
2848                  }
2849                }
2850              })
2851
2852            this.controller.addTextSpan("0123456789",
2853              {
2854                style:
2855                {
2856                  fontColor: Color.Black,
2857                  fontSize: 30
2858                }
2859              })
2860          })
2861          .onSelect((value: RichEditorSelection) => {
2862            this.start = value.selection[0];
2863            this.end = value.selection[1];
2864            this.message = "[" + this.start + ", " + this.end + "]"
2865          })
2866          .aboutToIMEInput((value: RichEditorInsertValue) => {
2867            console.log("---------------------- aboutToIMEInput ----------------------")
2868            console.log("insertOffset:" + value.insertOffset)
2869            console.log("insertValue:" + value.insertValue)
2870            return true;
2871          })
2872          .onIMEInputComplete((value: RichEditorTextSpanResult) => {
2873            console.log("---------------------- onIMEInputComplete ---------------------")
2874            console.log("spanIndex:" + value.spanPosition.spanIndex)
2875            console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]")
2876            console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]")
2877            console.log("value:" + value.value)
2878          })
2879          .aboutToDelete((value: RichEditorDeleteValue) => {
2880            console.log("---------------------- aboutToDelete --------------------------")
2881            console.log("offset:" + value.offset)
2882            console.log("direction:" + value.direction)
2883            console.log("length:" + value.length)
2884            value.richEditorDeleteSpans.forEach(item => {
2885              console.log("---------------------- item --------------------------")
2886              console.log("spanIndex:" + item.spanPosition.spanIndex)
2887              console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]")
2888              console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]")
2889              if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
2890                console.log("image:" + (item as RichEditorImageSpanResult).valueResourceStr)
2891              } else {
2892                console.log("text:" + (item as RichEditorTextSpanResult).value)
2893              }
2894            })
2895            return true;
2896          })
2897          .onDeleteComplete(() => {
2898            console.log("---------------------- onDeleteComplete ------------------------")
2899          })
2900          .borderWidth(1)
2901          .borderColor(Color.Green)
2902          .width("100%")
2903          .height('80.00%')
2904      }
2905      .borderWidth(1)
2906      .borderColor(Color.Red)
2907      .width("100%")
2908      .height("70%")
2909    }
2910  }
2911}
2912```
2913![ImageSpanStyle](figures/richEditorImageSpanStyle.gif)
2914
2915### Example 5: Binding a Gesture Event to a Span
2916This example shows how to bind a [gesture](#richeditorgesture11) callback to a span.
2917
2918```ts
2919// xxx.ets
2920@Entry
2921@Component
2922struct Index {
2923  controller: RichEditorController = new RichEditorController()
2924  options: RichEditorOptions = { controller: this.controller };
2925  @State textFlag: string = "TextFlag";
2926
2927  build() {
2928    Column() {
2929      Column() {
2930        Text(this.textFlag)
2931          .copyOption(CopyOptions.InApp)
2932          .fontSize(50)
2933          .height(150)
2934      }
2935      Divider()
2936      Column() {
2937        RichEditor(this.options)
2938          .onReady(() => {
2939            this.controller.addTextSpan('Area1\n', {
2940              style:
2941              {
2942                fontColor: Color.Orange,
2943                fontSize: 50
2944              },
2945              gesture:
2946              {
2947                onClick: () => {
2948                  this.textFlag = "Area1 is onClick."
2949                },
2950                onLongPress: () => {
2951                  this.textFlag = "Area1 is onLongPress."
2952                }
2953              }
2954            })
2955
2956            this.controller.addTextSpan('Area2\n', {
2957              style:
2958              {
2959                fontColor: Color.Blue,
2960                fontSize: 50
2961              },
2962              gesture:
2963              {
2964                onClick: () => {
2965                  this.textFlag = "Area2 is onClick."
2966                },
2967                onLongPress: () => {
2968                  this.textFlag = "Area2 is onLongPress."
2969                }
2970              }
2971            })
2972
2973            this.controller.addImageSpan($r("app.media.icon"),
2974              {
2975                imageStyle:
2976                {
2977                  size: ["100px", "100px"],
2978                  layoutStyle: {
2979                    margin: 5,
2980                    borderRadius: 15
2981                  }
2982                },
2983                gesture:
2984                {
2985                  onClick: () => {
2986                    this.textFlag = "ImageSpan is onClick."
2987                  },
2988                  onLongPress: () => {
2989                    this.textFlag = "ImageSpan is onLongPress."
2990                  }
2991                },
2992                onHover : (status) => {
2993                  this.textFlag = "ImageSpan is onHover :" + status
2994                }
2995              })
2996          })
2997      }
2998      .borderWidth(1)
2999      .borderColor(Color.Red)
3000      .width("100%")
3001      .height("70%")
3002    }
3003  }
3004}
3005```
3006![OnClickAndLongPress](figures/richEditorGestureAndHover.gif)
3007
3008### Example 6: Updating and Obtaining Paragraph Styles
3009This example demonstrates how to update paragraph styles using the [updateParagraphStyle](#updateparagraphstyle11) API and obtain paragraph information within a specified range using the [getParagraphs](#getparagraphs11) API.
3010
3011```ts
3012// xxx.ets
3013@Entry
3014@Component
3015struct Index {
3016  controller: RichEditorController = new RichEditorController();
3017  private spanParagraphs: RichEditorParagraphResult[] = [];
3018
3019  build() {
3020    Column() {
3021      RichEditor({ controller: this.controller })
3022        .onReady(() => {
3023          this.controller.addTextSpan("0123456789\n", {
3024            style: {
3025              fontColor: Color.Pink,
3026              fontSize: "32",
3027            },
3028            paragraphStyle: {
3029              textAlign: TextAlign.Start,
3030              leadingMargin: 16
3031            }
3032          })
3033          this.controller.addTextSpan("0123456789")
3034        })
3035        .width("80%")
3036        .height("30%")
3037        .border({ width: 1, radius: 5 })
3038        .draggable(false)
3039
3040      Column({ space: 5 }) {
3041        Button("Align Left").onClick(() => {
3042          this.controller.updateParagraphStyle({ start: -1, end: -1,
3043            style: {
3044              textAlign: TextAlign.Start,
3045            }
3046          })
3047        })
3048
3049        Button("Align Right").onClick(() => {
3050          this.controller.updateParagraphStyle({ start: -1, end: -1,
3051            style: {
3052              textAlign: TextAlign.End,
3053            }
3054          })
3055        })
3056
3057        Button("Center").onClick(() => {
3058          this.controller.updateParagraphStyle({ start: -1, end: -1,
3059            style: {
3060              textAlign: TextAlign.Center,
3061            }
3062          })
3063        })
3064
3065        Button("Set Paragraph Spacing to 50").onClick (() => {
3066          this.controller.updateParagraphStyle({ start: -1, end: -1,
3067            style: {
3068              paragraphSpacing: 50,
3069            }
3070          })
3071        })
3072        Divider()
3073        Button("getParagraphs").onClick(() => {
3074          this.spanParagraphs = this.controller.getParagraphs({ start: -1, end: -1 })
3075          console.log("RichEditor getParagraphs:" + JSON.stringify(this.spanParagraphs))
3076        })
3077
3078        Button("UpdateSpanStyle1").onClick(() => {
3079          this.controller.updateSpanStyle({ start: -1, end: -1,
3080            textStyle: {
3081              fontColor: Color.Brown,
3082              fontSize: 20
3083            }
3084          })
3085        })
3086
3087        Button("UpdateSpanStyle2").onClick(() => {
3088          this.controller.updateSpanStyle({ start: -1, end: -1,
3089            textStyle: {
3090              fontColor: Color.Green,
3091              fontSize: 30
3092            }
3093          })
3094        })
3095      }
3096    }
3097  }
3098}
3099```
3100![TextAlignAndGetParagraphInfo](figures/richEditorTextAlignAndGetParagraphInfo.gif)
3101
3102### Example 7: Updating the Preset Style and Indent
3103This example shows how to update the preset text style using the [setTypingStyle](#settypingstyle11) API and set different paragraph indents using the [updateParagraphStyle](#updateparagraphstyle11) API.
3104
3105```ts
3106// xxx.ets
3107import { font } from '@kit.ArkUI'
3108
3109const canvasWidth = 1000
3110const canvasHeight = 100
3111const Indentation = 40
3112class LeadingMarginCreator {
3113  private settings: RenderingContextSettings = new RenderingContextSettings(true)
3114  private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(canvasWidth, canvasHeight)
3115  private offContext: OffscreenCanvasRenderingContext2D = this.offscreenCanvas.getContext("2d", this.settings)
3116  public static instance: LeadingMarginCreator = new LeadingMarginCreator()
3117
3118  // Obtain the font size level, which ranges from 0 to 4.
3119  public getFontSizeLevel(fontSize: number) {
3120    const fontScaled: number = Number(fontSize) / 16
3121
3122    enum FontSizeScaleThreshold {
3123      SMALL = 0.9,
3124      NORMAL = 1.1,
3125      LEVEL_1_LARGE = 1.2,
3126      LEVEL_2_LARGE = 1.4,
3127      LEVEL_3_LARGE = 1.5
3128    }
3129
3130    let fontSizeLevel: number = 1
3131
3132    if (fontScaled < FontSizeScaleThreshold.SMALL) {
3133      fontSizeLevel = 0
3134    } else if (fontScaled < FontSizeScaleThreshold.NORMAL) {
3135      fontSizeLevel = 1
3136    } else if (fontScaled < FontSizeScaleThreshold.LEVEL_1_LARGE) {
3137      fontSizeLevel = 2
3138    } else if (fontScaled < FontSizeScaleThreshold.LEVEL_2_LARGE) {
3139      fontSizeLevel = 3
3140    } else if (fontScaled < FontSizeScaleThreshold.LEVEL_3_LARGE) {
3141      fontSizeLevel = 4
3142    } else {
3143      fontSizeLevel = 1
3144    }
3145
3146    return fontSizeLevel
3147  }
3148  // Obtain the font size level, which ranges from 0 to 4.
3149  public getmarginLevel(Width: number) {
3150    let marginlevel: number = 1
3151    if (Width == 40) {
3152      marginlevel = 2.0
3153    } else if (Width == 80) {
3154      marginlevel = 1.0
3155    } else if (Width == 120) {
3156      marginlevel = 2/3
3157    } else if (Width == 160) {
3158      marginlevel = 0.5
3159    } else if (Width == 200) {
3160      marginlevel = 0.4
3161    }
3162    return marginlevel
3163  }
3164
3165  public genStrMark(fontSize: number, str: string): PixelMap {
3166    this.offContext = this.offscreenCanvas.getContext("2d", this.settings)
3167    this.clearCanvas()
3168    this.offContext.font = fontSize + 'vp sans-serif'
3169    this.offContext.fillText(str + '.', 0, fontSize * 0.9)
3170    return this.offContext.getPixelMap(0, 0, fontSize * (str.length + 1) / 1.75, fontSize)
3171  }
3172
3173  public genSquareMark(fontSize: number): PixelMap {
3174    this.offContext = this.offscreenCanvas.getContext("2d", this.settings)
3175    this.clearCanvas()
3176    const coordinate = fontSize * (1 - 1 / 1.5) / 2
3177    const sideLength = fontSize / 1.5
3178    this.offContext.fillRect(coordinate, coordinate, sideLength, sideLength)
3179    return this.offContext.getPixelMap(0, 0, fontSize, fontSize)
3180  }
3181
3182  // Generate a circle symbol.
3183  public genCircleMark(fontSize: number, width: number, level?: number ): PixelMap {
3184    const indentLevel = level ?? 1
3185    const offsetLevel = [22, 28, 32, 34, 38]
3186    const fontSizeLevel = this.getFontSizeLevel(fontSize)
3187    const marginlevel = this.getmarginLevel(width)
3188    const newCanvas = new OffscreenCanvas(canvasWidth, canvasHeight)
3189    const newOffContext: OffscreenCanvasRenderingContext2D = newCanvas.getContext("2d", this.settings)
3190    const centerCoordinate = 50
3191    const radius = 10
3192    this.clearCanvas()
3193    newOffContext.ellipse(100 * (indentLevel + 1) - centerCoordinate * marginlevel, offsetLevel[fontSizeLevel], radius * marginlevel, radius, 0, 0, 2 * Math.PI)
3194    newOffContext.fillStyle = '66FF0000'
3195    newOffContext.fill()
3196    return newOffContext.getPixelMap(0, 0, 100 + 100 * indentLevel, 100)
3197  }
3198
3199  private clearCanvas() {
3200    this.offContext.clearRect(0, 0, canvasWidth, canvasHeight)
3201  }
3202}
3203
3204@Entry
3205@Component
3206struct Index {
3207  controller: RichEditorController = new RichEditorController()
3208  options: RichEditorOptions = { controller: this.controller }
3209  private leadingMarkCreatorInstance = LeadingMarginCreator.instance
3210  private fontNameRawFile: string = 'MiSans-Bold'
3211  @State fs: number = 30
3212  @State cl: number = Color.Black
3213  private leftMargin: Dimension = 0
3214  private richEditorTextStyle: RichEditorTextStyle = {}
3215
3216  aboutToAppear() {
3217    font.registerFont({
3218      familyName: 'MiSans-Bold',
3219      familySrc: '/font/MiSans-Bold.ttf'
3220    })
3221  }
3222
3223  build() {
3224    Scroll() {
3225      Column() {
3226        RichEditor(this.options)
3227          .onReady(() => {
3228            this.controller.addTextSpan("0123456789\n",
3229              {
3230                style:
3231                {
3232                  fontWeight: 'medium',
3233                  fontFamily: this.fontNameRawFile,
3234                  fontColor: Color.Red,
3235                  fontSize: 50,
3236                  fontStyle: FontStyle.Italic,
3237                  decoration: { type: TextDecorationType.Underline, color: Color.Green }
3238                }
3239              })
3240
3241            this.controller.addTextSpan("abcdefg",
3242              {
3243                style:
3244                {
3245                  fontWeight: FontWeight.Lighter,
3246                  fontFamily: 'HarmonyOS Sans',
3247                  fontColor: 'rgba(0,128,0,0.5)',
3248                  fontSize: 30,
3249                  fontStyle: FontStyle.Normal,
3250                  decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' }
3251                }
3252              })
3253          })
3254          .borderWidth(1)
3255          .borderColor(Color.Green)
3256          .width("100%")
3257          .height("50%")
3258
3259        Row({ space: 5 }) {
3260          Button('setTypingStyle1')
3261            .fontSize(10)
3262            .onClick(() => {
3263              this.controller.setTypingStyle(
3264                {
3265                  fontWeight: 'medium',
3266                  fontFamily: this.fontNameRawFile,
3267                  fontColor: Color.Blue,
3268                  fontSize: 50,
3269                  fontStyle: FontStyle.Italic,
3270                  decoration: { type: TextDecorationType.Underline, color: Color.Green }
3271                })
3272            })
3273
3274          Button('setTypingStyle2')
3275            .fontSize(10)
3276            .onClick(() => {
3277              this.controller.setTypingStyle(
3278                {
3279                  fontWeight: FontWeight.Lighter,
3280                  fontFamily: 'HarmonyOS Sans',
3281                  fontColor: Color.Green,
3282                  fontSize: '30',
3283                  fontStyle: FontStyle.Normal,
3284                  decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' }
3285                })
3286            })
3287        }
3288        Divider()
3289        Button("getTypingStyle").onClick(() => {
3290          this.richEditorTextStyle = this.controller.getTypingStyle()
3291          console.log("RichEditor getTypingStyle:" + JSON.stringify(this.richEditorTextStyle))
3292        })
3293        Divider()
3294        Row({ space: 5 }) {
3295          Button("Increase Bullet Indent").onClick(() => {
3296            let margin = Number(this.leftMargin)
3297            if (margin < 200) {
3298              margin += Indentation
3299              this.leftMargin = margin
3300            }
3301            this.controller.updateParagraphStyle({
3302              start: -10,
3303              end: -10,
3304              style: {
3305                leadingMargin : {
3306                  pixelMap : this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1),
3307                  size: [margin, 40]
3308                }
3309              }
3310            })
3311          })
3312
3313          Button("Decrease Bullet Indent").onClick(() => {
3314            let margin = Number(this.leftMargin)
3315            if (margin > 0) {
3316              margin -= Indentation
3317              this.leftMargin = margin
3318            }
3319            this.controller.updateParagraphStyle({
3320              start: -10,
3321              end: -10,
3322              style: {
3323                leadingMargin : {
3324                  pixelMap : this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1),
3325                  size: [margin, 40]
3326                }
3327              }
3328            })
3329          })
3330        }
3331        Divider()
3332        Row({ space: 5 }) {
3333          Button("Increase Indent").onClick(() => {
3334            let margin = Number(this.leftMargin)
3335            if (margin < 200) {
3336              margin += Indentation
3337              this.leftMargin = margin
3338            }
3339            this.controller.updateParagraphStyle({
3340              start: -10,
3341              end: -10,
3342              style: {
3343                leadingMargin: margin
3344              }
3345            })
3346          })
3347
3348          Button("Decrease Indent").onClick(() => {
3349            let margin = Number(this.leftMargin)
3350            if (margin > 0) {
3351              margin -= Indentation
3352              this.leftMargin = margin
3353            }
3354            this.controller.updateParagraphStyle({
3355              start: -10,
3356              end: -10,
3357              style: {
3358                leadingMargin: margin
3359              }
3360            })
3361          })
3362        }
3363      }.borderWidth(1).borderColor(Color.Red)
3364    }
3365  }
3366}
3367```
3368![UpdateParagraphAndTypingStyle](figures/richEditorUpdateParagraphAndTypingStyle.gif)
3369
3370### Example 8: Setting Text Weight and Shadow
3371This example demonstrates how to set text weight and shadow using the [updateParagraphStyle](#updateparagraphstyle11) API.
3372
3373``` ts
3374@Entry
3375@Component
3376struct Index {
3377  controller: RichEditorController = new RichEditorController();
3378  options: RichEditorOptions = { controller: this.controller };
3379  private start: number = -1;
3380  private end: number = -1;
3381  @State message: string = "[-1, -1]"
3382  @State content: string = ""
3383  @State visable :number = 0;
3384  @State index:number = 0;
3385  @State offsetx: number = 0;
3386  @State textShadows : (ShadowOptions | Array<ShadowOptions> ) =
3387    [{ radius: 10, color: Color.Red, offsetX: 10, offsetY: 0 },{ radius: 10, color: Color.Black, offsetX: 20, offsetY: 0 },
3388      { radius: 10, color: Color.Brown, offsetX: 30, offsetY: 0 },{ radius: 10, color: Color.Green, offsetX: 40, offsetY: 0 },
3389      { radius: 10, color: Color.Yellow, offsetX: 100, offsetY: 0 }]
3390  @State textshadowOf : ShadowOptions[] = []
3391  build() {
3392    Column() {
3393      Column() {
3394        Text("selection range:").width("100%")
3395        Text() {
3396          Span(this.message)
3397        }.width("100%")
3398        Text("selection content:").width("100%")
3399        Text() {
3400          Span(this.content)
3401        }.width("100%")
3402      }
3403      .borderWidth(1)
3404      .borderColor(Color.Red)
3405      .width("100%")
3406      .height("20%")
3407      Row() {
3408        Button("Update Style: Bold & Text Shadow").onClick(() => {
3409          this.controller.updateSpanStyle({
3410            start: this.start,
3411            end: this.end,
3412            textStyle:
3413            {
3414              fontWeight: FontWeight.Bolder,
3415              textShadow: this.textShadows
3416            }
3417          })
3418        })
3419      }
3420      .borderWidth(1)
3421      .borderColor(Color.Red)
3422      .width("100%")
3423      .height("10%")
3424      Column() {
3425        RichEditor(this.options)
3426          .onReady(() => {
3427            this.controller.addTextSpan("0123456789",
3428              {
3429                style:
3430                {
3431                  fontColor: Color.Orange,
3432                  fontSize: 30,
3433                  textShadow: { radius: 10, color: Color.Blue, offsetX: 10, offsetY: 0 }
3434                }
3435              })
3436          })
3437          .borderWidth(1)
3438          .borderColor(Color.Green)
3439          .width("100%")
3440          .height("30%")
3441      }
3442      .borderWidth(1)
3443      .borderColor(Color.Red)
3444      .width("100%")
3445      .height("70%")
3446    }
3447  }
3448}
3449```
3450
3451![TextshadowExample](figures/rich_editor_textshadow.gif)
3452
3453### Example 9: Adding Custom Layout Spans
3454This example shows how to add custom layout spans using the [addBuilderSpan](#addbuilderspan11) API.
3455
3456``` ts
3457@Builder
3458function placeholderBuilder2() {
3459  Row({ space: 2 }) {
3460    Image($r("app.media.icon")).width(24).height(24).margin({ left: -5 })
3461    Text('okokokok').fontSize(10)
3462  }.width('20%').height(50).padding(10).backgroundColor(Color.Red)
3463}
3464
3465// xxx.ets
3466@Entry
3467@Component
3468struct Index {
3469  controller: RichEditorController = new RichEditorController();
3470  option: RichEditorOptions = { controller: this.controller };
3471  private start: number = 2;
3472  private end: number = 4;
3473  @State message: string = "[-1, -1]"
3474  @State content: string = ""
3475  private my_offset: number | undefined = undefined
3476  private my_builder: CustomBuilder = undefined
3477  @BuilderParam my_builder2:() => void = placeholderBuilder2;
3478
3479  @Builder
3480  placeholderBuilder() {
3481    Row({ space: 2 }) {
3482      Image($r("app.media.icon")).width(24).height(24).margin({ left: -5 })
3483      Text('Custom Popup').fontSize(10)
3484    }.width(100).height(50).padding(5)
3485  }
3486
3487  @Builder
3488  placeholderBuilder3() {
3489    Text("hello").padding('20').borderWidth(1).width('100%')
3490  }
3491
3492  @Builder
3493  placeholderBuilder4() {
3494    Column() {
3495      Column({ space: 5 }) {
3496        Text('direction:Row').fontSize(9).fontColor(0xCCCCCC).width('90%')
3497        Flex({ direction: FlexDirection.Row }) { // The child components are arranged in the same direction as the main axis runs along the rows.
3498          Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
3499          Text('1').width('20%').height(50).backgroundColor(0xD2B48C)
3500          Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
3501          Text('1').width('20%').height(50).backgroundColor(0xD2B48C)
3502        }
3503        .height(70)
3504        .width('90%')
3505        .padding(10)
3506        .backgroundColor(0xAFEEEE)
3507
3508        Text('direction:RowReverse').fontSize(9).fontColor(0xCCCCCC).width('90%')
3509        Flex({ direction: FlexDirection.RowReverse }) { // The child components are arranged opposite to the Row direction.
3510          Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
3511          Text('1').width('20%').height(50).backgroundColor(0xD2B48C)
3512          Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
3513          Text('1').width('20%').height(50).backgroundColor(0xD2B48C)
3514        }
3515        .height(70)
3516        .width('90%')
3517        .padding(10)
3518        .backgroundColor(0xAFEEEE)
3519
3520        Text('direction:Column').fontSize(9).fontColor(0xCCCCCC).width('90%')
3521        Flex({ direction: FlexDirection.Column }) { // The child components are arranged in the same direction as the main axis runs down the columns.
3522          Text('1').width('20%').height(40).backgroundColor(0xF5DEB3)
3523          Text('1').width('20%').height(40).backgroundColor(0xD2B48C)
3524          Text('1').width('20%').height(40).backgroundColor(0xF5DEB3)
3525          Text('1').width('20%').height(40).backgroundColor(0xD2B48C)
3526        }
3527        .height(160)
3528        .width('90%')
3529        .padding(10)
3530        .backgroundColor(0xAFEEEE)
3531
3532        Text('direction:ColumnReverse').fontSize(9).fontColor(0xCCCCCC).width('90%')
3533        Flex({ direction: FlexDirection.ColumnReverse }) { // The child components are arranged opposite to the Column direction.
3534          Text('1').width('20%').height(40).backgroundColor(0xF5DEB3)
3535          Text('1').width('20%').height(40).backgroundColor(0xD2B48C)
3536          Text('1').width('20%').height(40).backgroundColor(0xF5DEB3)
3537          Text('1').width('20%').height(40).backgroundColor(0xD2B48C)
3538        }
3539        .height(160)
3540        .width('90%')
3541        .padding(10)
3542        .backgroundColor(0xAFEEEE)
3543      }.width('100%').margin({ top: 5 })
3544    }.width('100%')
3545  }
3546
3547  @Builder
3548  MyMenu() {
3549    Menu() {
3550      MenuItem({ startIcon: $r("app.media.icon"), content: "Menu option 1" })
3551      MenuItem({ startIcon: $r("app.media.icon"), content: "Menu option 2" })
3552        .enabled(false)
3553    }
3554  }
3555
3556  build() {
3557    Column() {
3558      Column() {
3559        Text("selection range:").width("100%")
3560        Text() {
3561          Span(this.message)
3562        }.width("100%")
3563
3564        Text("selection content:").width("100%")
3565        Text() {
3566          Span(this.content)
3567        }.width("100%")
3568      }
3569      .borderWidth(1)
3570      .borderColor(Color.Red)
3571      .width("100%")
3572      .height("20%")
3573
3574      Row() {
3575        Button("Get Span Info").onClick(() => {
3576          console.info('getSpans='+JSON.stringify(this.controller.getSpans({ start:1, end:5 })))
3577          console.info('getParagraphs='+JSON.stringify(this.controller.getParagraphs({ start:1, end:5 })))
3578          this.content = ""
3579          this.controller.getSpans({
3580            start: this.start,
3581            end: this.end
3582          }).forEach(item => {
3583            if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
3584              if ((item as RichEditorImageSpanResult).valueResourceStr == "") {
3585                console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " +
3586                  (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1])
3587              } else {
3588                console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " +
3589                  (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " +
3590                  (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1])
3591              }
3592            } else {
3593              this.content += (item as RichEditorTextSpanResult).value;
3594              this.content += "\n"
3595              console.info("text span: " + (item as RichEditorTextSpanResult).value)
3596            }
3597          })
3598        })
3599        Button("Get Selection").onClick(() => {
3600          this.content = "";
3601          let select = this.controller.getSelection()
3602          console.info("selection start " + select.selection[0] + " end " + select.selection[1])
3603          select.spans.forEach(item => {
3604            if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
3605              if ((item as RichEditorImageSpanResult).valueResourceStr == "") {
3606                console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " +
3607                  (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1])
3608              } else {
3609                console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " +
3610                  (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " +
3611                  (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1])
3612              }
3613            } else {
3614              this.content += (item as RichEditorTextSpanResult).value;
3615              this.content += "\n"
3616              console.info("text span: " + (item as RichEditorTextSpanResult).value)
3617            }
3618          })
3619        })
3620        Button("Delete Selection").onClick(() => {
3621          this.controller.deleteSpans({
3622            start: this.start,
3623            end: this.end
3624          })
3625        })
3626      }
3627      .borderWidth(1)
3628      .borderColor(Color.Red)
3629      .width("100%")
3630      .height("10%")
3631
3632      Column() {
3633        RichEditor(this.option)
3634          .onReady(() => {
3635            this.controller.addTextSpan("0123456789",
3636              {
3637                style:
3638                {
3639                  fontColor: Color.Orange,
3640                  fontSize: 30
3641                }
3642              })
3643            this.controller.addImageSpan($r("app.media.icon"),
3644              {
3645                imageStyle:
3646                {
3647                  size: ["57px", "57px"]
3648                }
3649              })
3650          })
3651          .onSelect((value: RichEditorSelection) => {
3652            this.start = value.selection[0];
3653            this.end = value.selection[1];
3654            this.message = "[" + this.start + ", " + this.end + "]"
3655            console.info("onSelect="+JSON.stringify(value))
3656          })
3657          .aboutToIMEInput((value: RichEditorInsertValue) => {
3658            console.log("---------------------- aboutToIMEInput --------------------")
3659            console.info("aboutToIMEInput="+JSON.stringify(value))
3660            console.log("insertOffset:" + value.insertOffset)
3661            console.log("insertValue:" + value.insertValue)
3662            return true;
3663          })
3664          .onIMEInputComplete((value: RichEditorTextSpanResult) => {
3665            console.log("---------------------- onIMEInputComplete --------------------")
3666            console.info("onIMEInputComplete="+JSON.stringify(value))
3667            console.log("spanIndex:" + value.spanPosition.spanIndex)
3668            console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]")
3669            console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]")
3670            console.log("value:" + value.value)
3671          })
3672          .aboutToDelete((value: RichEditorDeleteValue) => {
3673            value.richEditorDeleteSpans.forEach(item => {
3674              console.log("---------------------- item --------------------")
3675              console.info("spanIndex=" + item.spanPosition.spanIndex)
3676              console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]")
3677              console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]")
3678              if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
3679                if ((item as RichEditorImageSpanResult).valueResourceStr == "") {
3680                  console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " +
3681                  (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1])
3682                } else {
3683                  console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " +
3684                  (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " +
3685                  (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1])
3686                }
3687              } else {
3688                console.info("delete text: " + (item as RichEditorTextSpanResult).value)
3689              }
3690            })
3691            return true;
3692          })
3693          .borderWidth(1)
3694          .borderColor(Color.Green)
3695          .width("100%")
3696          .height("30%")
3697
3698        Button("add span")
3699          .onClick(() => {
3700            let num = this.controller.addBuilderSpan(this.my_builder, { offset: this.my_offset })
3701            console.info('addBuilderSpan return ' + num)
3702          })
3703        Button("add image")
3704          .onClick(() => {
3705            let num = this.controller.addImageSpan($r("app.media.icon"), {
3706              imageStyle: {
3707                size: ["50px", "50px"],
3708                verticalAlign: ImageSpanAlignment.BOTTOM,
3709                layoutStyle: {
3710                  borderRadius: undefined,
3711                  margin: undefined
3712                }
3713              }
3714            })
3715            console.info('addImageSpan return' + num)
3716          })
3717        Row() {
3718          Button('builder1').onClick(() => {
3719            this.my_builder = () => {
3720              this.placeholderBuilder()
3721            }
3722          })
3723          Button('builder2').onClick(() => {
3724            this.my_builder = () => {
3725              this.my_builder2()
3726            }
3727          })
3728          Button('builder3').onClick(() => {
3729            this.my_builder = () => {
3730              this.placeholderBuilder3()
3731            }
3732          })
3733          Button('builder4').onClick(() => {
3734            this.my_builder = () => {
3735              this.placeholderBuilder4()
3736            }
3737          })
3738        }
3739      }
3740      .borderWidth(1)
3741      .borderColor(Color.Red)
3742      .width("100%")
3743      .height("70%")
3744    }
3745  }
3746}
3747```
3748![AddBuilderSpanExample](figures/rich_editor_addBuilderSpan.gif)
3749
3750### Example 10: Configuring Text Recognition
3751This example demonstrates how to enable text recognition by setting [enableDataDetector](#enabledatadetector11) to **true** and configuring text recognition settings using the [dataDetectorConfig](#datadetectorconfig11) API.
3752
3753```ts
3754@Entry
3755@Component
3756struct TextExample7 {
3757  controller: RichEditorController = new RichEditorController();
3758  options: RichEditorOptions = { controller: this.controller };
3759  @State phoneNumber: string = '(86) (755) ********';
3760  @State url: string = 'www.********.com';
3761  @State email: string = '***@example.com';
3762  @State address: string = 'Street A, city B, state C';
3763  @State enableDataDetector: boolean = true;
3764  @State enablePreviewText: boolean = false;
3765  @State types: TextDataDetectorType[] = [];
3766
3767  build() {
3768    Row() {
3769      Column() {
3770        RichEditor(this.options)
3771          .onReady(() => {
3772            this.controller.addTextSpan('Phone number:' + this.phoneNumber + '\n',
3773              {
3774                style:
3775                {
3776                  fontSize: 30
3777                }
3778              })
3779            this.controller.addTextSpan('URL:' + this.url + '\n',
3780              {
3781                style:
3782                {
3783                  fontSize: 30
3784                }
3785              })
3786            this.controller.addTextSpan('Email:' + this.email + '\n',
3787              {
3788                style:
3789                {
3790                  fontSize: 30
3791                }
3792              })
3793            this.controller.addTextSpan('Address:' + this.address,
3794              {
3795                style:
3796                {
3797                  fontSize: 30
3798                }
3799              })
3800          })
3801          .copyOptions(CopyOptions.InApp)
3802          .enableDataDetector(this.enableDataDetector)
3803          .dataDetectorConfig({types : this.types, onDetectResultUpdate: (result: string)=>{}})
3804          .enablePreviewText(this.enablePreviewText)
3805          .borderWidth(1)
3806          .padding(10)
3807          .width('100%')
3808      }
3809      .width('100%')
3810    }
3811  }
3812}
3813```
3814### Example 11: Setting Caret, Selection Handle, and Background Colors
3815This example shows how to set the caret and selection handle color using the [caretColor](#caretcolor12) attribute and the text selection background color using the [selectedBackgroundColor](#selectedbackgroundcolor12) attribute.
3816
3817``` ts
3818@Entry
3819@Component
3820struct RichEditorDemo {
3821  @State color: Color|string = ""
3822  controller: RichEditorController = new RichEditorController();
3823  build() {
3824    Column() {
3825      Row(){
3826        Button("Change to Red").onClick(() => {
3827          this.color = Color.Red
3828        })
3829      }.margin({top:50})
3830      RichEditor({ controller: this.controller })
3831        .onReady(()=>{
3832          this.controller.addTextSpan('This is for testing')
3833        })
3834        .width("100%")
3835        .border({ width: 1, radius: 5 })
3836        .key('RichEditor')
3837        .caretColor(this.color) // Caret color
3838        .selectedBackgroundColor(this.color) // Background color of the selected content.
3839        .margin({top:50})
3840    }
3841    .width('100%')
3842  }
3843}
3844```
3845![SetCaretAndSelectedBackgroundColorExample](figures/rich_editor_caret_color.gif)
3846
3847### Example 12: Setting the Line Height and Letter Spacing
3848This example demonstrates how to configure text line height ([lineHeight](#richeditortextstyle)) and letter spacing ([letterSpacing](#richeditortextstyle)) using the [updateSpanStyle](#updatespanstyle) API.
3849
3850```ts
3851@Entry
3852@Component
3853struct RichEditorDemo03 {
3854  controller: RichEditorController = new RichEditorController();
3855  options: RichEditorOptions = { controller: this.controller };
3856  @State start: number = -1;
3857  @State end: number = -1;
3858  @State LH:number = 50
3859  @State LS:number = 20
3860
3861  build() {
3862    Column() {
3863      Scroll(){
3864        Column(){
3865          Row() {
3866            Button("Line Height ++").onClick(()=>{
3867              this.LH = this.LH + 5
3868              this.controller.updateSpanStyle({
3869                start: this.start,
3870                end: this.end,
3871                textStyle:
3872                {
3873                  lineHeight: this.LH
3874                }
3875              })
3876            })
3877            Button("Line Height --").onClick(()=>{
3878              this.LH = this.LH - 5
3879              this.controller.updateSpanStyle({
3880                start: this.start,
3881                end: this.end,
3882                textStyle:
3883                {
3884                  lineHeight: this.LH
3885                }
3886              })
3887            })
3888            Button("Letter Spacing ++").onClick(()=>{
3889              this.LS = this.LS + 5
3890              this.controller.updateSpanStyle({
3891                start: this.start,
3892                end: this.end,
3893                textStyle:
3894                {
3895                  letterSpacing: this.LS
3896                }
3897              })
3898            })
3899            Button("Letter Spacing --").onClick(()=>{
3900              this.LS = this.LS - 5
3901              this.controller.updateSpanStyle({
3902                start: this.start,
3903                end: this.end,
3904                textStyle:
3905                {
3906                  letterSpacing: this.LS
3907                }
3908              })
3909            })
3910          }
3911        }
3912      }.borderWidth(1)
3913      .borderColor(Color.Red)
3914      .width("100%")
3915      .height("20%")
3916      .margin({top: 20})
3917
3918      Scroll(){
3919        Column() {
3920          Text("LineHeight:" + this.LH).width("100%")
3921          Text("LetterSpacing:" + this.LS).width("100%")
3922        }
3923      }
3924      .borderWidth(1)
3925      .borderColor(Color.Red)
3926      .width("100%")
3927      .height("20%")
3928      .margin({bottom: 20})
3929
3930      Column() {
3931        RichEditor(this.options).clip(true).padding(10)
3932          .onReady(() => {
3933            this.controller.addTextSpan("012345",
3934              {
3935                style:
3936                {
3937                  fontColor: Color.Orange,
3938                  fontSize: 30,
3939                  lineHeight: this.LH,
3940                  letterSpacing: this.LS
3941                }
3942              })
3943            this.controller.addTextSpan("6789",
3944              {
3945                style:
3946                {
3947                  fontColor: Color.Black,
3948                  fontSize: 30,
3949                  lineHeight: this.LH,
3950                  letterSpacing: this.LS
3951                }
3952              })
3953          })
3954          .borderWidth(1)
3955          .borderColor(Color.Green)
3956          .width(400)
3957          .height(400)
3958      }
3959      .borderWidth(1)
3960      .borderColor(Color.Red)
3961      .width("100%")
3962      .height("60%")
3963    }
3964  }
3965}
3966```
3967![AddBuilderSpanExample](figures/richEditorLineHeightAndLetterSpacing.png)
3968
3969### Example 13: Adding a Custom Paste Event
3970This example shows how to add a custom paste event to the component using the [onPaste](#onpaste11) event and customize user paste behavior using the [PasteEvent](#pasteevent11) API.
3971
3972```ts
3973@Entry
3974@Component
3975struct RichEditorDemo {
3976  controller: RichEditorController = new RichEditorController();
3977  options: RichEditorOptions = { controller: this.controller };
3978
3979  build() {
3980    Column({ space: 2 }) {
3981      RichEditor(this.options)
3982        .onReady(() => {
3983          this.controller.addTextSpan('RichEditor preventDefault')
3984        })
3985        .onPaste((event?: PasteEvent) => {
3986          if (event != undefined && event.preventDefault) {
3987            event.preventDefault();
3988          }
3989        })
3990        .borderWidth(1)
3991        .borderColor(Color.Green)
3992        .width('100%')
3993        .height('40%')
3994    }
3995  }
3996}
3997```
3998![PreventDefaultExample](figures/richEditorPreventDefault.gif)
3999
4000### Example 14: Setting Text Feature Effects
4001This example demonstrates how to set text feature effects using the [addTextSpan](#addtextspan) API and the [fontFeature](#richeditortextstyle) attribute. This example sets the **FontFeature** attribute to **ss01**, which changes the digit "0" from its original oval shape to a shape with rounded corners.
4002
4003```ts
4004@Entry
4005@Component
4006struct RichEditorExample {
4007  controller: RichEditorController = new RichEditorController();
4008  options: RichEditorOptions = { controller: this.controller };
4009  @State enableDataDetector: boolean = true;
4010  @State types: TextDataDetectorType[] = [];
4011  build() {
4012    Row() {
4013      Column() {
4014        RichEditor(this.options)
4015          .onReady(() => {
4016            this.controller.addTextSpan('This is ss01 off :' + '0000' + '\n',
4017              {
4018                style:
4019                {
4020                  fontSize: 30
4021                }
4022              })
4023            this.controller.addTextSpan('This is ss01 on :' + '0000' + '\n',
4024              {
4025                style:
4026                {
4027                  fontSize: 30,
4028                  fontFeature: "\"ss01\" 1"
4029                }
4030              })
4031          })
4032          .copyOptions(CopyOptions.InApp)
4033          .enableDataDetector(this.enableDataDetector)
4034          .dataDetectorConfig({types : this.types, onDetectResultUpdate: (result: string)=>{}})
4035          .borderWidth(1)
4036          .padding(10)
4037          .width('100%')
4038      }
4039      .width('100%')
4040      .margin({top:150})
4041    }
4042  }
4043}
4044```
4045![FontFeatureExample](figures/richEditorFontFeature.png)
4046
4047### Example 15: Setting Custom Keyboard Avoidance
4048This example shows how to bind a custom keyboard using the [customKeyboard](#customkeyboard) attribute and configure whether the custom keyboard supports keyboard avoidance using the [KeyboardOptions](#keyboardoptions12) parameter.
4049
4050```ts
4051@Entry
4052@Component
4053struct RichEditorExample {
4054  controller: RichEditorController = new RichEditorController()
4055  @State height1:string|number = '80%'
4056  @State height2:number = 100
4057  @State supportAvoidance:boolean = true;
4058
4059  // Create a custom keyboard component.
4060  @Builder CustomKeyboardBuilder() {
4061    Column() {
4062      Row(){
4063        Button('Add Emoticon').onClick(() => {
4064          this.controller.addTextSpan("\uD83D\uDE0A",
4065            {
4066              style:
4067              {
4068                fontColor: Color.Orange,
4069              }
4070            })
4071        })
4072      }
4073      Grid() {
4074        ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => {
4075          GridItem() {
4076            Button(item + "")
4077              .width(110).onClick(() => {
4078              this.controller.addTextSpan(item + '', {
4079                offset: this.controller.getCaretOffset(),
4080                style:
4081                {
4082                  fontColor: Color.Orange,
4083                  fontSize: 30
4084                }
4085              })
4086              this.controller.setCaretOffset(this.controller.getCaretOffset() + item.toString().length)
4087            })
4088          }
4089        })
4090      }.maxCount(3).columnsGap(10).rowsGap(10).padding(5)
4091    }.backgroundColor(Color.Gray)
4092  }
4093
4094  build() {
4095    Column() {
4096      Row(){
4097        Button("20%")
4098          .fontSize(24)
4099          .onClick(()=>{
4100            this.height1 = "20%"
4101          })
4102        Button("80%")
4103          .fontSize(24)
4104          .margin({left:20})
4105          .onClick(()=>{
4106            this.height1 = "80%"
4107          })
4108      }
4109      .justifyContent(FlexAlign.Center)
4110      .alignItems(VerticalAlign.Bottom)
4111      .height(this.height1)
4112      .width("100%")
4113      .padding({bottom:50})
4114      RichEditor({ controller: this.controller })
4115        // Bind the custom keyboard.
4116        .customKeyboard(this.CustomKeyboardBuilder(),{ supportAvoidance: this.supportAvoidance }).margin(10).border({ width: 1 })
4117        .borderWidth(1)
4118        .borderColor(Color.Red)
4119        .width("100%")
4120    }
4121  }
4122}
4123```
4124![CustomRichEditorType](figures/Custom_Rich_Editor.gif)
4125
4126### Example 16: Viewing the Editing State
4127This example demonstrates how to obtain the current editing state of the rich text using the [isEditing](#isediting12) API. The [onEditingChange](#oneditingchange12) event can be added to the component to log whether the component is currently in editing mode.
4128
4129```ts
4130@Entry
4131@Component
4132struct RichEditor_onEditingChange {
4133  controller: RichEditorController = new RichEditorController()
4134  @State controllerIsEditing: boolean = false
4135  @Builder
4136
4137  build() {
4138    Column() {
4139      Row() {
4140        Button("View Editing State: isEditing():").onClick(() => {
4141          this.controllerIsEditing = this.controller.isEditing()
4142        })
4143          .padding(5)
4144        Text('' + this.controllerIsEditing)
4145          .width('100%')
4146          .padding(5)
4147          .fontColor(Color.Orange)
4148          .fontSize(20)
4149      }
4150      RichEditor({ controller: this.controller })
4151        .onEditingChange((isEditing: boolean) => {
4152          console.log("Current Editing Status:" + isEditing)
4153        })
4154        .height(400)
4155        .borderWidth(1)
4156        .borderColor(Color.Red)
4157        .width("100%")
4158    }
4159  }
4160}
4161```
4162
4163![RichEditorOnEditingChange](figures/richEditorOnEditingChange.gif)
4164
4165### Example 17: Configuring Text Change Callback
4166This example shows how to add the [onWillChange](#onwillchange12) event to the component, which triggers a callback before the component performs any insert or delete operations.
4167
4168```ts
4169@Entry
4170@Component
4171struct RichEditorExample {
4172  controller: RichEditorController = new RichEditorController()
4173  build() {
4174    Column() {
4175      RichEditor({ controller: this.controller })
4176        .height(200)
4177        .borderWidth(1)
4178        .borderColor(Color.Red)
4179        .width("100%")
4180        .onReady(() => {
4181          this.controller.addTextSpan('TestWord', { style: { fontColor: Color.Orange, fontSize: 30 } })
4182          this.controller.updateSpanStyle({
4183            start: -1,
4184            end: -1,
4185            textStyle:
4186            {
4187              fontWeight: FontWeight.Bolder
4188            }
4189          })
4190        })
4191        .onWillChange((value: RichEditorChangeValue) => {
4192          console.log('Test log: onWillChange')
4193          console.log('rangeBefore: ' + JSON.stringify(value.rangeBefore))
4194          console.log('print replacedSpans')
4195          value.replacedSpans.forEach((item: RichEditorTextSpanResult) => {
4196            console.log('spanPosition:' + JSON.stringify(item.spanPosition))
4197            console.log('value:' + item.value)
4198            console.log('textStyle:' + JSON.stringify(item.textStyle))
4199            console.log('offsetInSpan:' + item.offsetInSpan)
4200            console.log('valueResource:' + item.valueResource)
4201            console.log('paragraphStyle:' + JSON.stringify(item.paragraphStyle))
4202          })
4203          console.log('print replacedImageSpans')
4204          value.replacedImageSpans.forEach((item: RichEditorImageSpanResult) => {
4205            console.log('spanPosition:' + JSON.stringify(item.spanPosition))
4206            console.log('valuePixelMap:' + JSON.stringify(item.valuePixelMap))
4207            console.log('valueResourceStr:' + item.valueResourceStr)
4208            console.log('imageStyle:' + JSON.stringify(item.imageStyle))
4209            console.log('offsetInSpan:' + item.offsetInSpan)
4210          })
4211          console.log('print replacedSymbolSpans')
4212          value.replacedSymbolSpans.forEach((item: RichEditorTextSpanResult) => {
4213            console.log('spanPosition:' + JSON.stringify(item.spanPosition))
4214            console.log('value:' + item.value)
4215            console.log('offsetInSpan:' + item.offsetInSpan)
4216            console.log('symbolSpanStyle:' + JSON.stringify(item.symbolSpanStyle))
4217            console.log('valueResource:' + item.valueResource)
4218            console.log('paragraphStyle:' + JSON.stringify(item.paragraphStyle))
4219          })
4220          return true
4221        })
4222        .onDidChange((rangeBefore: TextRange, rangeAfter: TextRange) => {
4223          console.log('Test log: onDidChange')
4224          console.log('rangeBefore:' + JSON.stringify(rangeBefore))
4225          console.log('rangeAfter:' + JSON.stringify(rangeAfter))
4226        })
4227        .onCut((event:CutEvent) => {
4228          event.preventDefault!()
4229          console.log('Test log: onCut')
4230        })
4231        .onCopy((event:CopyEvent) => {
4232          event.preventDefault!()
4233          console.log('Test log: onCopy')
4234        })
4235        .onPaste(()=>{
4236          console.log('Test log: onPaste')
4237        })
4238      Text('Test text Hello')
4239        .lineHeight(50)
4240        .fontSize(24)
4241        .draggable(true)
4242        .onDragStart(()=>{})
4243      TextInput({text:'Test text NiHao'})
4244        .draggable(true)
4245        .margin(20)
4246    }
4247  }
4248}
4249```
4250### Example 18: Configuring the Enter Key Type
4251This example demonstrates how to set the Enter key type of the soft keyboard using the [enterKeyType](#enterkeytype12) attribute.
4252
4253```ts
4254@Entry
4255@Component
4256struct SoftKeyboardEnterTypeExample {
4257  controller: RichEditorController = new RichEditorController()
4258
4259    build() {
4260    Column() {
4261      Button("Stop Editing").onClick(()=>{
4262        this.controller.stopEditing()
4263      })
4264      RichEditor({ controller: this.controller })
4265        .margin(10)
4266        .border({ width: 1 })
4267        .height(200)
4268        .borderWidth(1)
4269        .borderColor(Color.Red)
4270        .width("100%")
4271        .enterKeyType(EnterKeyType.Search)
4272        .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => {
4273          console.log("trigger richeditor onsubmit" + enterKey);
4274          this.controller.addTextSpan(" type["+ enterKey +"] triggerred")
4275          event.keepEditableState();
4276        })
4277    }.height("100%").justifyContent(FlexAlign.Center)
4278  }
4279}
4280```
4281
4282![SoftKeyboardEnterType](figures/richeditorentertype.gif)
4283
4284### Example 19: Setting the Paragraph Line Break Rule
4285This example shows how to set the line break rule ([lineBreakStrategy](#richeditorparagraphstyle11)) using the [updateParagraphStyle](#updateparagraphstyle11) API and obtain the current line break rule using the [getParagraphs](#getparagraphs11) API.
4286
4287```ts
4288@Entry
4289@Component
4290struct LineBreakStrategyExample {
4291  controller: RichEditorController = new RichEditorController();
4292  private spanParagraphs: RichEditorParagraphResult[] = [];
4293  @State lineBreakOptionStr: string[] = ['GREEDY', 'HIGH_QUALITY', 'BALANCED']
4294  @State attributeValue: string = ""
4295  @State testStr: string = "0123456789,0123456789,0123456789,0123456789,0123456789."
4296  build() {
4297    Column() {
4298      RichEditor({ controller: this.controller })
4299        .onReady(() => {
4300          this.controller.addTextSpan(this.testStr, {
4301            style: {
4302              fontColor: Color.Black,
4303              fontSize: "32",
4304            },
4305            paragraphStyle: {
4306              textAlign: TextAlign.Start,
4307              lineBreakStrategy: LineBreakStrategy.GREEDY
4308            }
4309          })
4310        })
4311        .width(400)
4312        .height(300)
4313        .margin({bottom:20})
4314        .draggable(false)
4315      Column(){
4316        Text('linebreak value: ' + this.attributeValue).fontSize(20).fontColor(Color.Black)
4317      }.margin({bottom: 10})
4318      Column({ space: 10 }) {
4319        Button("Set LineBreakStrategy to GREEDY").onClick(() => {
4320          this.controller.updateParagraphStyle({ start: -1, end: -1,
4321            style: {
4322              lineBreakStrategy: LineBreakStrategy.GREEDY,
4323            }
4324          })
4325        })
4326        Button("Set LineBreakStrategy to HIGH_QUALITY").onClick(() => {
4327          this.controller.updateParagraphStyle({ start: -1, end: -1,
4328            style: {
4329              lineBreakStrategy: LineBreakStrategy.HIGH_QUALITY,
4330            }
4331          })
4332        })
4333        Button("Set LineBreakStrategy to BALANCED").onClick(() => {
4334          this.controller.updateParagraphStyle({ start: -1, end: -1,
4335            style: {
4336              lineBreakStrategy: LineBreakStrategy.BALANCED,
4337            }
4338          })
4339        })
4340        Divider()
4341        Row(){
4342          Button("Get LineBreakStrategy Value").onClick(() => {
4343            this.spanParagraphs = this.controller.getParagraphs({ start: -1, end: -1 })
4344            console.log("RichEditor getParagraphs:" + JSON.stringify(this.spanParagraphs))
4345            this.spanParagraphs.forEach(item => {
4346              if(typeof(item as RichEditorParagraphResult)['style'] != 'undefined'){
4347                this.attributeValue = ""
4348                console.info('lineBreakStrategy:'+ JSON.stringify((item as RichEditorParagraphResult)['style']))
4349                this.attributeValue += this.lineBreakOptionStr[Number((item as RichEditorParagraphResult)['style'].lineBreakStrategy)];
4350              }
4351            })
4352          })
4353        }
4354      }
4355    }
4356  }
4357}
4358```
4359
4360![LineBreakStrategy](figures/richEditorLineBreak.gif)
4361
4362### Example 20: Using Basic Functionality of Styled Strings
4363This example demonstrates how to bind a [styled string](./ts-universal-styled-string.md) to a **RichEditor** component using the [setStyledString](#setstyledstring12) API in [RichEditorStyledStringController](#richeditorstyledstringcontroller12). The [getStyledString](#getstyledstring12) API can be used to obtain the styled string displayed by the **RichEditor** component.
4364
4365```ts
4366// xxx.ets
4367import { LengthMetrics } from '@kit.ArkUI'
4368import { image } from '@kit.ImageKit'
4369
4370@Entry
4371@Component
4372struct Index {
4373  stringLength: number = 0;
4374  imagePixelMap: image.PixelMap | undefined = undefined;
4375  @State selection: string = "";
4376  @State content: string = "";
4377  @State range: string = "";
4378  @State replaceString: string = "";
4379  @State rangeBefore: string = "";
4380  @State rangeAfter: string = "";
4381  richEditorStyledString: MutableStyledString = new MutableStyledString("");
4382  textStyle: TextStyle = new TextStyle({
4383    fontWeight: FontWeight.Lighter,
4384    fontFamily: 'HarmonyOS Sans',
4385    fontColor: Color.Green,
4386    fontSize: LengthMetrics.vp(30),
4387    fontStyle: FontStyle.Normal
4388  })
4389  fontStyle1: TextStyle = new TextStyle({ fontColor: Color.Blue });
4390  fontStyle2: TextStyle = new TextStyle({
4391    fontWeight: FontWeight.Bolder,
4392    fontFamily: 'Arial',
4393    fontColor: Color.Orange,
4394    fontSize: LengthMetrics.vp(30),
4395    fontStyle: FontStyle.Italic
4396  })
4397
4398  controller1: RichEditorController = new RichEditorController()
4399  options1: RichEditorOptions = { controller: this.controller1 };
4400  // Create a styled string object.
4401  mutableStyledString: MutableStyledString = new MutableStyledString("Initial styled string",
4402    [{ start: 0, length: 5, styledKey: StyledStringKey.FONT, styledValue: this.fontStyle1 }]);
4403  styledString: StyledString = new StyledString("Styled string to insert",
4404    [{ start: 2, length: 4, styledKey: StyledStringKey.FONT, styledValue: this.fontStyle2 }]);
4405  controller: RichEditorStyledStringController = new RichEditorStyledStringController();
4406  options: RichEditorStyledStringOptions = {controller: this.controller};
4407  // Text content change callback
4408  contentChangedListener: StyledStringChangedListener = {
4409    onWillChange: (value: StyledStringChangeValue) => {
4410      this.range = '[ ' + value.range.start + ' , ' + value.range.end + ' ]';
4411      this.replaceString = value.replacementString.getString();
4412      return true;
4413    },
4414    onDidChange: (rangeBefore, rangeAfter) => {
4415      this.rangeBefore = '[ ' + rangeBefore.start + ' , ' + rangeBefore.end + ' ]';
4416      this.rangeAfter = '[ ' + rangeAfter.start + ' , ' + rangeAfter.end + ' ]';
4417    }
4418  }
4419
4420  async aboutToAppear() {
4421    console.info("aboutToAppear initial imagePixelMap");
4422    this.imagePixelMap = await this.getPixmapFromMedia($r('app.media.app_icon'));
4423  }
4424
4425  private async getPixmapFromMedia(resource: Resource) {
4426    let unit8Array = await getContext(this)?.resourceManager?.getMediaContent({
4427      bundleName: resource.bundleName,
4428      moduleName: resource.moduleName,
4429      id: resource.id
4430    })
4431    let imageSource = image.createImageSource(unit8Array.buffer.slice(0, unit8Array.buffer.byteLength))
4432    let createPixelMap: image.PixelMap = await imageSource.createPixelMap({
4433      desiredPixelFormat: image.PixelMapFormat.RGBA_8888
4434    })
4435    await imageSource.release()
4436    return createPixelMap
4437  }
4438
4439
4440  build() {
4441    Column({space:6}) {
4442      Column() {
4443        Text("Selection information")
4444          .fontSize(20)
4445          .width("100%")
4446        Text("selection range: " + this.selection).width("100%")
4447        Text("selection content: " + this.content).width("100%")
4448      }
4449      .width("100%")
4450      .height("10%")
4451
4452      Column() {
4453        Text("onWillChange callback")
4454          .fontSize(20)
4455          .width("100%")
4456        Text("range: " + this.range).width("100%")
4457        Text("replacementString: " + this.replaceString).width("100%")
4458        Text("onWillChange callback")
4459          .fontSize(20)
4460          .width("100%")
4461        Text("rangeBefore: " + this.rangeBefore).width("100%")
4462        Text("rangeAfter: " + this.rangeAfter).width("100%")
4463      }
4464      .borderWidth(1)
4465      .borderColor(Color.Black)
4466      .width("100%")
4467      .height("20%")
4468
4469      RichEditor(this.options)
4470        .onReady(() => {
4471          // Register a text change callback.
4472          this.controller.onContentChanged(this.contentChangedListener);
4473          // Set the styled string displayed in the component.
4474          this.controller.setStyledString(this.mutableStyledString);
4475        })
4476        .height("20%")
4477        .width("100%")
4478
4479      RichEditor(this.options1)
4480        .onReady(() => {
4481        this.controller1.addTextSpan("Convert into Styled String");
4482      })
4483        .height("10%")
4484        .width("100%")
4485        .borderWidth(1)
4486        .borderColor(Color.Black)
4487
4488        Row({space:2}) {
4489          Button("Insert Image")
4490            .stateEffect(true)
4491            .onClick(() => {
4492            if (this.imagePixelMap !== undefined) {
4493              let imageStyledString = new MutableStyledString(new ImageAttachment({
4494                value: this.imagePixelMap,
4495                size: { width: 50, height: 50 },
4496                layoutStyle: { borderRadius: LengthMetrics.vp(10) },
4497                verticalAlign: ImageSpanAlignment.BASELINE,
4498                objectFit: ImageFit.Contain
4499              }))
4500              // Obtain the styled string displayed in the component.
4501              this.richEditorStyledString = this.controller.getStyledString();
4502              this.richEditorStyledString.appendStyledString(imageStyledString);
4503              // Display the styled string after the image is inserted on the component.
4504              this.controller.setStyledString(this.richEditorStyledString);
4505              this.controller.setCaretOffset(this.richEditorStyledString.length);
4506            }
4507          })
4508          Button("Insert Text").onClick () => {
4509            // Obtain the styled string displayed in the component.
4510            this.richEditorStyledString = this.controller.getStyledString();
4511            this.richEditorStyledString.appendStyledString(this.styledString);
4512            // Display the styled string after the text is inserted on the component.
4513            this.controller.setStyledString(this.richEditorStyledString);
4514            this.controller.setCaretOffset(this.richEditorStyledString.length);
4515          })
4516          Button("Delete Selected").onClick(() => {
4517            // Obtain the selection.
4518            let richEditorSelection = this.controller.getSelection();
4519            let start = richEditorSelection.start ? richEditorSelection.start : 0;
4520            let end = richEditorSelection.end ? richEditorSelection.end : 0;
4521            if (start < 0 || end <= start) {
4522              return;
4523            }
4524            // Obtain the styled string displayed in the component.
4525            this.richEditorStyledString = this.controller.getStyledString();
4526            this.richEditorStyledString.removeString(start, end - start);
4527            // Display the styled string after the content is deleted on the component.
4528            this.controller.setStyledString(this.richEditorStyledString);
4529          })
4530        }
4531        Row({space:2}) {
4532          Button("Get Selection").onClick(() => {
4533            // Obtain the selection.
4534            let richEditorSelection = this.controller.getSelection();
4535            let start = richEditorSelection.start ? richEditorSelection.start : 0;
4536            let end = richEditorSelection.end ? richEditorSelection.end : 0;
4537            // Obtain the styled string displayed in the component.
4538            this.richEditorStyledString = this.controller.getStyledString();
4539            this.selection = '[ ' + start + ' , ' + end + ' ]';
4540            if (start == end) {
4541              this.content = "";
4542            } else {
4543              this.content = this.richEditorStyledString.subStyledString(start, end - start).getString();
4544            }
4545          })
4546          Button("Update Selection Style").onClick(() => {
4547            // Obtain the selection.
4548            let richEditorSelection = this.controller.getSelection();
4549            let start = richEditorSelection.start ? richEditorSelection.start : 0;
4550            let end = richEditorSelection.end ? richEditorSelection.end : 0;
4551            if (start < 0 || end <= start) {
4552              return;
4553            }
4554            // Obtain the styled string displayed in the component.
4555            this.richEditorStyledString = this.controller.getStyledString();
4556            this.richEditorStyledString.setStyle({
4557              start: start,
4558              length: end - start,
4559              styledKey: StyledStringKey.FONT,
4560              styledValue: this.textStyle
4561            })
4562            // Display the styled string after the style change on the component.
4563            this.controller.setStyledString(this.richEditorStyledString);
4564          })
4565        }
4566        Row({space:2}){
4567          // Convert a styled string into a span.
4568          Button("Call fromStyledString").onClick(() => {
4569            this.controller1.addTextSpan("Call fromStyledString: " +JSON.stringify(this.controller1.fromStyledString(this.mutableStyledString)))
4570          })
4571          // Convert the component content within the given range into a styled string.
4572          Button("Call toStyledString").onClick(() => {
4573            this.controller.setStyledString(this.controller1.toStyledString({start:0,end:13}))
4574          })
4575        }
4576    }
4577  }
4578}
4579```
4580
4581
4582
4583### Example 21: Obtaining Layout Information
4584This example shows how to obtain layout information using the [getLayoutManager](#getlayoutmanager12) API. It includes obtaining the total number of lines using [getLineCount](ts-text-common.md#getlinecount), the glyph position closest to a given coordinate using [getGlyphPositionAtCoordinate](ts-text-common.md#getglyphpositionatcoordinate), and line metrics, text style information, and font properties using [getLineMetrics](ts-text-common.md#getlinemetrics).
4585
4586```ts
4587@Entry
4588@Component
4589export struct Index {
4590  @State lineCount: string = ""
4591  @State glyphPositionAtCoordinate: string = ""
4592  @State lineMetrics: string = ""
4593  controller: RichEditorController = new RichEditorController();
4594  @State textStr: string =
4595    'Hello World!'
4596
4597  build() {
4598    Scroll() {
4599      Column() {
4600        Text('getLayoutManager obtains the layout information relative to the component')
4601          .fontSize(9)
4602          .fontColor(0xCCCCCC)
4603          .width('90%')
4604          .padding(10)
4605        RichEditor({ controller: this.controller })
4606          .borderColor(Color.Red)
4607          .borderWidth(1)
4608          .onReady(() => {
4609            this.controller.addTextSpan(this.textStr)
4610          })
4611          .onAreaChange(() => {
4612            let layoutManager = this.controller.getLayoutManager();
4613            this.lineCount = "LineCount: " + layoutManager.getLineCount()
4614          })
4615
4616        Text('LineCount').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10)
4617        Text(this.lineCount)
4618
4619        Text('GlyphPositionAtCoordinate').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10)
4620        Button("Glyph info of relative component coordinates [150, 50]")
4621          .onClick(() => {
4622            let layoutManager: LayoutManager = this.controller.getLayoutManager()
4623            let position = layoutManager.getGlyphPositionAtCoordinate(150, 50)
4624            this.glyphPositionAtCoordinate =
4625            "Relative component coordinates [150, 50] glyphPositionAtCoordinate position: " + position.position + " affinity: " +
4626            position.affinity
4627          })
4628          .margin({ bottom: 20, top: 10 })
4629        Text(this.glyphPositionAtCoordinate)
4630
4631        Text('LineMetrics').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10)
4632        Button("Line Metrics")
4633          .onClick(() => {
4634            let layoutManager: LayoutManager = this.controller.getLayoutManager()
4635            let lineMetrics = layoutManager.getLineMetrics(0)
4636            this.lineMetrics = "lineMetrics is " + JSON.stringify(lineMetrics) + '\n\n'
4637            let runMetrics = lineMetrics.runMetrics
4638            runMetrics.forEach((value, key) => {
4639              this.lineMetrics += "runMetrics key is " + key + " " + JSON.stringify(value) + "\n\n"
4640            });
4641          })
4642          .margin({ bottom: 20, top: 10 })
4643        Text(this.lineMetrics)
4644      }
4645      .margin({ top: 100, left: 8, right: 8 })
4646    }
4647  }
4648}
4649```
4650
4651![LayoutManager](figures/getLayoutManager.gif)
4652
4653### Example 22: Setting Custom Menu Extensions
4654This example demonstrates how to set custom menu extensions using the [editMenuOptions](#editmenuoptions12) property. This allows you to customize the text content, icons, and callback methods for the menu extensions.
4655
4656```ts
4657// xxx.ets
4658@Entry
4659@Component
4660struct RichEditorExample {
4661  controller: RichEditorController = new RichEditorController();
4662  options: RichEditorOptions = { controller: this.controller }
4663
4664  onCreateMenu(menuItems: Array<TextMenuItem>) {
4665    console.log('menuItems size=' + menuItems.length);
4666    menuItems.forEach((value, index) => {
4667      console.log('menuItem' + index + ', id=' + JSON.stringify(value));
4668    })
4669    let extensionMenuItems: Array<TextMenuItem> = [
4670      {
4671        content: 'Extended RichEditor 1', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension1')
4672      },
4673      {
4674        content: 'Extended RichEditor 2', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension2')
4675      },
4676      {
4677        content: 'Extended RichEditor 3', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension3')
4678      },
4679      {
4680        content: 'Extended RichEditor 4', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension4')
4681      }
4682    ]
4683    return menuItems.concat(extensionMenuItems)
4684  }
4685  onMenuItemClicked(menuItem: TextMenuItem, textRange: TextRange) {
4686    if (menuItem.id.equals(TextMenuItemId.of('extension1'))) {
4687      console.log('click' + menuItem.content + ', textRange=' + JSON.stringify(textRange))
4688      return true;
4689    }
4690    return false;
4691  }
4692
4693  build() {
4694    Row() {
4695      RichEditor(this.options)
4696        .onReady(() => {
4697          this.controller.addTextSpan("Extended RichEditor")
4698        })
4699        .editMenuOptions({
4700          onCreateMenu: (menuItems: Array<TextMenuItem>) => {
4701            return this.onCreateMenu(menuItems)
4702          },
4703          onMenuItemClick: (menuItem: TextMenuItem, textRange: TextRange) => {
4704            return this.onMenuItemClicked(menuItem, textRange)
4705          }
4706        })
4707        .height(200)
4708        .borderWidth(1)
4709        .borderColor(Color.Red)
4710    }
4711  }
4712}
4713```
4714
4715![RichEditorSelectionMenuOptions](figures/richEditorSelectionMenuOptions.png)
4716
4717### Example 23: Setting Common Component Attributes
4718This example shows how to set common attributes for the component, including:
4719
4720- Setting the scrollbar display mode during editing using [barState](#barstate13)
4721- Configuring whether the soft keyboard is automatically displayed when the component gains focus through means other than clicking, using [enableKeyboardOnFocus](#enablekeyboardonfocus12)
4722- Enabling or disabling haptic feedback for the component using [enableHapticFeedback](#enablehapticfeedback13)
4723- Obtaining preview text information using [getPreviewText](#getpreviewtext12) Specifying whether to prevent the back button press from being propagated to other components or applications, using [stopBackPress](#stopbackpress18)
4724
4725```ts
4726// xxx.ets
4727import { JSON } from '@kit.ArkTS';
4728
4729@Entry
4730@Component
4731struct RichEditor_example {
4732  controller: RichEditorController = new RichEditorController()
4733  options: RichEditorOptions = { controller: this.controller };
4734
4735  controller1: RichEditorController = new RichEditorController()
4736  options1: RichEditorOptions = { controller: this.controller1 };
4737
4738  @State e: boolean = true
4739  @State bs_num: number = 0
4740  @State bs: (BarState | undefined)[] = [BarState.Auto, BarState.On, BarState.Off, undefined]
4741  @State bs_string: (String)[] = ["Auto", "On", "Off", "undefined"]
4742
4743  build() {
4744    Column({space: 3}) {
4745      RichEditor(this.options)
4746        .onReady(() => {
4747          this.controller.addTextSpan('This text is for demonstration purposes. This text is for demonstration purposes. This text is for demonstration purposes. ', {
4748            style: {
4749              fontColor: Color.Black,
4750              fontSize: 15
4751            }
4752          })
4753        })
4754        .onDidIMEInput((value: TextRange) => {
4755          this.controller1.addTextSpan("\n" + "onDidIMEInput callback triggered. Input range: (" + value.start + "," + value.end + ")", {
4756            style: {
4757              fontColor: Color.Gray,
4758              fontSize: 10
4759            }
4760          })
4761        })
4762        .onSelectionChange((value: RichEditorRange) => {
4763          this.controller1.addTextSpan("\n" + "onSelectionChange callback triggered. Input range: (" + value.start + "," + value.end + ")", {
4764            style: {
4765              fontColor: Color.Gray,
4766              fontSize: 10
4767            }
4768          })
4769        })
4770        .width(300)
4771        .height(100)
4772        .margin(20)
4773        .barState(this.bs[this.bs_num])
4774        .enableKeyboardOnFocus(this.e)
4775        .enableHapticFeedback(true)
4776        .stopBackPress(false);
4777
4778      RichEditor(this.options1).width(300)
4779
4780      Button('Set barState to ' + this.bs_string[this.bs_num])
4781        .height(30)
4782        .fontSize(13)
4783        .onClick(() => {
4784          this.bs_num++
4785          if (this.bs_num > (this.bs.length - 1)) {
4786            this.bs_num = 0
4787          }
4788        })
4789
4790      Button('Set enableKeyboardOnFocus to ' + this.e)
4791        .height(30)
4792        .fontSize(13)
4793        .onClick(() => {
4794          this.e = !this.e
4795        })
4796
4797      Button('Get Preview Text')
4798        .height(30)
4799        .fontSize(13)
4800        .onClick(() => {
4801          this.controller1.addTextSpan("\nObtained preview text: " + JSON.stringify(this.controller.getPreviewText()))
4802        })
4803    }
4804  }
4805}
4806
4807```
4808
4809
4810
4811### Example 24: Obtaining the Relative Position of the Cursor in the Component
4812This example demonstrates how to obtain the relative position of the current cursor in the component using the [getCaretRect](#getcaretrect18) API in **RichEditorBaseController**.
4813
4814```ts
4815// xxx.ets
4816@Entry
4817@Component
4818struct Index {
4819  controller: RichEditorController = new RichEditorController()
4820  options: RichEditorOptions = { controller: this.controller };
4821  @State caretRect: string = "not found";
4822
4823  build() {
4824    Column() {
4825      Button('get caret rect')
4826        .onClick(() => {
4827          let rectCaret = this.controller.getCaretRect();
4828          if(rectCaret == undefined) {
4829            this.caretRect = 'undefined'
4830          } else {
4831            this.caretRect = 'X: ' + rectCaret.x + '\nY: ' + rectCaret.y
4832              + '\nWidth: ' + rectCaret.width + '\nHeight: ' + rectCaret.height
4833          }
4834        })
4835        .fontSize(24)
4836        .width("60%")
4837        .height("10%")
4838
4839      Text(this.caretRect)
4840        .margin(12)
4841        .fontSize(24)
4842
4843      RichEditor(this.options)
4844        .onReady(() => {
4845          this.controller.addTextSpan('12345678901234567890', {
4846            style:
4847            {
4848              fontColor: Color.Orange,
4849              fontSize: 50
4850            }
4851          })
4852        })
4853        .borderWidth(1)
4854        .borderColor(Color.Red)
4855        .width("100%")
4856        .height("60%")
4857    }
4858  }
4859}
4860
4861```
4862
4863
4864
4865### Example 25: Setting the Maximum Number of Lines and Maximum Number of Characters
4866This example shows how to set the maximum number of characters using **maxLength** and the maximum number of lines using **maxLines**.
4867
4868```ts
4869@Entry
4870@Component
4871struct RichEditorExample {
4872  @State text: string = "As the sun begins to set, casting a warm golden hue across the sky," +
4873    "the world seems to slow down and breathe a sigh of relief. The sky is painted with hues of orange, " +
4874    " pink, and lavender, creating a breathtaking tapestry that stretches as far as the eye can see." +
4875    "The air is filled with the sweet scent of blooming flowers, mingling with the earthy aroma of freshly turned soil." +
4876    "it casts a warm," +
4877    "golden hue that spreads like liquid amber across the vast expanse of the sky." +
4878    "The once-blue heavens gradually transform, " +
4879    "now painted in a breathtaking palette of soft oranges, pinks, " +
4880    "and purples, each color blending seamlessly into the next. Wisps of clouds, tinged with fiery edges, " +
4881    "float lazily amidst this celestial canvas," +
4882    "creating a scene so serene and beautiful that it almost seems to pause time itself." +
4883    "As the sun begins to set, casting a warm golden hue across the sky," +
4884    "the world seems to slow down and breathe a sigh of relief. The sky is painted with hues of orange, " +
4885    " pink, and lavender, creating a breathtaking tapestry that stretches as far as the eye can see." +
4886    "The air is filled with the sweet scent of blooming flowers, mingling with the earthy aroma of freshly turned soil." +
4887    "it casts a warm," +
4888    "golden hue that spreads like liquid amber across the vast expanse of the sky." +
4889    "The once-blue heavens gradually transform, "
4890  @State maxLineList: (number | undefined)[] = [2, 6, undefined]
4891  @State maxLineIndex: number = 0
4892  @State maxLineStringList: (string)[] = ["2", "6", "undefined"]
4893  richEditorStyledString: MutableStyledString = new MutableStyledString("");
4894  controller1: RichEditorController = new RichEditorController()
4895  controller2: TextInputController = new TextInputController()
4896  controller3: RichEditorController = new RichEditorController()
4897  controller4: RichEditorStyledStringController = new RichEditorStyledStringController();
4898  controller: RichEditorController = new RichEditorController();
4899  option: RichEditorOptions = { controller: this.controller };
4900
4901  build() {
4902    Column() {
4903      Text("Current maxLength value: 7")
4904        .margin(10)
4905        .fontSize(25)
4906      Row() {
4907        Button("Insert 1-Character Image")
4908          .onClick(() => {
4909            this.controller1.addImageSpan($r("app.media.app_icon"),
4910              {
4911                imageStyle:
4912                {
4913                  size: ["57px", "57px"]
4914                }
4915              })
4916          })
4917        Button("Insert 2-Character Image")
4918          .onClick(() => {
4919            this.controller1.addSymbolSpan($r("sys.symbol.ohos_trash"),
4920              {
4921                style:
4922                {
4923                  fontSize: 30
4924                }
4925              })
4926          })
4927          .margin({ left: 20 })
4928      }
4929
4930      RichEditor({ controller: this.controller1 })
4931        .width('95%')
4932        .margin(10)
4933        .height(60)
4934        .maxLength(7)
4935        .backgroundColor('rgb(240,250,255)')
4936      Text("Current maxLine value: " + this.maxLineStringList[this.maxLineIndex]).margin(10)
4937        .fontSize(25)
4938      Button("Change maxLines").onClick(() => {
4939        this.maxLineIndex++
4940        if (this.maxLineIndex > this.maxLineList.length - 1) {
4941          this.maxLineIndex = 0
4942        }
4943      })
4944      RichEditor({ controller: this.controller3 })
4945        .onReady(() => {
4946          this.controller3.addTextSpan(this.text,
4947            {
4948              style:
4949              {
4950                fontColor: 'rgb(0,74,175)'
4951              }
4952            })
4953        })
4954        .margin(10)
4955        .width('95%')
4956        .maxLines(this.maxLineList[this.maxLineIndex])
4957        .backgroundColor('rgb(240,250,255)')
4958    }
4959  }
4960}
4961```
4962
4963
4964### Example 26: Setting the Drag Preview and Drag Shadow for a Custom Layout
4965This example shows how to use **addBuilderSpan** to configure the drag preview and drag shadow for a custom layout in drag-and-drop scenarios.
4966
4967```ts
4968// xxx.ets
4969import { ColorMetrics } from '@kit.ArkUI';
4970
4971@Entry
4972@Component
4973struct richEditorNew03 {
4974  controller: RichEditorController = new RichEditorController();
4975  options: RichEditorOptions = { controller: this.controller }
4976  build() {
4977    Column({ space: 10 }) {
4978      Column() {
4979        RichEditor(this.options)
4980          .onReady(() => {
4981            this.controller.addBuilderSpan(() => {
4982              this.placeholderBuilder()
4983            }, {
4984              offset: -1,
4985              dragBackgroundColor: ColorMetrics.rgba(0xff, 0x80, 0, 0xff),
4986              isDragShadowNeeded: false
4987            })
4988            this.controller.addBuilderSpan(() => {
4989              this.placeholderBuilder()
4990            }, {
4991              offset: -1,
4992              dragBackgroundColor: ColorMetrics.resourceColor("#ffff0000")
4993                .blendColor(ColorMetrics.resourceColor("#ff00ff00")),
4994              isDragShadowNeeded: true
4995            })
4996            this.controller.addBuilderSpan(() => {
4997              this.placeholderBuilder()
4998            }, { offset: -1 })
4999          })
5000          .borderWidth(1)
5001          .width("100%")
5002          .height("50%")
5003          .margin(50)
5004      }
5005      .width('100%')
5006      .margin({top:100})
5007    }
5008  }
5009
5010  @Builder
5011  placeholderBuilder() {
5012    Row() {
5013      Text('This is a BuilderSpan, not plain text content')
5014        .fontSize(22)
5015        .copyOption(CopyOptions.InApp)
5016    }
5017  }
5018}
5019```
5020
5021
5022### Example 27: Setting the URL Style for Text
5023This example demonstrates how to add **UrlStyle** in the **addTextSpan** and **updateSpanStyle** APIs to enable text to be clickable and link to a URL.
5024
5025```ts
5026// xxx.ets
5027
5028@Entry
5029@Component
5030struct RichEditorExample {
5031  controller: RichEditorController = new RichEditorController();
5032  options: RichEditorOptions = { controller: this.controller };
5033  styledStringController: RichEditorStyledStringController = new RichEditorStyledStringController();
5034  styledStringOptions: RichEditorStyledStringOptions = { controller: this.styledStringController };
5035
5036  build() {
5037    Column() {
5038      Row() {
5039        Button("Add Example Url").onClick(() => {
5040          this.controller.addTextSpan("Example URL", {
5041            urlStyle: { url: "https://www.example.com" }
5042          })
5043        })
5044        Button("Clear Url").onClick(() => {
5045          this.controller.updateSpanStyle({
5046            start: 0,
5047            textStyle: {},
5048            urlStyle: { url: "" }
5049          })
5050        })
5051      }
5052
5053      Row() {
5054        RichEditor(this.options)
5055          .height('35%')
5056          .border({ width: 1, color: Color.Blue })
5057      }
5058
5059      Row() {
5060        RichEditor(this.styledStringOptions)
5061          .height('35%')
5062          .border({ width: 1, color: Color.Red })
5063      }
5064    }
5065  }
5066}
5067```
5068