RichEditor

The <RichEditor> is a component that supports interactive text editing and mixture of text and imagery.

NOTE

This component is supported since API version 10. Updates will be marked with a superscript to indicate their earliest API version.

Drag effects such as floating for the <RichEditor> component can only be implemented through the onDragStart event.

Child Components

This component can contain the <Span> and <ImageSpan> child components.

APIs

RichEditor(value: RichEditorOptions)

Parameters

Name Type Mandatory Description
value RichEditorOptions Yes Options for initializing the component.

Attributes

The universal attributes are supported.

NOTE

The default value of the clip attribute is true.

The align attribute supports only the start, center, and end options.

Name Type Description
customKeyboard CustomBuilder Custom keyboard.
NOTE
When a custom keyboard is set, activating the text box opens the specified custom component, instead of the system input method.
The 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.
The custom keyboard is displayed on top of the current page, without compressing or raising the page.
The custom keyboard cannot obtain the focus, but it blocks gesture events.
By default, the custom keyboard is closed when the input component loses the focus.
copyOptions CopyOptions Whether copy and paste is allowed for text content.
Default value: CopyOptions.LocalDevice
NOTE
If copyOptions is set to CopyOptions.InApp or CopyOptions.LocalDevice, long pressing content in the component will display a shortcut menu, after which you can adjust the content selection scope and perform the desired operation, such as copy and select all.
If copyOptions is set to CopyOptions.None, copy and paste is not allowed.

Events

In addition to the universal events, the following events are supported.

Name Description
onReady(callback: () => void) Triggered when initialization of the component is completed.
onSelect(callback: (value: RichEditorSelection) => void) Triggered when selection (by clicking the left mouse button, highlighting the text to select, and releasing the left mouse button) is performed.
- value: information about all selected spans.
aboutToIMEInput(callback: (value: RichEditorInsertValue) => boolean) Triggered when content is about to be entered in the input method.
- value: content to be entered in the input method.
onIMEInputComplete(callback: (value: RichEditorTextSpanResult) => void) Triggered when text input is completed.
- value: text span information after text input is completed.
aboutToDelete(callback: (value: RichEditorDeleteValue) => boolean) Triggered when content is about to be deleted in the input method.
- value: information about the text span where the content to be deleted is located.
onDeleteComplete(callback: () => void) Triggered when deletion in the input method is completed.

RichEditorInsertValue

Describes the text to be inserted.

Name Type Mandatory Description
insertOffset number Yes Offset of the text to be inserted.
insertValue string Yes Content of the text to be inserted.

RichEditorDeleteValue

Name Type Mandatory Description
offset number Yes Offset of the text to be deleted.
direction RichEditorDeleteDirection Yes Direction of the delete operation.
length number Yes Length of the content to be deleted.
richEditorDeleteSpans Array<RichEditorTextSpanResult | RichEditorImageSpanResult> Yes Information about the text or image spans to be deleted.

RichEditorDeleteDirection

Enumerates the directions of the delete operation.

Name Description
BACKWARD Backward.
FORWARD Forward.

RichEditorTextSpanResult

Provides the text span information.

Name Type Mandatory Description
spanPosition RichEditorSpanPosition Yes Span position.
value string Yes Text span content.
textStyle RichEditorTextStyleResult Yes Text span style.
offsetInSpan [number, number] Yes Start and end positions of the valid content in the text span.

RichEditorSpanPosition

Provides the span position information.

Name Type Mandatory Description
spanIndex number Yes Span index.
spanRange [number, number] Yes Start and end positions of the span content in the <RichEditor> component.

RichEditorTextStyleResult

Provides the text span style information returned by the backend.

Name Type Mandatory Description
fontColor ResourceColor Yes Font color.
fontSize number Yes Font size.
fontStyle FontStyle Yes Font style.
fontWeight number Yes Font weight.
fontFamily string Yes Font family.
decoration {
type: TextDecorationType,
color: ResourceColor
}
Yes Style and color of the text decorative line.

RichEditorImageSpanResult

Provides the image information returned by the backend.

Name Type Mandatory Description
spanPosition RichEditorSpanPosition Yes Span position.
valuePixelMap PixelMap No Image content.
valueResourceStr ResourceStr No Image resource ID.
imageStyle RichEditorImageSpanStyleResult Yes Image style.
offsetInSpan [number, number] Yes Start and end positions of the image in the span.

RichEditorImageSpanStyleResult

Provides the image span style information returned by the backend.

Name Type Mandatory Description
size [number, number] Yes Width and height of the image.
verticalAlign ImageSpanAlignment Yes Vertical alignment mode of the image.
objectFit ImageFit Yes Scale mode of the image.

RichEditorOptions

Defines the options for initializing the <RichEditor> component.

Name Type Mandatory Description
controller RichEditorController Yes Controller for the <RichEditor> component.

RichEditorController

