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