1# Rich Text (RichEditor) 2**RichEditor** is a component that supports interactive text editing and mixture of text and imagery. It is typically used to handle user inputs with mixed content, such as comment sections that allow for image input. For details, see RichEditor](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md). 3 4## Creating a RichEditor Component 5You create a **RichEditor** component by calling an API, which varies depending on the type of component you want to create. 6 7### Creating a RichEditor Component Without Using a Styled String 8```ts 9RichEditor(value: RichEditorOptions) 10``` 11Creates a **RichEditor** component with the initialization options specified by **RichEditorOptions**. 12 13```ts 14controller: RichEditorController = new RichEditorController(); 15options: RichEditorOptions = { controller: this.controller }; 16 17RichEditor(this.options) 18 .onReady(() => { 19 this.controller.addTextSpan('Create a RichEditor component without using a styled string.', { 20 style: { 21 fontColor: Color.Black, 22 fontSize: 15 23 } 24 }) 25 }) 26``` 27 28 29### Creating a RichEditor Component Using a Styled String 30```ts 31RichEditor(options: RichEditorStyledStringOptions) 32``` 33 34Creates a **RichEditor** component with the initialization options specified by **RichEditorStyledStringOptions**. 35 36```ts 37mutableStyledString: MutableStyledString = new MutableStyledString("Create a RichEditor component using a styled string.", 38 [{ 39 start: 0, 40 length: 5, 41 styledKey: StyledStringKey.FONT, 42 styledValue: this.fontStyle 43 }]); 44 45controller: RichEditorStyledStringController = new RichEditorStyledStringController(); 46options: RichEditorStyledStringOptions = {controller: this.controller}; 47 48RichEditor(this.options) 49 .onReady(() => { 50 this.controller.setStyledString(this.mutableStyledString); 51 }) 52``` 53 54 55## Setting Attributes 56 57### Setting the Custom Context Menu on Text Selection 58 59You can set custom context menu on text selection using the [bindSelectionMenu](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#bindselectionmenu) API, which includes the following parameters: 60 61**spanType**: type of the menu, with the default being text.<br>**content**: content of the menu.<br>**responseType**: response type of the menu, with the default being a long press.<br>**options**: options of the menu, allowing you to set callbacks for when the menu appears or disappears. 62 63If the custom menu is too long, embed a **Scroll** component to prevent the keyboard from being blocked. 64 65```ts 66RichEditor(this.options) 67 .onReady(() => { 68 this.controller.addTextSpan('The component has a custom menu that can be triggered by a long press.', { 69 style: { 70 fontColor: Color.Black, 71 fontSize: 18 72 } 73 }) 74 }) 75 .bindSelectionMenu(RichEditorSpanType.TEXT, this.SystemMenu, ResponseType.LongPress, { 76 onDisappear: () => { 77 this.sliderShow = false 78 } 79 }) 80 .width(300) 81 .height(300) 82 83@Builder 84SystemMenu() { 85 Column() { 86 Menu() { 87 if (this.controller) { 88 MenuItemGroup() { 89 MenuItem({ 90 startIcon: this.theme.cutIcon, 91 content: "Cut", 92 labelInfo: "Ctrl+X", 93 }) 94 MenuItem({ 95 startIcon: this.theme.copyIcon, 96 content: "Copy", 97 labelInfo: "Ctrl+C" 98 }) 99 MenuItem({ 100 startIcon: this.theme.pasteIcon, 101 content: "Paste", 102 labelInfo: "Ctrl+V" 103 }) 104 } 105 } 106 } 107 .radius(this.theme.containerBorderRadius) 108 .clip(true) 109 .backgroundColor(Color.White) 110 .width(this.theme.defaultMenuWidth) 111 } 112 .width(this.theme.defaultMenuWidth) 113} 114``` 115 116 117 118### Setting the Color of the Caret and Selection Handle in the Text Box 119 120You can set the color of the caret and selection handle in the text box using the [caretColor](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#caretcolor12) API. 121 122```ts 123RichEditor(this.options) 124 .onReady(() => { 125 this.controller.addTextSpan('The component has the color set for the caret and selection handle.', { 126 style: { 127 fontColor: Color.Black, 128 fontSize: 15 129 } 130 }) 131 }) 132 .caretColor(Color.Orange) 133 .width(300) 134 .height(300) 135``` 136 137 138 139### Setting Placeholder Text 140 141You can set the placeholder text, which is displayed when there is no input, using the [placeholder](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#placeholder12) API. 142 143In the API, **value** indicates the placeholder text displayed when there is no input; **style** indicates the font style for the placeholder text. If not specified, the style follows the theme settings. 144 145```ts 146RichEditor(this.options) 147 .placeholder("Enter your content here", { 148 fontColor: Color.Gray, 149 font: { 150 size: 15, 151 weight: FontWeight.Normal, 152 family: "HarmonyOS Sans", 153 style: FontStyle.Normal 154 } 155 }) 156 .width(300) 157 .height(300) 158``` 159 160 161 162For details about all available attributes, see [RichEditor Attributes](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#attributes). 163 164## Adding Events 165### Adding a Callback for Component Initialization 166 167Use the [onReady](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onready) API to add a callback that is invoked after the component has been initialized. 168 169In the API, **callback** indicates the callback invoked when the **RichEditor** component has completed initialization. 170 171```ts 172RichEditor(this.options) 173 .onReady(() => { 174 this.controller.addTextSpan('The onReady callback content is preset text within the component.', { 175 style: { 176 fontColor: Color.Black, 177 fontSize: 15 178 } 179 }) 180 }) 181``` 182 183 184 185### Adding a Callback for Content Selection 186 187Use the [onSelect](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onselect) API to add a callback that is invoked when content within the component is selected. 188 189In **callback**, [RichEditorSelection](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorselection) provides information about all the selected content. 190 191The callback can be invoked in either of the following ways: (1) If content is selected with the mouse left button, the callback is invoked after the left button is released. (2) If content is selected with a finger, the callback is invoked after the finger is lifted. 192 193```ts 194RichEditor(this.options) 195 .onReady(() => { 196 this.controller.addTextSpan('Select this text to invoke the onSelect callback.', { 197 style: { 198 fontColor: Color.Black, 199 fontSize: 15 200 } 201 }) 202 }) 203 .onSelect((value: RichEditorSelection) => { 204 this.controller1.addTextSpan(JSON.stringify(value), { 205 style: { 206 fontColor: Color.Gray, 207 fontSize: 10 208 } 209 }) 210 }) 211 .width(300) 212 .height(50) 213Text('View callback content:').fontSize(10).fontColor(Color.Gray).width(300) 214RichEditor(this.options1) 215 .width(300) 216 .height(70) 217 ``` 218 219 220 221### Adding Callbacks for Before and After Text and Image Changes 222 223Use the [onWillChange](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onwillchange12) API to add a callback invoked before text or image changes. Use the [onDidChange](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#ondidchange12) API to add a callback invoked after text or image changes. 224 225In the **onWillChange** callback, [RichEditorChangeValue](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorchangevalue12) provides information about the text and image change; a boolean value indicates whether the change is allowed (**true**) or not allowed (**false**). 226 227In the **onDidChange** callback, [OnDidChangeCallback](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#ondidchangecallback12) provides the content range before and after the text or image change. 228 229The **RichEditor** component constructed with [RichEditorStyledStringOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorstyledstringoptions12) does not support these two types of callbacks. 230 231```ts 232RichEditor(this.options) 233 .onReady(() => { 234 this.controller.addTextSpan('The callback is invoked before the text or image change.\nThe callback is invoked after the text or image change.', { 235 style: { 236 fontColor: Color.Black, 237 fontSize: 15 238 } 239 }) 240 }) 241 .onWillChange((value: RichEditorChangeValue) => { 242 this.controller1.addTextSpan('The callback is invoked before the text or image change: \n' + JSON.stringify(value), { 243 style: { 244 fontColor: Color.Gray, 245 fontSize: 10 246 } 247 }) 248 return true; 249 }) 250 .onDidChange((rangeBefore: TextRange, rangeAfter: TextRange) => { 251 this.controller1.addTextSpan('\nThe callback is invoked after the text or image change: \nrangeBefore: ' + JSON.stringify(rangeBefore) + '\nrangeAfter: ' + JSON.stringify(rangeBefore), { 252 style: { 253 fontColor: Color.Gray, 254 fontSize: 10 255 } 256 }) 257 return true; 258 }) 259 .width(300) 260 .height(50) 261Text('View callback content:').fontSize(10).fontColor(Color.Gray).width(300) 262RichEditor(this.options1) 263 .width(300) 264 .height(70) 265``` 266 267 268 269### Adding Callbacks for Before and After Content Input in the Input Method 270 271Use the [aboutToIMEInput](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#abouttoimeinput) API to add a callback invoked when content is about to be entered in the input method. Use the [onIMEInputComplete](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onimeinputcomplete) method to add a callback invoked when text input in the input method is complete. 272 273In the **aboutToIMEInput** callback, [RichEditorInsertValue](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorinsertvalue) provides information about the content to be entered in the input method; a boolean value indicates whether the content is inserted (**true**) or not (**false**). 274 275In the **onIMEInputComplete** callback, [RichEditorTextSpanResult](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditortextspanresult) provides information about the text span after the text input is completed. 276 277The **RichEditor** component constructed with [RichEditorStyledStringOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorstyledstringoptions12) does not support these two types of callbacks. 278 279```ts 280RichEditor(this.options) 281 .onReady(() => { 282 this.controller.addTextSpan('The callback is invoked before content input in the input method.\nThe callback is invoked when text input in the input method is complete.' , { 283 style: { 284 fontColor: Color.Black, 285 fontSize: 15 286 } 287 }) 288 }) 289 .aboutToIMEInput((value: RichEditorInsertValue) => { 290 this.controller1.addTextSpan('The callback is invoked before content input in the input method: \n'+JSON.stringify(value), { 291 style: { 292 fontColor: Color.Gray, 293 fontSize: 10 294 } 295 }) 296 return true; 297 }) 298 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 299 this.controller1.addTextSpan('The callback is invoked when text input in the input method is complete: \n'+ JSON.stringify(value), { 300 style: { 301 fontColor: Color.Gray, 302 fontSize: 10 303 } 304 }) 305 return true; 306 }) 307 .width(300) 308 .height(50) 309Text('View callback content:').fontSize(10).fontColor(Color.Gray).width(300) 310RichEditor(this.options1) 311 .width(300) 312 .height(70) 313``` 314 315 316 317### Adding a Callback for Before Paste Completion 318 319Use the [onPaste](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#onpaste11) API to add a callback invoked when the paste is about to be completed. 320 321In the API, **callback** is used to define the user paste event. 322 323By default, only plain text can be pasted. You can use this API to override the default system behavior so that both images and text can be pasted. 324 325```ts 326RichEditor(this.options) 327 .onReady(() => { 328 this.controller.addTextSpan('Copy and paste operations on this text trigger the corresponding callbacks.', { 329 style: { 330 fontColor: Color.Black, 331 fontSize: 15 332 } 333 }) 334 }) 335 .onPaste(() => { 336 this.controller1.addTextSpan ('The onPaste callback is invoked.\n', { 337 style: { 338 fontColor: Color.Gray, 339 fontSize: 10 340 } 341 }) 342 }) 343 .width(300) 344 .height(70) 345``` 346 347### Adding a Callback for Before Cut Completion 348 349Use the [onCut](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#oncut12) API to add a callback invoked when text is about to be cut. 350 351In the API, **callback** is used to define the user cut event. 352 353By default, only plain text can be cut. You can use this API to override the default system behavior so that both images and text can be cut. 354 355```ts 356RichEditor(this.options) 357 .onReady(() => { 358 this.controller.addTextSpan('Copy and paste operations on this text trigger the corresponding callbacks.', { 359 style: { 360 fontColor: Color.Black, 361 fontSize: 15 362 } 363 }) 364 }) 365 .onCut(() => { 366 this.controller1.addTextSpan ('The onCut callback is invoked.\n', { 367 style: { 368 fontColor: Color.Gray, 369 fontSize: 10 370 } 371 }) 372 }) 373 .width(300) 374 .height(70) 375``` 376 377### Adding a Callback for Before Copy Completion 378 379Use the [onCopy](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#oncopy12) API to add a callback invoked when text is about to be copied. 380 381In the API, **callback** is used to define the user copy event. 382 383By default, only plain text can be copied. You can use this API to override the default system behavior so that both images and text can be copied. 384 385```ts 386RichEditor(this.options) 387 .onReady(() => { 388 this.controller.addTextSpan('Copy and paste operations on this text trigger the corresponding callbacks.', { 389 style: { 390 fontColor: Color.Black, 391 fontSize: 15 392 } 393 }) 394 }) 395 .onCopy(() => { 396 this.controller1.addTextSpan ('The onCopy callback is invoked.\n', { 397 style: { 398 fontColor: Color.Gray, 399 fontSize: 10 400 } 401 }) 402 }) 403 .width(300) 404 .height(70) 405``` 406 407 408 409 410For details about all available events, see [RichEditor Events](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#events). 411 412## Setting the Typing Style 413 414Use the [setTypingStyle](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#settypingstyle12) API to set the typing style. 415 416In the API, **value** indicates the preset typing style. 417 418```ts 419RichEditor(this.options) 420 .onReady(() => { 421 this.controller.addTextSpan('Click the button to change the preset typing style.', { 422 style: { 423 fontColor: Color.Black, 424 fontSize: 15 425 } 426 }) 427 }) 428 .width(300) 429 .height(60) 430Button('setTypingStyle', { 431 buttonStyle: ButtonStyleMode.NORMAL 432 }) 433 .height(30) 434 .fontSize(13) 435 .onClick(() => { 436 this.controller.setTypingStyle({ 437 fontWeight: 'medium', 438 fontColor: Color.Pink, 439 fontSize: 15, 440 fontStyle: FontStyle.Italic, 441 decoration: { 442 type: TextDecorationType.Underline, 443 color: Color.Gray 444 } 445 }) 446 }) 447``` 448 449 450 451## Setting Highlight for Selected Content 452 453Use the [setSelection](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#setselection12) API to configure the component to highlight the background of the selected portion. 454 455In the API:<br>**selectionStart**: start position of the selection.<br>selectionEnd: end position of the selection. If both **selectionStart** and **selectionEnd** are set to **-1**, the entire content is selected. 456 457If this API is called when the text box is not focused, the selected effect is not displayed. 458 459```ts 460RichEditor(this.options) 461 .onReady(() => { 462 this.controller.addTextSpan('Click the button to select the text at positions 0 to 2 here.', { 463 style: { 464 fontColor: Color.Black, 465 fontSize: 15 466 } 467 }) 468 }) 469 .width(300) 470 .height(60) 471Button('setSelection(0,2)', { 472 buttonStyle: ButtonStyleMode.NORMAL 473 }) 474 .height(30) 475 .fontSize(13) 476 .onClick(() => { 477 this.controller.setSelection(0, 2) 478 }) 479``` 480 481 482 483## Adding a Text Span 484 485In addition to directly entering content into the component, you can also add a text span using the [addTextSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addtextspan) API. 486 487In the API, **value** indicates the text content to add, and **options** indicates the text options, which include the offset position where the text is added and the text style information ([RichEditorParagraphStyle](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditortextspanoptions)). 488 489If the cursor in the component is blinking, the cursor position is updated to be after the inserted text span. 490 491```ts 492RichEditor(this.options) 493 .onReady(() => { 494 this.controller.addTextSpan('Click the button to add text here.', { 495 style: { 496 fontColor: Color.Black, 497 fontSize: 15 498 } 499 }) 500 }) 501 .width(300) 502 .height(100) 503Button('addTextSpan', { 504 buttonStyle: ButtonStyleMode.NORMAL 505 }) 506 .height(30) 507 .fontSize(13) 508 .onClick(() => { 509 this.controller.addTextSpan('Add text.') 510 }) 511``` 512 513 514 515## Adding an Image Span 516 517Use the [addImageSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addimagespan) API to add an image span. 518 519In the API, **value** indicates the image content to be added, and **options** indicates the image options, which include the offset position where the image is added and the image style information ([RichEditorImageSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorimagespanoptions)). 520 521Adds an image span. If the cursor in the component is blinking, the cursor position is updated to be after the inserted image span. 522 523```ts 524RichEditor(this.options) 525 .onReady(() => { 526 this.controller.addTextSpan('Click the button to add an image here.', { 527 style: { 528 fontColor: Color.Black, 529 fontSize: 15 530 } 531 }) 532 }) 533 .width(300) 534 .height(100) 535Button('addImageSpan', { 536 buttonStyle: ButtonStyleMode.NORMAL 537 }) 538 .height(30) 539 .fontSize(13) 540 .onClick(() => { 541 this.controller.addImageSpan($r("app.media.startIcon"), { 542 imageStyle: { 543 size: ["57px", "57px"] 544 } 545 }) 546 }) 547``` 548 549 550 551## Adding a Builder Span 552Use the [addBuilderSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addbuilderspan11) API to add a builder span. 553 554In the API, **value** indicates the content created by the builder, and **options** indicates the builder options, which allow you to set the index of this builder in the **RichEditor** component through [RichEditorBuilderSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorbuilderspanoptions11). Each text character is considered a single unit. 555 556```ts 557@Builder 558TextBuilder() { 559 Row() { 560 Image($r('app.media.startIcon')).width(50).height(50).margin(16) 561 Column() { 562 Text("Text.txt").fontWeight (FontWeight.Bold).fontSize(16) 563 Text("123.45KB").fontColor('#8a8a8a').fontSize(12) 564 }.alignItems(HorizontalAlign.Start) 565 }.backgroundColor('#f4f4f4') 566 .borderRadius("20") 567 .width(220) 568} 569 570Button('addBuilderSpan', { 571 buttonStyle: ButtonStyleMode.NORMAL 572 }) 573 .height(30) 574 .fontSize(13) 575 .onClick(() => { 576 this.my_builder = () => { 577 this.TextBuilder() 578 } 579 this.controller.addBuilderSpan(this.my_builder) 580 }) 581``` 582 583 584## Adding a Symbol Span 585 586Use the [addSymbolSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#addsymbolspan11) AOU to add a symbol span. 587 588In the API, **value** indicates the content of the symbol span, and **options** indicates options of the symbol span, which are used to set the offset position and style information of the symbol span ([RichEditorSymbolSpanOptions](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorsymbolspanoptions11)). 589 590If the cursor in the component is blinking, the cursor position is updated to be after the inserted symbol span. 591 592Currently, gestures, copying, and dragging are not supported for the symbol span. 593 594```ts 595RichEditor(this.options) 596 .onReady(() => { 597 this.controller.addTextSpan('Click the button to add a symbol here.', { 598 style: { 599 fontColor: Color.Black, 600 fontSize: 15 601 } 602 }) 603 }) 604 .width(300) 605 .height(100) 606Button('addSymbolSpan', { 607 buttonStyle: ButtonStyleMode.NORMAL 608 }) 609 .height(30) 610 .fontSize(13) 611 .onClick(() => { 612 this.controller.addSymbolSpan($r("sys.symbol.basketball_fill"), { 613 style: { 614 fontSize: 30 615 } 616 }) 617 }) 618``` 619 620 621## Obtaining Span Information 622 623Use the [getSpans](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#getspans) API to obtain the span information of the component. 624 625In the API, **value** indicates the range of the target span. The return value is an array of either [RichEditorTextSpanResult](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditortextspanresult) or [RichEditorImageSpanResult](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md#richeditorimagespanresult), which includes information about text and image spans. 626 627```ts 628RichEditor(this.options) 629 .onReady(() => { 630 this.controller.addTextSpan('Click the button to obtain the span information.', { 631 style: { 632 fontColor: Color.Black, 633 fontSize: 15 634 } 635 }) 636 }) 637 .width(300) 638 .height(50) 639Text('View the return value of getSpans: ').fontSize (10).fontColor(Color.Gray).width(300) 640RichEditor(this.options1) 641 .width(300) 642 .height(50) 643Button('getSpans', { 644 buttonStyle: ButtonStyleMode.NORMAL 645 }) 646 .height(30) 647 .fontSize(13) 648 .onClick(() => { 649 this.controller1.addTextSpan(JSON.stringify(this.controller.getSpans()), { 650 style: { 651 fontColor: Color.Gray, 652 fontSize: 10 653 } 654 }) 655 656 }) 657``` 658 659