Implements the controller for the <RichEditor> component.

Objects to Import

controller: RichEditorController = new RichEditorController()

getCaretOffset

getCaretOffset(): number

Obtains the current cursor position.

Return value

Type Description
number Cursor position.

setCaretOffset

setCaretOffset(offset: number): boolean

Sets the cursor position.

Parameters

Name Type Mandatory Description
offset number Yes Offset of the cursor. If the value is out of the text range, the setting fails.

Return value

Type Description
boolean Whether the cursor position is set successfully.

addTextSpan

addTextSpan(value: string, options?: RichEditorTextSpanOptions): number

Adds a text span.

Parameters

Name Type Mandatory Description
value string Yes Text content.
options RichEditorTextSpanOptions No Text options.

Return value

Type Description
number Position of the added text span.

addImageSpan

addImageSpan(value: PixelMap | ResourceStr, options?: RichEditorImageSpanOptions): number

Adds an image span.

Parameters

Name Type Mandatory Description
value PixelMap|ResourceStr Yes Image content.
options RichEditorImageSpanOptions No Image options.

Return value

Type Description
number Position of the added image span.

updateSpanStyle

updateSpanStyle(value: RichEditorUpdateTextSpanStyleOptions | RichEditorUpdateImageSpanStyleOptions): void

Updates the text or image span style.
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.

Parameters

Name Type Mandatory Description
value RichEditorUpdateTextSpanStyleOptions | RichEditorUpdateImageSpanStyleOptions Yes Text or image span style options.

getSpans

getSpans(value?: RichEditorRange): Array<RichEditorTextSpanResult| RichEditorImageSpanResult>

Obtains span information.

Parameters

Name Type Mandatory Description
value RichEditorRange No Range of the target span.

Return value

Type Description
Array<RichEditorTextSpanResult | RichEditorImageSpanResult> Text and image span information.

deleteSpans

deleteSpans(value?: RichEditorRange): void

Deletes the text and image spans in a specified range.

Parameters

Name Type Mandatory Description
value RichEditorRange No Range of the target spans. If this parameter is omitted, all text and image spans will be deleted.

RichEditorSelection

Provides information about the selected content.

Name Type Mandatory Description
selection [number, number] Yes Range of the selected.
spans Array<RichEditorTextSpanResult| RichEditorImageSpanResult> Yes Span information.

RichEditorUpdateTextSpanStyleOptions

Defines the text span style options.

Name Type Mandatory Description
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.
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.
textStyle RichEditorTextStyle Yes Text style.

RichEditorUpdateImageSpanStyleOptions

Defines the image span style options.

Name Type Mandatory Description
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.
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.
imageStyle RichEditorImageSpanStyle Yes Image style.

RichEditorTextSpanOptions

Describes the options for adding a text span.

Name Type Mandatory Description
offset number No Position of the text span to be added. If this parameter is omitted, the text span will be added to the end of all text strings.
style RichEditorTextStyle No Style of the text span to be added. If this parameter is omitted, the default text style will be used.

RichEditorTextStyle

Provides the text style information.

Name Type Mandatory Description
fontColor ResourceColor No Font color.
Default value: Color.Black
fontSize 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.
Since API version 9, this API is supported in ArkTS widgets.
fontStyle FontStyle No Font style.
Default value: FontStyle.Normal
fontWeight FontWeight | number | string No Font weight.
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.
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.
Default value: FontWeight.Normal
fontFamily ResourceStr No Font family. The HarmonyOS Sans font and register custom fonts are supported.
Default font: 'HarmonyOS Sans'
decoration {
type: TextDecorationType,
color?: ResourceColor
}
No Style and color of the text decorative line.
Default value: {
type: TextDecorationType.None,
color: Color.Black
}

RichEditorImageSpanOptions

Defines the options for adding an image span.

Name Type Mandatory Description
offset number No Position of the image span to be added. If this parameter is omitted, the image span will be added to the end of all text strings.
imageStyle RichEditorImageSpanStyle No Image style. If this parameter is omitted, the default image style will be used.

RichEditorImageSpanStyle

Provides the image span style information.

Name Type Mandatory Description
size [Dimension, Dimension] No Width and height of the image.
verticalAlign ImageSpanAlignment No Vertical alignment mode of the image.
Default value: ImageSpanAlignment.BASELINE
objectFit ImageFit No Scale mode of the image.
Default value: ImageFit.Cover

RichEditorRange

Provides the span range information.

Name Type Mandatory Description
start number No Start position. If this parameter is left empty or set to a negative value, the value 0 will be used.
end number No End position. If this parameter is left empty or set to a negative value or any value beyond the range, it indicates infinity.

Example

Example 1

// xxx.ets
@Entry
@Component
struct Index {
  controller: RichEditorController = new RichEditorController()
  options: RichEditorOptions = { controller: this.controller }
  private start: number = -1
  private end: number = -1
  @State message: string = "[-1, -1]"
  @State content: string = ""

  build() {
    Column() {
      Column() {
        Text("selection range:").width("100%")
        Text() {
          Span(this.message)
        }.width("100%")
        Text("selection content:").width("100%")
        Text() {
          Span(this.content)
        }.width("100%")
      }
      .borderWidth(1)
      .borderColor(Color.Red)
      .width("100%")
      .height("20%")

      Row() {
        Button ("Update Style: Bold").onClick(() => {
          this.controller.updateSpanStyle({
            start: this.start,
            end: this.end,
            textStyle:
            {
              fontWeight: FontWeight.Bolder
            }
          })
        })
        Button("Obtain Selection").onClick(() => {
          this.content = "";
          this.controller.getSpans({
            start: this.start,
            end: this.end
          }).forEach(item => {
            if(typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined'){
              this.content += (item as RichEditorImageSpanResult).valueResourceStr
              this.content += "\n"
            } else {
              this.content += (item as RichEditorTextSpanResult).value
              this.content += "\n"
            }
          })
        })
        Button("Delete Selection").onClick(() => {
          this.controller.deleteSpans({
            start: this.start,
            end: this.end
          })
          this.start = -1
          this.end = -1
          this.message = "[" + this.start + ", " + this.end + "]"
        })
      }
      .borderWidth(1)
      .borderColor(Color.Red)
      .width("100%")
      .height("10%")

      Column() {
        RichEditor(this.options)
          .onReady(() => {
            this.controller.addTextSpan("0123456789",
              {
                style:
                {
                  fontColor: Color.Orange,
                  fontSize: 30
                }
              })
            this.controller.addImageSpan($r("app.media.icon"),
              {
                imageStyle:
                {
                  size: ["57px", "57px"]
                }
              })
            this.controller.addTextSpan("0123456789",
              {
                style:
                {
                  fontColor: Color.Black,
                  fontSize: 30
                }
              })
          })
          .onSelect((value: RichEditorSelection) => {
            this.start = value.selection[0]
            this.end = value.selection[1]
            this.message = "[" + this.start + ", " + this.end + "]"
          })
          .aboutToIMEInput((value: RichEditorInsertValue) => {
            console.log("---------------------- aboutToIMEInput ----------------------")
            console.log("insertOffset:" + value.insertOffset)
            console.log("insertValue:" + value.insertValue)
            return true
          })
          .onIMEInputComplete((value: RichEditorTextSpanResult) => {
            console.log("---------------------- onIMEInputComplete ---------------------")
            console.log("spanIndex:" + value.spanPosition.spanIndex)
            console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]")
            console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]")
            console.log("value:" + value.value)
          })
          .aboutToDelete((value: RichEditorDeleteValue) => {
            console.log("---------------------- aboutToDelete --------------------------")
            console.log("offset:" + value.offset)
            console.log("direction:" + value.direction)
            console.log("length:" + value.length)
            value.richEditorDeleteSpans.forEach(item => {
              console.log("---------------------- item --------------------------")
              console.log("spanIndex:" + item.spanPosition.spanIndex)
              console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]")
              console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]")
              if (typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
                console.log("image:" + (item as RichEditorImageSpanResult).valueResourceStr)
              } else {
                console.log("text:" + (item as RichEditorTextSpanResult).value)
              }
            })
            return true
          })
          .onDeleteComplete(() => {
            console.log("---------------------- onDeleteComplete ------------------------")
          })
          .borderWidth(1)
          .borderColor(Color.Green)
          .width("100%")
          .height("30%")
      }
      .borderWidth(1)
      .borderColor(Color.Red)
      .width("100%")
      .height("70%")
    }
  }
}

richeditor

Example 2

// xxx.ets
@Entry
@Component
struct RichEditorExample {
  controller: RichEditorController = new RichEditorController()

  // Create a custom keyboard component.
  @Builder CustomKeyboardBuilder() {
    Column() {
      Grid() {
        ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => {
          GridItem() {
            Button(item + "")
              .width(110).onClick(() => {
              this.controller.addTextSpan(item + '', {
                offset: this.controller.getCaretOffset(),
                style:
                {
                  fontColor: Color.Orange,
                  fontSize: 30
                }
              })
              this.controller.setCaretOffset(this.controller.getCaretOffset() + item.toString().length)
            })
          }
        })
      }.maxCount(3).columnsGap(10).rowsGap(10).padding(5)
    }.backgroundColor(Color.Gray)
  }

  build() {
    Column() {
      RichEditor({ controller: this.controller })
        // Bind the custom keyboard.
        .customKeyboard(this.CustomKeyboardBuilder()).margin(10).border({ width: 1 })
        .height(200)
        .borderWidth(1)
        .borderColor(Color.Red)
        .width("100%")
    }
  }
}

customKeyboard