1# RichEditor 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @carnivore233--> 5<!--Designer: @pssea--> 6<!--Tester: @mateng_Holtens--> 7<!--Adviser: @HelloCrease--> 8 9支持图文混排和文本交互式编辑的组件。 10 11> **说明:** 12> 13> 该组件从API version 10开始支持。后续版本新增内容,采用上角标单独标记该内容的起始版本。 14 15 16## 子组件 17 18不包含子组件。 19 20 21## 接口 22 23### RichEditor 24 25RichEditor(value: RichEditorOptions) 26 27**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 28 29**系统能力:** SystemCapability.ArkUI.ArkUI.Full 30 31**参数:** 32 33| 参数名 | 类型 | 必填 | 说明 | 34| ----- | --------------------------------------- | ---- | ----------- | 35| value | [RichEditorOptions](#richeditoroptions) | 是 | 富文本组件初始化选项。 | 36 37### RichEditor<sup>12+</sup> 38 39RichEditor(options: RichEditorStyledStringOptions) 40 41**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 42 43**系统能力:** SystemCapability.ArkUI.ArkUI.Full 44 45**参数:** 46 47| 参数名 | 类型 | 必填 | 说明 | 48| ----- | --------------------------------------- | ---- | ----------- | 49| options | [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) | 是 | 富文本组件初始化选项。 | 50 51## 属性 52 53除支持[通用属性](ts-component-general-attributes.md)外,还支持以下属性: 54 55> **说明:** 56> 57> align属性只支持上方、中间和下方位置的对齐方式。 58> 59> 不支持[borderImage](ts-universal-attributes-border-image.md#borderimage)属性。 60 61### customKeyboard 62 63customKeyboard(value: CustomBuilder, options?: KeyboardOptions) 64 65设置自定义键盘。 66 67当设置自定义键盘时,输入框激活后不会打开系统输入法,而是加载指定的自定义组件。 68 69自定义键盘的高度可以通过自定义组件根节点的height属性设置,宽度不可设置,使用系统默认值。 70 71自定义键盘无法获取焦点,但是会拦截手势事件。 72 73默认在输入控件失去焦点时,关闭自定义键盘。 74 75如果设备支持拍摄输入,设置自定义键盘后,该输入框会不支持拍摄输入。 76 77**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 78 79**系统能力:** SystemCapability.ArkUI.ArkUI.Full 80 81**参数:** 82 83| 参数名 | 类型 | 必填 | 说明 | 84| --------------------- | ------------------------------------------- | ---- | -------------------------------- | 85| value | [CustomBuilder](ts-types.md#custombuilder8) | 是 | 自定义键盘。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 86| options<sup>12+</sup> | [KeyboardOptions](#keyboardoptions12) | 否 | 设置自定义键盘是否支持避让功能。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 87 88### bindSelectionMenu 89 90bindSelectionMenu(spanType: RichEditorSpanType, content: CustomBuilder, responseType: ResponseType | RichEditorResponseType, 91 options?: SelectionMenuOptions) 92 93设置自定义选择菜单。自定义菜单超长时,建议内部嵌套[Scroll](./ts-container-scroll.md)组件使用,避免键盘被遮挡。 94 95**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 96 97**系统能力:** SystemCapability.ArkUI.ArkUI.Full 98 99**参数:** 100 101| 参数名 | 类型 | 必填 | 说明 | 102| ------------ | ------------------------------------------------------------ | ---- | --------------------------------------------------------- | 103| spanType | [RichEditorSpanType](#richeditorspantype) | 是 | 菜单的类型。<br/>默认值:<br/>RichEditorSpanType.TEXT | 104| content | [CustomBuilder](ts-types.md#custombuilder8) | 是 | 菜单的内容。 | 105| responseType | [ResponseType](ts-appendix-enums.md#responsetype8) \| [RichEditorResponseType](#richeditorresponsetype11) | 是 | 菜单的响应类型。<br/> 默认值:<br/>ResponseType.LongPress | 106| options | [SelectionMenuOptions](#selectionmenuoptions) | 否 | 菜单的选项。 | 107 108### copyOptions 109 110copyOptions(value: CopyOptions) 111 112设置组件是否支持文本内容可复制粘贴。 113 114从API version 20开始,RichEditor组件在执行复制或剪切操作时,会将HTML格式的内容添加到剪贴板中。 115 116- 仅支持TextSpan和ImageSpan向剪贴板中添加HTML内容,其他Span类型(如BuilderSpan、SymbolSpan、CustomSpan)则不能添加。 117 118- 设置RichEditor组件的属性字符串时,请参考属性字符串[toHtml](ts-universal-styled-string.md#tohtml14)接口文档,以了解支持转换为HTML的范围。 119 120copyOptions不为CopyOptions.None时,长按组件内容,会弹出文本选择菜单。如果通过bindSelectionMenu等方式自定义文本选择菜单,则会弹出自定义的菜单。 121 122设置copyOptions为CopyOptions.None时,禁用复制、剪切、翻译、分享、搜索、帮写功能,且不支持拖拽操作。 123 124**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 125 126**系统能力:** SystemCapability.ArkUI.ArkUI.Full 127 128**参数:** 129 130| 参数名 | 类型 | 必填 | 说明 | 131| ------ | ------------------------------------------------ | ---- | ------------------------------------------------------------ | 132| value | [CopyOptions](ts-appendix-enums.md#copyoptions9) | 是 | 组件支持文本内容是否可复制粘贴。<br/>默认值:CopyOptions.LocalDevice | 133 134### enableDataDetector<sup>11+</sup> 135 136enableDataDetector(enable: boolean) 137 138设置是否进行文本特殊实体识别。 139 140该接口依赖设备底层应具有文本识别能力,否则设置不会生效。 141 142当enableDataDetector设置为true且未指定[dataDetectorConfig](#datadetectorconfig11)属性时,系统将默认识别所有类型的实体,并将这些实体的color和decoration更改为预设样式: 143 144```ts 145color: '#ff007dff' 146decoration:{ 147 type: TextDecorationType.Underline, 148 color: '#ff007dff', 149 style: TextDecorationStyle.SOLID 150} 151``` 152 153触摸点击或鼠标右键点击实体时,会根据实体类型弹出对应的实体操作菜单,鼠标左键点击实体会直接响应菜单的第一个选项。 154 155对addBuilderSpan的节点文本,该功能不会生效。 156 157当copyOptions设置为CopyOptions.None时,点击实体弹出的菜单没有选择文本和复制功能。 158<!--RP1--><!--RP1End--> 159 160**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 161 162**系统能力:** SystemCapability.ArkUI.ArkUI.Full 163 164**参数:** 165 166| 参数名 | 类型 | 必填 | 说明 | 167| ------ | ------- | ---- | --------------------------------- | 168| enable | boolean | 是 | 使能文本识别。<br/>true表示使能文本特殊实体识别,false表示不使能文本特殊实体识别。<br/>默认值: false | 169 170### dataDetectorConfig<sup>11+</sup> 171 172dataDetectorConfig(config: TextDataDetectorConfig) 173 174设置文本特殊实体识别配置,可配置识别类型、实体显示样式,并可选择是否开启长按预览功能。 175 176需配合[enableDataDetector](#enabledatadetector11)一起使用,设置enableDataDetector为true时,dataDetectorConfig的配置才能生效。 177 178当有两个实体A、B重叠时,按以下规则保留实体: 179 1801. 若A ⊂ B,则保留B,反之则保留A。 181 1822. 当A ⊄ B且B ⊄ A时,若A.start < B.start,则保留A,反之则保留B。 183 184**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 185 186**系统能力:** SystemCapability.ArkUI.ArkUI.Full 187 188**参数:** 189 190| 参数名 | 类型 | 必填 | 说明 | 191| ------ | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ | 192| config | [TextDataDetectorConfig](ts-text-common.md#textdatadetectorconfig11对象说明) | 是 | 文本识别配置。| 193 194### enablePreviewText<sup>12+</sup> 195 196enablePreviewText(enable: boolean) 197 198设置是否开启预上屏功能。 199 200**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 201 202**系统能力:** SystemCapability.ArkUI.ArkUI.Full 203 204**参数:** 205 206| 参数名 | 类型 | 必填 | 说明 | 207| ------ | ------- | ---- | --------------------------------- | 208| enable | boolean | 是 | 使能预上屏功能。<br/>true表示开启,false表示不开启。<br/>默认值: true | 209 210> **说明:** 211> 212该接口在CAPI场景使用时默认关闭。可以在工程的module.json5中配置[metadata](../../../../application-dev/quick-start/module-structure.md#metadata对象内部结构)字段控制是否启用预上屏,配置如下: 213> ```json 214> "metadata": [ 215> { 216> "name": "can_preview_text", 217> "value": "true", 218> } 219> ] 220> ``` 221 222### placeholder<sup>12+</sup> 223 224placeholder(value: ResourceStr, style?: PlaceholderStyle) 225 226设置无输入时的提示文本。 227 228**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 229 230**系统能力:** SystemCapability.ArkUI.ArkUI.Full 231 232**参数:** 233 234| 参数名 | 类型 | 必填 | 说明 | 235| ------ | --------------------------------------- | ---- | ------------------------------------------------------- | 236| value | [ResourceStr](ts-types.md#resourcestr) | 是 | 无输入时的提示文本。 | 237| style | [PlaceholderStyle](#placeholderstyle12) | 否 | 提示文本的字体样式。<br/>缺省时默认跟随主题。 | 238 239### caretColor<sup>12+</sup> 240 241caretColor(value: ResourceColor) 242 243设置输入框光标、手柄颜色。 244 245**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 246 247**系统能力:** SystemCapability.ArkUI.ArkUI.Full 248 249**参数:** 250 251| 参数名 | 类型 | 必填 | 说明 | 252| ------ | ------------------------------------------ | ---- | -------------------------------------- | 253| value | [ResourceColor](ts-types.md#resourcecolor) | 是 | 输入框光标、手柄颜色。<br/>默认值:'#007DFF' | 254 255### selectedBackgroundColor<sup>12+</sup> 256 257selectedBackgroundColor(value: ResourceColor) 258 259设置文本选中的底板颜色。如果未设置不透明度,默认为20%不透明度。 260 261**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 262 263**系统能力:** SystemCapability.ArkUI.ArkUI.Full 264 265**参数:** 266 267| 参数名 | 类型 | 必填 | 说明 | 268| ------ | ------------------------------------------ | ---- | ------------------------------------------ | 269| value | [ResourceColor](ts-types.md#resourcecolor) | 是 | 文本选中的底板颜色。<br/>默认为20%不透明度。 | 270 271### editMenuOptions<sup>12+</sup> 272 273editMenuOptions(editMenu: EditMenuOptions) 274 275设置系统默认菜单的扩展项,允许配置扩展项的文本内容、图标和回调方法。 276 277调用[disableMenuItems](../arkts-apis-uicontext-textmenucontroller.md#disablemenuitems20)或[disableSystemServiceMenuItems](../arkts-apis-uicontext-textmenucontroller.md#disablesystemservicemenuitems20)接口屏蔽文本选择菜单内的系统服务菜单项时,editMenuOptions接口内回调方法[onCreateMenu](./ts-text-common.md#oncreatemenu12)的入参列表中不包含被屏蔽的菜单选项。 278 279**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 280 281**系统能力:** SystemCapability.ArkUI.ArkUI.Full 282 283**参数:** 284 285| 参数名 | 类型 | 必填 | 说明 | 286| ------ | --------------------------------------------- | ---- | --------------------------------------------- | 287| editMenu | [EditMenuOptions](ts-text-common.md#editmenuoptions) | 是 | 扩展菜单选项。 | 288 289### enterKeyType<sup>12+</sup> 290 291enterKeyType(value: EnterKeyType) 292 293设置软键盘输入法回车键类型。 294 295**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 296 297**系统能力:** SystemCapability.ArkUI.ArkUI.Full 298 299**参数:** 300 301| 参数名 | 类型 | 必填 | 说明 | 302| ------ | ------ | ---- | ----------------------------------- | 303| value | [EnterKeyType](ts-basic-components-textinput.md#enterkeytype枚举说明) | 是 | 软键盘输入法回车键类型。<br/>默认为EnterKeyType.NEW_LINE。 | 304 305### enableKeyboardOnFocus<sup>12+</sup> 306 307enableKeyboardOnFocus(isEnabled: boolean) 308 309设置RichEditor通过点击以外的方式获焦时,是否主动拉起软键盘。 310 311 312**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 313 314**系统能力:** SystemCapability.ArkUI.ArkUI.Full 315 316**参数:** 317 318| 参数名 | 类型 | 必填 | 说明 | 319| ------ | ------- | ---- | ----------------------------------------------------------- | 320| isEnabled | boolean | 是 | 通过点击以外的方式获焦时,是否主动拉起软键盘。<br/>true表示主动拉起软键盘,false表示不主动拉起软键盘。<br/>默认值: true | 321 322### barState<sup>13+</sup> 323 324barState(state: BarState) 325 326设置RichEditor滚动条的显示模式。 327 328**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 329 330**系统能力:** SystemCapability.ArkUI.ArkUI.Full 331 332**参数:** 333 334| 参数名 | 类型 | 必填 | 说明 | 335| ------ | ----------------------------------------- | ---- | ------------------------------------------------------ | 336| state | [BarState](ts-appendix-enums.md#barstate) | 是 | 输入框滚动条的显示模式。<br/>默认值:BarState.Auto | 337 338### maxLength<sup>18+</sup> 339 340maxLength(maxLength: Optional\<number\>) 341 342设置组件内容的最大长度。当内容(包含文本、图片、Symbol和Builder)的总长度达到此值时,将无法继续添加内容。 343 344**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 345 346**系统能力:** SystemCapability.ArkUI.ArkUI.Full 347 348**参数:** 349 350| 参数名 | 类型 | 必填 | 说明 | 351| ------ | ------ | ---- | ------------------------------------------------------------ | 352| maxLength | [Optional](ts-universal-attributes-custom-property.md#optionalt12)\<number> | 是 | 文本的最大输入字符数。<br/>默认值:Infinity,可以无限输入,支持undefined类型。<br/>**说明:** <br/>当不设置该属性或设置异常值时,取默认值,设置小数时,取整数部分。 | 353 354### maxLines<sup>18+</sup> 355 356maxLines(maxLines: Optional\<number\>) 357 358设置富文本可显示的最大行数。maxLines为可显示行数,当设置maxLines时,超出内容可滚动显示。同时设置组件高度和最大行数,组件高度优先生效。 359 360**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 361 362**系统能力:** SystemCapability.ArkUI.ArkUI.Full 363 364**参数:** 365 366| 参数名 | 类型 | 必填 | 说明 | 367| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ | 368| maxLines | [Optional](ts-universal-attributes-custom-property.md#optionalt12)\<number> | 是 | 设置富文本可显示的最大行数。maxLines为可显示行数,当设置maxLines时,超出内容可滚动显示。同时设置组件高度和最大行数,组件高度优先生效。<br/>默认值:Infinity,可以无限输入,支持undefined类型。 <br/>取值范围:(0, +∞) | 369 370### enableHapticFeedback<sup>13+</sup> 371 372enableHapticFeedback(isEnabled: boolean) 373 374设置RichEditor是否支持触感反馈。 375 376**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 377 378**系统能力:** SystemCapability.ArkUI.ArkUI.Full 379 380**参数:** 381 382| 参数名 | 类型 | 必填 | 说明 | 383| ------ | --------------------------------------------- |-----|-------------------------------------------------------------------------------------| 384| isEnabled | boolean | 是 | 控制触感反馈的开关。<br/>默认值:true。true表示开启触感反馈,false表示关闭触感反馈。<br/>**说明:**<br/>触感反馈需应用具备ohos.permission.VIBRATE权限,用户已启用触感反馈,且系统硬件支持时才会生效。 | 385 386### keyboardAppearance<sup>15+</sup> 387 388keyboardAppearance(appearance: Optional\<KeyboardAppearance\>) 389 390设置键盘外观。 391 392**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 393 394**系统能力:** SystemCapability.ArkUI.ArkUI.Full 395 396**参数:** 397 398| 参数名 | 类型 | 必填 | 说明 | 399| ------ | ----------------------------------------- | ---- | ------------------------------------------------------ | 400| appearance | [Optional](ts-universal-attributes-custom-property.md#optionalt12)\<[KeyboardAppearance](ts-text-common.md#keyboardappearance15枚举说明)\> | 是 | 键盘外观。<br/>默认值:KeyboardAppearance.NONE_IMMERSIVE | 401 402### stopBackPress<sup>18+</sup> 403 404stopBackPress(isStopped: Optional<boolean>) 405 406设置是否阻止返回键传递。 407 408**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 409 410**系统能力:** SystemCapability.ArkUI.ArkUI.Full 411 412**参数:** 413 414| 参数名 | 类型 | 必填 | 说明 | 415| ------ | --------------------------------------------- |-----|-------------------------------------------------------------------------------------| 416| isStopped | [Optional](ts-universal-attributes-custom-property.md#optionalt12)<boolean> | 是 | 是否阻止返回键。<br/>默认值:true,true表示阻止返回键,false表示不阻止返回键。<br/>**说明:** <br/>当不设置该属性或设置异常值时,取默认值。| 417 418### undoStyle<sup>20+</sup> 419 420undoStyle(style: Optional<UndoStyle>) 421 422设置撤销还原时是否保留原内容的样式。 423 424使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建RichEditor组件时,撤销还原时默认保留原内容样式,不受该接口设置的属性影响。 425 426**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 427 428**系统能力:** SystemCapability.ArkUI.ArkUI.Full 429 430**参数:** 431 432| 参数名 | 类型 | 必填 | 说明 | 433| ------ | --------------------------------------------- |-----|-------------------------------------------------------------------------------------| 434| style | [Optional](ts-universal-attributes-custom-property.md#optionalt12)<[UndoStyle](#undostyle20-1)> | 是 | 撤销还原是否保留原样式选项。默认值:UndoStyle.CLEAR_STYLE | 435 436### enableAutoSpacing<sup>20+</sup> 437 438enableAutoSpacing(enable: Optional\<boolean>) 439 440设置是否开启中文与西文的自动间距。 441 442**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 443 444**系统能力:** SystemCapability.ArkUI.ArkUI.Full 445 446**参数:** 447 448| 参数名 | 类型 | 必填 | 说明 | 449| ------ | ------- | ---- | ---------------------------------- | 450| enable | [Optional](ts-universal-attributes-custom-property.md#optionalt12)\<boolean> | 是 | 是否开启中文与西文的自动间距。<br/>true为开启自动间距,false为不开启。<br />默认值:false | 451 452## 事件 453 454除支持[通用事件](ts-component-general-events.md)外,还支持[OnDidChangeCallback](ts-text-common.md#ondidchangecallback12)、[StyledStringChangedListener](ts-text-common.md#styledstringchangedlistener12)、[StyledStringChangeValue](ts-text-common.md#styledstringchangevalue12)和以下事件: 455 456### onReady 457 458onReady(callback:Callback\<void\>) 459 460富文本组件初始化完成后触发回调。 461 462**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 463 464**系统能力:** SystemCapability.ArkUI.ArkUI.Full 465 466**参数:** 467 468| 参数名 | 类型 | 必填 | 说明 | 469| ----- | --------------------------------------- | ---- | ----------- | 470| callback |Callback\<void\> | 是 | 订阅富文本组件初始化完成的回调。 | 471 472### onSelect 473 474onSelect(callback:Callback\<[RichEditorSelection](#richeditorselection)\>) 475 476鼠标左键双击选中内容触发回调;松开鼠标左键再次触发回调。 477 478手指长按选中内容触发回调;松开手指再次触发回调。 479 480通过手指或鼠标连续修改选中区、三击选段场景,不回调onSelect。 481 482需要实时感知选中区变化的场景和使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件,请使用onSelectionChange接口。 483 484**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 485 486**系统能力:** SystemCapability.ArkUI.ArkUI.Full 487 488**参数:** 489 490| 参数名 | 类型 | 必填 | 说明 | 491| ------ | ------------------------------------------- | ---- | -------------------- | 492| callback | Callback\<[RichEditorSelection](#richeditorselection)\> | 是 | [RichEditorSelection](#richeditorselection)为选中的所有span信息。<br/>选择时触发的回调。 | 493 494### aboutToIMEInput 495 496aboutToIMEInput(callback:Callback\<[RichEditorInsertValue](#richeditorinsertvalue), boolean\>) 497 498输入法输入内容前触发回调。 499 500使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 501 502**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 503 504**系统能力:** SystemCapability.ArkUI.ArkUI.Full 505 506**参数:** 507 508| 参数名 | 类型 | 必填 | 说明 | 509| ------ | ------------------------------------------- | ---- | -------------------- | 510| callback | Callback\<[RichEditorInsertValue](#richeditorinsertvalue), boolean\> | 是 | [RichEditorInsertValue](#richeditorinsertvalue)为输入法将要输入内容信息。<br/>true:组件执行添加内容操作。<br/>false:组件不执行添加内容操作。<br/>输入法输入内容前的回调。| 511 512### onDidIMEInput<sup>12+</sup> 513 514onDidIMEInput(callback:Callback\<TextRange>) 515 516输入法输入完成后,触发回调。 517 518使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 519 520**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 521 522**系统能力:** SystemCapability.ArkUI.ArkUI.Full 523 524**参数:** 525 526| 参数名 | 类型 | 必填 | 说明 | 527| ------ | ------------------------------------------- | ---- | -------------------- | 528| callback | Callback\<[TextRange](ts-text-common.md#textrange12)\> | 是 | TextRange为输入法本次输入内容的范围。<br/>输入法完成输入时的回调。| 529 530 531### onIMEInputComplete 532 533onIMEInputComplete(callback:Callback\<[RichEditorTextSpanResult](#richeditortextspanresult)\>) 534 535输入法输入完成后,触发回调。 536 537该接口仅支持返回一个文本span的信息,当编辑操作涉及返回多个文本span信息时,建议使用[onDidIMEInput](#ondidimeinput12)接口。 538 539使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 540 541**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 542 543**系统能力:** SystemCapability.ArkUI.ArkUI.Full 544 545**参数:** 546 547| 参数名 | 类型 | 必填 | 说明 | 548| ------ | ------------------------------------------- | ---- | -------------------- | 549| callback | Callback\<[RichEditorTextSpanResult](#richeditortextspanresult)\> | 是 | [RichEditorTextSpanResult](#richeditortextspanresult)为输入法完成输入后的文本Span信息。<br/>输入法完成输入后的回调。| 550 551### aboutToDelete 552 553aboutToDelete(callback:Callback\<[RichEditorDeleteValue](#richeditordeletevalue), boolean\>) 554 555输入法删除内容前,触发回调。 556 557使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 558 559**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 560 561**系统能力:** SystemCapability.ArkUI.ArkUI.Full 562 563**参数:** 564 565| 参数名 | 类型 | 必填 | 说明 | 566| ------ | ------------------------------------------- | ---- | -------------------- | 567| callback | Callback\<[RichEditorDeleteValue](#richeditordeletevalue), boolean\> | 是 | [RichEditorDeleteValue](#richeditordeletevalue)为准备删除的内容所在的文本或者图片Span信息。<br/>true:组件执行删除操作。<br/>false:组件不执行删除操作。<br/>输入法删除内容前的回调,英文预上屏点击候选词时会执行该回调。| 568 569### onDeleteComplete 570 571onDeleteComplete(callback:Callback\<void\>) 572 573输入法删除内容后,触发回调。 574 575使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 576 577**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 578 579**系统能力:** SystemCapability.ArkUI.ArkUI.Full 580 581**参数:** 582 583| 参数名 | 类型 | 必填 | 说明 | 584| ----- | --------------------------------------- | ---- | ----------- | 585| callback |Callback\<void\> | 是 | 订阅输入法完成删除内容的回调。 | 586 587### onPaste<sup>11+</sup> 588 589onPaste(callback: [PasteEventCallback](#pasteeventcallback12) ) 590 591粘贴时,触发回调。开发者可以通过该方法,覆盖系统默认行为,实现图文的粘贴。 592 593**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 594 595**系统能力:** SystemCapability.ArkUI.ArkUI.Full 596 597**参数:** 598 599| 参数名 | 类型 | 必填 | 说明 | 600| ------ | ------- | ---- | ----------------------------- | 601| callback | [PasteEventCallback](#pasteeventcallback12) | 是 | 订阅粘贴时的回调。 | 602 603### onSelectionChange<sup>12+</sup> 604 605onSelectionChange(callback:Callback\<[RichEditorRange](#richeditorrange)\>) 606 607内容选择区域或编辑状态下的光标位置发生变化时,将触发该回调。光标位置变化时,回调中选择区域的起始和终止位置相等。 608 609**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 610 611**系统能力:** SystemCapability.ArkUI.ArkUI.Full 612 613**参数:** 614 615| 参数名 | 类型 | 必填 | 说明 | 616| ----- | --------------------------------------- | ---- | ----------- | 617| callback |Callback\<[RichEditorRange](#richeditorrange)\> | 是 | [RichEditorRange](#richeditorrange)为所有内容的选择区域起始和终止位置。<br/>订阅文本选择区域发生变化或编辑状态下光标位置发生变化时触发的回调。| 618 619### onEditingChange<sup>12+</sup> 620 621onEditingChange(callback: Callback\<boolean\>) 622 623组件内容的编辑状态发生变化时触发该回调函数。 624 625**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 626 627**系统能力:** SystemCapability.ArkUI.ArkUI.Full 628 629**参数:** 630 631| 参数名 | 类型 | 必填 | 说明 | 632| ----- | --------------------------------------- | ---- | ----------- | 633| callback | Callback\<boolean\> | 是 | true表示编辑态,false表示非编辑态。 | 634 635### onSubmit<sup>12+</sup> 636 637onSubmit(callback: SubmitCallback) 638 639按下软键盘输入法回车键时触发该回调。 640 641**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 642 643**系统能力:** SystemCapability.ArkUI.ArkUI.Full 644 645**参数:** 646 647| 参数名 | 类型 | 必填 | 说明 | 648| ------ | ------- | ---- | ----------------------------- | 649| callback | [SubmitCallback](#submitcallback12) | 是 | 订阅事件的回调。 | 650 651### onWillChange<sup>12+</sup> 652 653onWillChange(callback: Callback\<[RichEditorChangeValue](#richeditorchangevalue12) , boolean\>) 654 655在组件执行增删操作前,触发回调。 656 657使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 658 659**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 660 661**系统能力:** SystemCapability.ArkUI.ArkUI.Full 662 663**参数:** 664 665| 参数名 | 类型 | 必填 | 说明 | 666| -- | -- | -- | -- | 667| callback | Callback\<[RichEditorChangeValue](#richeditorchangevalue12) , boolean\> | 是 | [RichEditorChangeValue](#richeditorchangevalue12)为图文变化信息;boolean表示当前图文是否允许被更改,true:允许图文被更改;false:不允许图文被更改。 | 668 669### onDidChange<sup>12+</sup> 670 671onDidChange(callback: OnDidChangeCallback) 672 673在组件执行增删操作后,触发回调。如果文本实际未发生增删,则不触发该回调。 674 675使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件不支持该回调。 676 677**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 678 679**系统能力:** SystemCapability.ArkUI.ArkUI.Full 680 681**参数:** 682 683| 参数名 | 类型 | 必填 | 说明 | 684| -- | -- | -- | -- | 685| callback | [OnDidChangeCallback](ts-text-common.md#ondidchangecallback12) | 是 | 图文变化前后的内容范围。 | 686 687### onCut<sup>12+</sup> 688 689onCut(callback: Callback\<CutEvent\>) 690 691剪切时触发回调。开发者可以通过该方法,覆盖系统默认行为,实现图文的剪切。 692 693使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件,默认支持图文的剪切。 694 695**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 696 697**系统能力:** SystemCapability.ArkUI.ArkUI.Full 698 699**参数:** 700 701| 参数名 | 类型 | 必填 | 说明 | 702| ----- | --------------------------------------- | ---- | ----------- | 703| callback |Callback\<[CutEvent](#cutevent12)\> | 是 | 定义用户剪切事件。 | 704 705### onCopy<sup>12+</sup> 706 707onCopy(callback: Callback\<CopyEvent\>) 708 709复制时触发回调。开发者可以通过该方法,覆盖系统默认行为,实现图文的复制。 710 711使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件,默认支持图文的复制。 712 713**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 714 715**系统能力:** SystemCapability.ArkUI.ArkUI.Full 716 717**参数:** 718 719| 参数名 | 类型 | 必填 | 说明 | 720| ----- | --------------------------------------- | ---- | ----------- | 721| callback |Callback\<[CopyEvent](#copyevent12)\> | 是 | 定义用户复制事件。 | 722 723## RichEditorInsertValue 724 725插入文本的信息。 726 727**系统能力:** SystemCapability.ArkUI.ArkUI.Full 728 729| 名称 | 类型 | 只读 | 可选 | 说明 | 730| ------------ | ------ | ---- | ----|------ | 731| insertOffset | number | 否| 否 | 插入的文本偏移位置。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 732| insertValue | string | 否| 否 | 插入的文本内容。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 733| previewText<sup>12+</sup> | string | 否| 是 | 插入的预上屏文本内容。<br/> **原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 734 735 736## RichEditorDeleteValue 737 738删除操作和被删除内容的信息。 739 740**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 741 742**系统能力:** SystemCapability.ArkUI.ArkUI.Full 743 744| 名称 | 类型 | 只读 | 可选 | 说明 | 745| --------------------- | ---------------------------------------- | ---- | -----|-------------- | 746| offset | number | 否 | 否 | 删除内容的偏移位置。 | 747| direction | [RichEditorDeleteDirection](#richeditordeletedirection) | 否 | 否 | 删除操作的方向。 | 748| length | number | 否 | 否 | 删除内容长度。 | 749| richEditorDeleteSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult) \| [RichEditorImageSpanResult](#richeditorimagespanresult)> | 否 | 否 | 删除的文本或图片Span的信息。 | 750 751 752## RichEditorDeleteDirection 753 754删除方向。 755 756**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 757 758**系统能力:** SystemCapability.ArkUI.ArkUI.Full 759 760| 名称 | 说明 | 761| -------- | ---------- | 762| BACKWARD | 向后删除。 | 763| FORWARD | 向前删除。 | 764 765 766## RichEditorTextSpanResult 767 768文本Span信息。 769 770**系统能力:** SystemCapability.ArkUI.ArkUI.Full 771 772| 名称 | 类型 | 只读 | 可选 | 说明 | 773| ----------------------------- | ---------------------------------------- | ---- | ------------|---------- | 774| spanPosition | [RichEditorSpanPosition](#richeditorspanposition) | 否 | 否 | Span位置。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 775| value | string | 否 | 否 | 文本Span内容或Symbol的id。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 776| textStyle | [RichEditorTextStyleResult](#richeditortextstyleresult) | 否 | 否 | 文本Span样式信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 777| offsetInSpan | [number, number] | 否 | 否 | 文本Span内容里有效内容的起始和结束位置。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 778| valueResource<sup>11+</sup> | [Resource](ts-types.md#resource) | 否 | 是 | 组件SymbolSpan内容。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 779| symbolSpanStyle<sup>11+</sup> | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | 否 | 是 | 组件SymbolSpan样式信息。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 780| paragraphStyle<sup>12+</sup> | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 否 | 是 | 段落样式。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 781| previewText<sup>12+</sup> | string | 否 | 是 | 文本Span预上屏内容。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 782| urlStyle<sup>19+</sup> | [RichEditorUrlStyle](#richeditorurlstyle19) | 否 | 是 | url信息。<br/>默认值:undefined <br/>**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。| 783 784 785## RichEditorSpanPosition 786 787Span位置信息。 788 789**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 790 791**系统能力:** SystemCapability.ArkUI.ArkUI.Full 792 793| 名称 | 类型 | 只读 | 可选 | 说明 | 794| --------- | ---------------- |----| ---- | --------------------------- | 795| spanIndex | number | 否 | 否 | Span索引值。 | 796| spanRange | [number, number] | 否 | 否 | Span内容在RichEditor内的起始和结束位置。 | 797 798## RichEditorSpanType 799 800Span类型信息。 801 802**系统能力:** SystemCapability.ArkUI.ArkUI.Full 803 804| 名称 | 值 | 说明 | 805| ----- | ---- | ------------ | 806| TEXT | 0 | Span类型为文字。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 807| IMAGE | 1 | Span类型为图像。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 808| MIXED | 2 | Span类型为图文混合。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 809| BUILDER<sup>12+</sup> | 3 | Span类型为BuilderSpan。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 810| DEFAULT<sup>15+</sup> | 4 | 注册此类型的菜单,但未注册TEXT、IMAGE、MIXED、BUILDER菜单时,文字类型、图像类型、图文混合类型、BuilderSpan类型都会触发并显示此类型对应的菜单。 <br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。| 811 812## RichEditorResponseType<sup>11+</sup> 813 814菜单的响应类型。 815 816**系统能力:** SystemCapability.ArkUI.ArkUI.Full 817 818| 名称 | 值 | 说明 | 819| ----- | ---- | ------------ | 820| RIGHT_CLICK | 0 | 通过鼠标右键触发菜单弹出。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 821| LONG_PRESS | 1 | 通过长按触发菜单弹出。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 822| SELECT | 2 | 通过鼠标选中触发菜单弹出。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 823| DEFAULT<sup>15+</sup> | 3 | 注册此响应类型的菜单,但未注册RIGHT_CLICK、LONG_PRESS、SELECT响应类型的菜单时,通过鼠标右键、长按、鼠标选中都会触发菜单弹出。 <br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 | 824 825## UndoStyle<sup>20+</sup> 826 827撤销还原是否保留原样式选项。 828 829**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 830 831**系统能力:** SystemCapability.ArkUI.ArkUI.Full 832 833| 名称 | 值 | 说明 | 834| ----- | ---- | ------------ | 835| CLEAR_STYLE | 0 | 撤销还原内容不保留原样式。 | 836| KEEP_STYLE | 1 | 撤销还原内容保留原样式。 | 837 838## RichEditorTextStyleResult 839 840后端返回的文本样式信息。 841 842**系统能力:** SystemCapability.ArkUI.ArkUI.Full 843 844| 名称 | 类型 | 只读 | 可选 | 说明 | 845| ---------- | ---------------------------------------- | ---- | -------|----- | 846| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 否| 否 | 文本颜色。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 847| fontSize | number | 否| 否 | 字体大小,默认单位为fp。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 848| fontStyle | [FontStyle](ts-appendix-enums.md#fontstyle) | 否| 否 | 字体样式。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 849| fontWeight | number | 否| 否 | 字体粗细。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 850| fontFamily | string | 否| 否 | 字体列表。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 851| decoration | [DecorationStyleResult](ts-text-common.md#decorationstyleresult12) | 否| 否 | 文本装饰线样式信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 852| textShadow<sup>12+</sup> | Array<[ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions对象说明)> | 否| 是 | 文字阴影效果。<br/>**说明:**<br/>仅支持查询阴影模糊半径、颜色和偏移量。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 853| lineHeight<sup>12+</sup> | number | 否| 是 | 文本行高,默认单位为fp。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 854| letterSpacing<sup>12+</sup>| number | 否 | 是 | 文本字符间距,默认单位为fp。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 855| fontFeature<sup>12+</sup> | string | 否| 是 | 文字特性效果。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 856| halfLeading<sup>18+</sup> | boolean | 否 | 是 | 文本是否将行间距平分至行的顶部与底部。<br/>true表示将行间距平分至行的顶部与底部,false则不平分。<br/>默认值:false。<br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。| 857| textBackgroundStyle<sup>18+</sup> | [TextBackgroundStyle](ts-basic-components-span.md#textbackgroundstyle11对象说明) | 否 | 是 | 文本背景样式。<br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。| 858 859> **说明:** 860> 861> 在RichEditorTextStyle中,fontWeight是设置字体粗细的输入参数。 862> 而在RichEditorTextStyleResult中,会将之前设置的字体粗细转换为数字后返回。 863> 转换关系如下: 864> 865> | RichEditorTextStyle中的fontWeight | RichEditorTextStyleResult中的fontWeight | 866> | ---- | ----------------------------------- | 867> | 100 | 0 | 868> | 200 | 1 | 869> | 300 | 2 | 870> | 400 | 3 | 871> | 500 | 4 | 872> | 600 | 5 | 873> | 700 | 6 | 874> | 800 | 7 | 875> | 900 | 8 | 876> | Lighter | 12 | 877> | Normal | 10 | 878> | Regular | 14 | 879> | Medium | 13 | 880> | Bold | 9 | 881> | Bolder | 11 | 882> 883> RichEditorSymbolSpanStyle和RichEditorSymbolSpanStyleResult中fontWeight的转换关系, 884> 与RichEditorTextStyle和RichEditorTextStyleResult中fontWeight的转换关系一致。 885 886## RichEditorSymbolSpanStyleResult<sup>11+</sup> 887 888后端返回的SymbolSpan样式信息。 889 890**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 891 892**系统能力:** SystemCapability.ArkUI.ArkUI.Full 893 894| 名称 | 类型 | 只读 | 可选 | 说明 | 895| ------ | -------- | ---- | ------------------------------|-------- | 896| fontColor | Array\<[ResourceColor](ts-types.md#resourcecolor)\> | 否 | 否 | SymbolSpan组件颜色。<br/> 默认值:不同渲染策略下默认值不同。 | 897| fontSize | number \| string \| [Resource](ts-types.md#resource) | 否 | 否 | SymbolSpan组件大小,默认单位为fp。<br/>默认值:跟随主题。| 898| fontWeight | number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string | 否 | 否 | SymbolSpan组件粗细。<br/>number类型取值[100,900],取值间隔为100,默认为400,取值越大,字体越粗。<br/>string类型仅支持number类型取值的字符串形式,例如“400”,以及“bold”、“bolder”、“lighter”、“regular” 、“medium”分别对应FontWeight中相应的枚举值。<br/>默认值:FontWeight.Normal。| 899| renderingStrategy | [SymbolRenderingStrategy](ts-basic-components-symbolGlyph.md#symbolrenderingstrategy11枚举说明) | 否 | 否 | SymbolSpan组件渲染策略。<br/>默认值:SymbolRenderingStrategy.SINGLE。<br/> 900| effectStrategy | [SymbolEffectStrategy](ts-basic-components-symbolGlyph.md#symboleffectstrategy11枚举说明) | 否 | 否 | SymbolSpan组件动效策略。<br/>默认值:SymbolEffectStrategy.NONE。<br/> 901 902## RichEditorImageSpanResult 903 904后端返回的图片信息。 905 906**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 907 908**系统能力:** SystemCapability.ArkUI.ArkUI.Full 909 910| 名称 | 类型 | 只读 | 可选 | 说明 | 911|------------------|-------------------------------------------------------------------|-----|-------|-----------| 912| spanPosition | [RichEditorSpanPosition](#richeditorspanposition) | 否 | 否 | Span位置。| 913| valuePixelMap | [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md) | 否 | 是 | 图片内容。| 914| valueResourceStr | [ResourceStr](ts-types.md#resourcestr) | 否 | 是 | 图片资源id。| 915| imageStyle | [RichEditorImageSpanStyleResult](#richeditorimagespanstyleresult) | 否 | 否 | 图片样式。| 916| offsetInSpan | [number, number] | 否 | 否 | Span里图片的起始和结束位置。| 917 918## RichEditorImageSpanStyleResult 919 920后端返回的图片样式信息。 921 922**系统能力:** SystemCapability.ArkUI.ArkUI.Full 923 924| 名称 | 类型 | 只读 | 可选 | 说明 | 925| ------------- | ---------------------------------------- | ---- | -----|---- | 926| size | [number, number] | 否 | 否 | 图片的宽度和高度,单位为px。默认值:size的默认值与objectFit的值有关,不同的objectFit值对应的size默认值也不同。objectFit的值为Cover时,图片高度为组件高度减去组件上下内边距,图片宽度为组件宽度减去组件左右内边距。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 927| verticalAlign | [ImageSpanAlignment](ts-appendix-enums.md#imagespanalignment10) | 否 | 否 | 图片垂直对齐方式。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 928| objectFit | [ImageFit](ts-appendix-enums.md#imagefit) | 否 | 否 | 图片缩放类型。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 929| layoutStyle<sup>12+</sup> | [RichEditorLayoutStyle](#richeditorlayoutstyle11) | 否 | 是 | 图片布局风格。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 930 931## RichEditorLayoutStyle<sup>11+</sup> 932 933图片布局信息。 934 935**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 936 937**系统能力:** SystemCapability.ArkUI.ArkUI.Full 938 939|名称 |类型 | 只读 | 可选| 说明| 940| ------------- | ----------------------- | ---- | ----------|-------------------------------------------------- | 941|margin | [Dimension](ts-types.md#dimension10) \| [Margin](ts-types.md#margin) | 否| 是 | 外边距类型,用于描述组件不同方向的外边距。<br/>参数为Dimension类型时,四个方向外边距同时生效。| 942|borderRadius | [Dimension](ts-types.md#dimension10) \| [BorderRadiuses](ts-types.md#borderradiuses9) | 否 | 是 | 圆角类型,用于描述组件边框圆角半径。<br/>参数为Dimension类型时,不支持以Percentage形式设置。| 943 944## RichEditorOptions 945 946RichEditor初始化参数。 947 948**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 949 950**系统能力:** SystemCapability.ArkUI.ArkUI.Full 951 952| 名称 | 类型 | 只读 | 可选 | 说明 | 953| ---------- | ---------------------------------------- | ---- | ----|--- | 954| controller | [RichEditorController](#richeditorcontroller) | 否 | 否 | 富文本控制器。 | 955 956## RichEditorStyledStringOptions<sup>12+</sup> 957 958RichEditor初始化参数。 959 960**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 961 962**系统能力:** SystemCapability.ArkUI.ArkUI.Full 963 964| 名称 | 类型 | 只读 | 可选 | 说明 | 965| ---------- | ---------------------------------------- | ---- | ----|--- | 966| controller | [RichEditorStyledStringController](#richeditorstyledstringcontroller12) | 否 | 否 | 富文本控制器。 | 967 968## RichEditorChangeValue<sup>12+</sup> 969 970图文变化信息。 971 972**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 973 974**系统能力:** SystemCapability.ArkUI.ArkUI.Full 975 976| 名称 | 类型 | 只读 | 可选 | 说明 | 977| --------------------- | ---------------------------------------- | ---- | -------|------------ | 978| rangeBefore | [TextRange](ts-text-common.md#textrange12) | 否 | 否 | 即将被替换内容的开始和结束索引。 | 979| replacedSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)> | 否 | 否 | 替换后文本Span的具体信息。 | 980| replacedImageSpans | Array<[RichEditorImageSpanResult](#richeditorimagespanresult)> | 否 | 否 | 替换后ImageSpan的具体信息。 | 981| replacedSymbolSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)> | 否 | 否 | 替换后SymbolSpan的具体信息。 | 982 983## RichEditorBaseController<sup>12+</sup> 984 985RichEditor组件控制器基类。 986 987### getCaretOffset<sup>10+</sup> 988 989getCaretOffset(): number 990 991返回当前光标所在位置。 992 993**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 994 995**系统能力:** SystemCapability.ArkUI.ArkUI.Full 996 997**返回值:** 998 999| 类型 | 说明 | 1000| ------ | --------- | 1001| number | 当前光标所在位置。 | 1002 1003### setCaretOffset<sup>10+</sup> 1004 1005setCaretOffset(offset: number): boolean 1006 1007设置光标位置。 1008 1009**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1010 1011**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1012 1013**参数:** 1014 1015| 参数名 | 类型 | 必填 | 说明 | 1016| ------ | ------ | ---- | -------------------- | 1017| offset | number | 是 | 光标偏移位置。超出所有内容范围时,设置失败。 | 1018 1019**返回值:** 1020 1021| 类型 | 说明 | 1022| ------- | --------- | 1023| boolean | 光标是否设置成功。<br/>true表示光标位置设置成功,false表示未成功。 | 1024 1025### closeSelectionMenu<sup>10+</sup> 1026 1027closeSelectionMenu(): void 1028 1029关闭自定义选择菜单或系统默认选择菜单。 1030 1031**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1032 1033**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1034 1035### getTypingStyle<sup>11+</sup> 1036 1037getTypingStyle(): RichEditorTextStyle 1038 1039获取用户预设的文本样式。 1040 1041**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1042 1043**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1044 1045**返回值:** 1046 1047| 类型 | 说明 | 1048| ---------------------------------------- | ------- | 1049| [RichEditorTextStyle](#richeditortextstyle) | 用户预设样式。 | 1050 1051### setTypingStyle<sup>11+</sup> 1052 1053setTypingStyle(value: RichEditorTextStyle): void 1054 1055设置用户预设的文本样式。 1056 1057**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1058 1059**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1060 1061**参数:** 1062 1063| 参数名 | 类型 | 必填 | 说明 | 1064| ----- | ---------------------------------------- | ---- | ----- | 1065| value | [RichEditorTextStyle](#richeditortextstyle) | 是 | 预设样式。 | 1066 1067### setTypingParagraphStyle<sup>20+</sup> 1068 1069setTypingParagraphStyle(style: RichEditorParagraphStyle): void 1070 1071设置用户预设的段落样式。仅在组件内容为空或组件末尾换行后,输入文本生效。 1072 1073**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。 1074 1075**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1076 1077**参数:** 1078 1079| 参数名 | 类型 | 必填 | 说明 | 1080| ----- | ---------------------------------------- | ---- | ----- | 1081| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 是 | 预设段落样式。 | 1082 1083### setSelection<sup>11+</sup> 1084 1085setSelection(selectionStart: number, selectionEnd: number, options?: SelectionOptions): void 1086 1087支持设置组件内的内容选中,选中部分背板高亮。 1088 1089selectionStart和selectionEnd均为-1时表示全选,均为0时可以清空选中区。 1090 1091未获焦时调用该接口不产生选中效果。 1092 1093从API version 12开始,在2in1设备中,无论options取何值,调用setSelection接口都不会弹出菜单,此外,如果组件中已经存在菜单,调用setSelection接口会关闭菜单。 1094 1095在非2in1设备中,options取值为MenuPolicy.DEFAULT时,遵循以下规则: 1096 10971. 组件内有手柄菜单时,接口调用后不关闭菜单,并且调整菜单位置。 1098 10992. 组件内有不带手柄的菜单时,接口调用后不关闭菜单,并且菜单位置不变。 1100 11013. 组件内无菜单时,接口调用后也无菜单显示。 1102 1103**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1104 1105**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1106 1107**参数:** 1108 1109| 参数名 | 类型 | 必填 | 说明 | 1110| -------------- | ------ | ---- | ------- | 1111| selectionStart | number | 是 | 选中开始位置。 | 1112| selectionEnd | number | 是 | 选中结束位置。 | 1113| options<sup>12+</sup> | [SelectionOptions](ts-universal-attributes-text-style.md#selectionoptions12对象说明) | 否 | 选择项配置。 | 1114 1115### isEditing<sup>12+</sup> 1116 1117isEditing(): boolean 1118 1119获取当前富文本的编辑状态。 1120 1121**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1122 1123**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1124 1125**返回值:** 1126 1127| 类型 | 说明 | 1128| ------- | ----------------------------- | 1129| boolean | true为编辑态,false为非编辑态。 | 1130 1131### stopEditing<sup>12+</sup> 1132 1133stopEditing(): void 1134 1135退出编辑态。 1136 1137**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1138 1139**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1140 1141### getLayoutManager<sup>12+</sup> 1142 1143getLayoutManager(): LayoutManager 1144 1145获取布局管理器对象。 1146 1147**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1148 1149**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1150 1151**返回值:** 1152 1153| 类型 | 说明 | 1154| ---------------------------------------- | ------- | 1155| [LayoutManager](ts-text-common.md#layoutmanager12) | 布局管理器对象。 | 1156 1157### getPreviewText<sup>12+</sup> 1158 1159getPreviewText(): PreviewText 1160 1161获取预上屏信息。 1162 1163**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1164 1165**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1166 1167**返回值:** 1168 1169| 类型 | 说明 | 1170| ---------------------------------------- | ------- | 1171| [PreviewText](ts-text-common.md#previewtext12) | 预上屏信息。 | 1172 1173### getCaretRect<sup>18+</sup> 1174 1175getCaretRect(): RectResult | undefined 1176 1177返回当前光标与RichEditor组件的相对位置。如果光标不闪烁,返回undefined。 1178 1179**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 1180 1181**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1182 1183**返回值:** 1184 1185| 类型 | 说明 | 1186| ------ | --------- | 1187| [RectResult](ts-universal-attributes-on-child-touch-test.md#rectresult) \| undefined | 当前光标与RichEditor的相对位置。 | 1188 1189## RichEditorController 1190 1191RichEditor组件的控制器,继承自[RichEditorBaseController](#richeditorbasecontroller12)。 1192 1193### 导入对象 1194 1195``` 1196controller: RichEditorController = new RichEditorController(); 1197``` 1198 1199### addTextSpan 1200 1201addTextSpan(content: ResourceStr, options?: RichEditorTextSpanOptions): number 1202 1203添加文本内容,如果组件光标闪烁,插入后光标位置更新为新插入文本的后面。 1204 1205**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1206 1207**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1208 1209**参数:** 1210 1211| 参数名 | 类型 | 必填 | 说明 | 1212| ------- | ---------------------------------------- | ---- | ----- | 1213| content | [ResourceStr](ts-types.md#resourcestr) | 是 | 文本内容。 <br>从API version 20开始,支持Resource类型。| 1214| options | [RichEditorTextSpanOptions](#richeditortextspanoptions) | 否 | 文本选项。 | 1215 1216**返回值:** 1217 1218| 类型 | 说明 | 1219| ------ | -------------------- | 1220| number | 添加完成的TextSpan在所有Span中的索引位置。 | 1221 1222### addImageSpan 1223 1224addImageSpan(value: PixelMap | ResourceStr, options?: RichEditorImageSpanOptions): number 1225 1226添加图片内容,如果组件光标闪烁,插入后光标位置更新为新插入图片的后面。 1227 1228不建议直接添加网络图片。 1229 1230**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1231 1232**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1233 1234**参数:** 1235 1236| 参数名 | 类型 | 必填 | 说明 | 1237| ------- | ---------------------------------------- | ---- | ----- | 1238| value | [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md) \| [ResourceStr](ts-types.md#resourcestr) | 是 | 图片内容。 | 1239| options | [RichEditorImageSpanOptions](#richeditorimagespanoptions) | 否 | 图片选项。 | 1240 1241**返回值:** 1242 1243| 类型 | 说明 | 1244| ------ | -------------------- | 1245| number | 添加完成的ImageSpan在所有Span中的索引位置。 | 1246 1247### addBuilderSpan<sup>11+</sup> 1248 1249addBuilderSpan(value: CustomBuilder, options?: RichEditorBuilderSpanOptions): number 1250 1251在RichEditor中添加用户自定义布局(BuilderSpan)。 1252 1253> **说明:** 1254> 1255> - RichEditor组件添加占位Span,占位Span调用系统的measure方法计算真实的长宽和位置。 1256> - 可通过[RichEditorBuilderSpanOptions](#richeditorbuilderspanoptions11)设置此builder在RichEditor中的index(一个文字为一个单位)。 1257> - 此占位Span不可获焦,支持拖拽,支持部分通用属性,占位、删除等能力等同于ImageSpan,长度视为一个文字。 1258> - 支持通过[bindSelectionMenu](#bindselectionmenu)设置自定义菜单。 1259> - 不支持通过[getSpans](#getspans),[getSelection](#getselection11),[onSelect](#onselect),[aboutToDelete](#abouttodelete)获取builderSpan信息。 1260> - 不支持通过[updateSpanStyle](#updatespanstyle),[updateParagraphStyle](#updateparagraphstyle11)等方式更新builder。 1261> - 对此builder节点进行复制或粘贴不生效。 1262> - builder的布局约束由RichEditor传入,如果builder里最外层组件不设置大小,则会用RichEditor的大小作为maxSize。 1263> - builder的手势相关事件机制与通用手势事件相同,如果builder中未设置透传,则仅有builder中的子组件响应。 1264> - 如果组件光标闪烁,插入后光标位置更新为新插入builder的后面。 1265 1266通用属性仅支持[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)、[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)。 1267 1268**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1269 1270**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1271 1272**参数:** 1273 1274| 参数名 | 类型 | 必填 | 说明 | 1275| ------- | ---------------------------------------- | ---- | ---------- | 1276| value | [CustomBuilder](ts-types.md#custombuilder8) | 是 | 自定义组件。 | 1277| options | [RichEditorBuilderSpanOptions](#richeditorbuilderspanoptions11) | 否 | builder选项。 | 1278 1279**返回值:** 1280 1281| 类型 | 说明 | 1282| ------ | ---------------------- | 1283| number | 添加完成的builderSpan在所有Span中的索引位置。 | 1284 1285### addSymbolSpan<sup>11+</sup> 1286 1287addSymbolSpan(value: Resource, options?: RichEditorSymbolSpanOptions ): number 1288 1289在RichEditor中添加图标小符号(SymbolSpan),如果组件光标闪烁,插入后光标位置更新为新插入SymbolSpan的后面。 1290 1291暂不支持手势、复制、拖拽处理。 1292 1293**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1294 1295**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1296 1297**参数:** 1298 1299| 参数名 | 类型 | 必填 | 说明 | 1300| ------- | ---------------------------------------- | ---- | ----- | 1301| value | [Resource](ts-types.md#resource) | 是 | symbol资源信息。 | 1302| options | [RichEditorSymbolSpanOptions](#richeditorsymbolspanoptions11) | 否 | symbol选项。 | 1303 1304**返回值:** 1305 1306| 类型 | 说明 | 1307| ------ | --------------------- | 1308| number | 添加完成的SymbolSpan在所有Span中的索引位置。 | 1309 1310### updateSpanStyle 1311 1312updateSpanStyle(value: RichEditorUpdateTextSpanStyleOptions | RichEditorUpdateImageSpanStyleOptions | RichEditorUpdateSymbolSpanStyleOptions): void 1313 1314更新文本、图片或SymbolSpan样式。<br/>若只更新了一个Span的部分内容,则会根据更新部分、未更新部分将该Span拆分为多个Span。 1315 1316使用该接口更新文本、图片或SymbolSpan样式时默认不会关闭自定义文本选择菜单。 1317 1318**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1319 1320**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1321 1322**参数:** 1323 1324| 参数名 | 类型 | 必填 | 说明 | 1325| ------ | -------- | ---- | -------------------------------------- | 1326| value | [RichEditorUpdateTextSpanStyleOptions](#richeditorupdatetextspanstyleoptions) \| [RichEditorUpdateImageSpanStyleOptions](#richeditorupdateimagespanstyleoptions) \| [RichEditorUpdateSymbolSpanStyleOptions](#richeditorupdatesymbolspanstyleoptions11) | 是 | 文本、图片或SymbolSpan的样式选项信息。 | 1327 1328> **说明:** 1329> 1330> 当start大于end时为异常情况,此时start为0,end为无穷大。 1331 1332### updateParagraphStyle<sup>11+</sup> 1333 1334updateParagraphStyle(value: RichEditorParagraphStyleOptions): void 1335 1336更新段落的样式。 1337 1338**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1339 1340**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1341 1342**参数:** 1343 1344| 参数名 | 类型 | 必填 | 说明 | 1345| ----- | ---------------------------------------- | ---- | ---------- | 1346| value | [RichEditorParagraphStyleOptions](#richeditorparagraphstyleoptions11) | 是 | 段落的样式选项信息。 | 1347 1348### getSpans 1349 1350getSpans(value?: RichEditorRange): Array<RichEditorImageSpanResult | RichEditorTextSpanResult> 1351 1352获取span信息。 1353 1354**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1355 1356**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1357 1358**参数:** 1359 1360| 参数名 | 类型 | 必填 | 说明 | 1361| ----- | ----------------------------------- | ---- | ----------- | 1362| value | [RichEditorRange](#richeditorrange) | 否 | 需要获取span范围。 | 1363 1364**返回值:** 1365 1366| 类型 | 说明 | 1367| ---------------------------------------- | ------------ | 1368| Array<[RichEditorImageSpanResult](#richeditorimagespanresult) \| [RichEditorTextSpanResult](#richeditortextspanresult)> | 文本和图片Span信息。 | 1369 1370### deleteSpans 1371 1372deleteSpans(value?: RichEditorRange): void 1373 1374删除指定范围内的文本和图片。 1375 1376**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1377 1378**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1379 1380**参数:** 1381 1382| 参数名 | 类型 | 必填 | 说明 | 1383| ----- | ----------------------------------- | ---- | ------------------- | 1384| value | [RichEditorRange](#richeditorrange) | 否 | 删除范围。省略时,删除所有文本和图片。 | 1385 1386### getParagraphs<sup>11+</sup> 1387 1388getParagraphs(value?: RichEditorRange): Array\<RichEditorParagraphResult> 1389 1390获取指定范围的段落信息。 1391 1392**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1393 1394**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1395 1396**参数:** 1397 1398| 参数名 | 类型 | 必填 | 说明 | 1399| ----- | ----------------------------------- | ---- | ---------- | 1400| value | [RichEditorRange](#richeditorrange) | 否 | 需要获取段落的范围。 | 1401 1402**返回值:** 1403 1404| 类型 | 说明 | 1405| ---------------------------------------- | -------- | 1406| Array\<[RichEditorParagraphResult](#richeditorparagraphresult11)> | 选中段落的信息。 | 1407 1408### getSelection<sup>11+</sup> 1409 1410getSelection(): RichEditorSelection 1411 1412获取选中内容。未选中时,返回光标所在span信息。 1413 1414**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1415 1416**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1417 1418**返回值:** 1419 1420| 类型 | 说明 | 1421| ---------------------------------------- | ------- | 1422| [RichEditorSelection](#richeditorselection) | 选中内容信息。 | 1423 1424### fromStyledString<sup>12+</sup> 1425 1426fromStyledString(value: StyledString): Array\<RichEditorSpan> 1427 1428将属性字符串转换为span信息。 1429 1430**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1431 1432**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1433 1434**参数:** 1435 1436| 参数名 | 类型 | 必填 | 说明 | 1437| ----- | ----------------------------------- | ---- | ---------- | 1438| value | [StyledString](ts-universal-styled-string.md#styledstring) | 是 | 转换前的属性字符串。 | 1439 1440**返回值:** 1441 1442| 类型 | 说明 | 1443| ---------------------------------------- | ------- | 1444| Array<[RichEditorSpan](#richeditorspan12)> | 文本和图片Span信息。 | 1445 1446**错误码:** 1447 1448以下错误码的详细介绍请参考[通用错误码](../../errorcode-universal.md)。 1449 1450| 错误码ID | 错误信息 | 1451| -------- | ------------------------------ | 1452| 401 | The parameter check failed. | 1453 1454### toStyledString<sup>12+</sup> 1455 1456toStyledString(value: RichEditorRange): StyledString 1457 1458将给定范围的组件内容转换成属性字符串,SymbolSpan和BuilderSpan不支持转换。 1459 1460**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1461 1462**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1463 1464**参数:** 1465 1466| 参数名 | 类型 | 必填 | 说明 | 1467| ----- | ----------------------------------- | ---- | ---------- | 1468| value | [RichEditorRange](#richeditorrange) | 是 | 需要获取的范围。 | 1469 1470**返回值:** 1471 1472| 类型 | 说明 | 1473| ---------------------------------------- | -------- | 1474| [StyledString](ts-universal-styled-string.md#styledstring) | 转换后的属性字符串 | 1475 1476**错误码:** 1477 1478以下错误码详细介绍请参考[通用错误码](../../errorcode-universal.md)。 1479 1480| 错误码ID | 错误信息 | 1481| -------- | ------------------------------ | 1482| 401 | The parameter check failed. | 1483 1484 1485## RichEditorStyledStringController<sup>12+</sup> 1486 1487使用属性字符串构建的RichEditor组件的控制器,继承自[RichEditorBaseController](#richeditorbasecontroller12)。 1488 1489### 导入对象 1490 1491``` 1492controller: RichEditorStyledStringController = new RichEditorStyledStringController(); 1493``` 1494 1495### getSelection<sup>12+</sup> 1496 1497getSelection(): RichEditorRange 1498 1499获取富文本当前的选中区域范围。 1500 1501**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1502 1503**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1504 1505**返回值:** 1506 1507| 类型 | 说明 | 1508| ---------------------------------------- | ------- | 1509| [RichEditorRange](#richeditorrange) | 选中区域范围。 | 1510 1511### setStyledString<sup>12+</sup> 1512 1513setStyledString(styledString: StyledString): void 1514 1515设置富文本组件显示的属性字符串。 1516 1517**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1518 1519**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1520 1521**参数:** 1522 1523| 参数名 | 类型 | 必填 | 说明 | 1524| ----- | ------ | ---- | ------------------- | 1525| styledString | [StyledString](ts-universal-styled-string.md#styledstring) | 是 | 属性字符串。<br/>**说明:** <br/>StyledString的子类[MutableStyledString](ts-universal-styled-string.md#mutablestyledstring)也可以作为入参值。 | 1526 1527### getStyledString<sup>12+</sup> 1528 1529getStyledString(): MutableStyledString 1530 1531获取富文本组件显示的属性字符串。 1532 1533**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1534 1535**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1536 1537**返回值:** 1538 1539| 类型 | 说明 | 1540| ------- | ----------------------------- | 1541| [MutableStyledString](ts-universal-styled-string.md#mutablestyledstring) | 富文本组件显示的属性字符串 | 1542 1543### onContentChanged<sup>12+</sup> 1544 1545onContentChanged(listener: StyledStringChangedListener): void 1546 1547注册文本内容变化回调,该回调会在后端程序导致文本内容变更时触发。 1548 1549**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1550 1551**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1552 1553**参数:** 1554 1555| 参数名 | 类型 | 必填 | 说明 | 1556| ----- | ------ | ---- | ------------------- | 1557| listener | [StyledStringChangedListener](ts-text-common.md#styledstringchangedlistener12) | 是 | 文本内容变化回调监听器。 | 1558 1559## RichEditorSelection 1560 1561选中内容信息。 1562 1563**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1564 1565**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1566 1567| 名称 | 类型 | 只读 | 可选 | 说明 | 1568| --------- | ---------------------------------------- | ---- | ---|---- | 1569| selection | [number, number] | 否 | 否 | 选中范围。 | 1570| spans | Array<[RichEditorTextSpanResult](#richeditortextspanresult) \| [RichEditorImageSpanResult](#richeditorimagespanresult)> | 否 | 否 | span信息。 | 1571 1572## RichEditorRange 1573 1574定义RichEditor的范围。 1575 1576**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1577 1578**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1579 1580| 名称 | 类型 | 只读 | 可选 | 说明 | 1581| ----- | ------ | ---- | ---------|--------------------------------------------------- | 1582| start | number | 否 | 是 | 需要更新样式的文本起始位置,省略或者设置负值时表示从0开始。 | 1583| end | number | 否 | 是 | 需要更新样式的文本结束位置,省略或者超出文本范围时表示无穷大。 | 1584 1585 1586## RichEditorSpanStyleOptions 1587 1588文本样式选项。 1589 1590继承自[RichEditorRange](#richeditorrange)。 1591 1592**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1593 1594**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1595 1596## RichEditorUpdateTextSpanStyleOptions 1597 1598文本样式选项。 1599 1600继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1601 1602**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1603 1604| 名称 | 类型 | 只读 | 可选| 说明 | 1605| --------- | ------------------------------------------- | ---- | -----|----- | 1606| textStyle | [RichEditorTextStyle](#richeditortextstyle) | 否 | 否 | 文本样式。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1607| urlStyle<sup>19+</sup> | [RichEditorUrlStyle](#richeditorurlstyle19) | 否 | 是 | url信息。<br/>默认值:undefined <br/>**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。| 1608 1609## RichEditorUpdateImageSpanStyleOptions 1610 1611图片的样式选项。 1612 1613继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1614 1615**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1616 1617**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1618 1619| 名称 | 类型 | 只读 | 可选 | 说明 | 1620| ---------- | ---------------------------------------- | ---- | ----------|--------------------- | 1621| imageStyle | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | 否| 否 | 图片样式。 | 1622 1623## RichEditorUpdateSymbolSpanStyleOptions<sup>11+</sup> 1624 1625SymbolSpan样式选项。 1626 1627继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1628 1629**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1630 1631**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1632 1633| 名称 | 类型 | 只读 | 可选 | 说明 | 1634| ----------- | --------------------------------------------------------- | ---- | ----|------ | 1635| symbolStyle | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | 否 | 否 | 组件样式。 | 1636 1637## RichEditorParagraphStyleOptions<sup>11+</sup> 1638 1639段落样式选项。 1640 1641继承自[RichEditorRange](#richeditorrange)。 1642 1643**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1644 1645**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1646 1647| 名称 | 类型 | 只读 | 可选 | 说明 | 1648| ----- | ---------------------------------------- | ---- | ------------|---------------------- | 1649| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 否 | 否 | 段落样式。 | 1650 1651> **说明:** 1652> 1653> 接口作用的范围:设定的区间所涉及的段落。 1654 1655 1656## RichEditorParagraphStyle<sup>11+</sup> 1657 1658段落样式。 1659 1660**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1661 1662| 名称 | 类型 | 只读 | 可选 | 说明 | 1663| ------------- | ---------------------------------------- | ---- | --------|---------- | 1664| textAlign | [TextAlign](ts-appendix-enums.md#textalign) | 否 | 是 | 设置文本段落在水平方向的对齐方式。默认值:TextAlign.START <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1665| leadingMargin | [Dimension](ts-types.md#dimension10) \| [LeadingMarginPlaceholder](#leadingmarginplaceholder11) | 否 | 是 | 设置文本段落缩进,当段落仅存在ImageSpan或BuilderSpan时,此属性值不生效。参数为Dimension类型时,不支持以Percentage形式设置。默认值:{"size":["0.00px","0.00px"]} <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1666| wordBreak<sup>12+</sup> | [WordBreak](ts-appendix-enums.md#wordbreak11) | 否 | 是 | 设置断行规则。 <br />默认值:WordBreak.BREAK_WORD <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1667| lineBreakStrategy<sup>12+</sup> | [LineBreakStrategy](ts-appendix-enums.md#linebreakstrategy12) | 否 | 是 | 设置折行规则。 <br />默认值:LineBreakStrategy.GREEDY<br />在wordBreak不等于breakAll的时候生效,不支持连字符。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1668| paragraphSpacing<sup>19+</sup> | number | 否 | 是 | 设置段落间距大小。<br/>单位:fp<br/>段落间距默认大小为0。<br/>**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。| 1669| textVerticalAlign<sup>20+</sup> | [TextVerticalAlign](ts-text-common.md#textverticalalign20) | 否 | 是 | 设置文本段落在垂直方向的对齐方式。<br/>默认值:TextVerticalAlign.BASELINE <br/>**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。| 1670 1671## LeadingMarginPlaceholder<sup>11+</sup> 1672 1673前导边距占位符,用于表示文本段落左侧与组件边缘之间的距离。 1674 1675**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1676 1677| 名称 | 类型 | 只读 | 可选 | 说明 | 1678| -------- | ---------------------------------------- | ---- | ---------|----- | 1679| pixelMap | [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md) | 否 | 否 | 图片内容。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1680| size | \[[Dimension](ts-types.md#dimension10), [Dimension](ts-types.md#dimension10)\] | 否 | 否 | 图片大小,不支持设置百分比。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 1681 1682## RichEditorParagraphResult<sup>11+</sup> 1683 1684后端返回的段落信息。 1685 1686**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1687 1688**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1689 1690| 名称 | 类型 | 只读 | 可选 | 说明 | 1691| ----- | ---------------------------------------- | ---- | ---|---- | 1692| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) |否| 否 | 段落样式。 | 1693| range | \[number, number\] |否 | 否 | 段落起始和结束位置。 | 1694 1695## RichEditorTextSpanOptions 1696 1697添加文本的偏移位置和文本样式信息。 1698 1699**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1700 1701| 名称 | 类型 | 只读 | 可选 | 说明 | 1702| ---------------------------- | ---------------------------------------- | ---- | ------|-------------------- | 1703| offset | number | 否 | 是 | 添加文本的位置。省略时,添加到所有内容的最后。<br/>当值小于0时,放在所有内容最前面;当值大于所有内容长度时,放在所有内容最后面。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1704| style | [RichEditorTextStyle](#richeditortextstyle) | 否 | 是 | 文本样式信息。省略时,使用系统默认文本信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1705| paragraphStyle<sup>11+</sup> | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 否 | 是 | 段落样式。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 1706| gesture<sup>11+</sup> | [RichEditorGesture](#richeditorgesture11) | 否 | 是 | 行为触发回调。省略时,仅使用系统默认行为。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1707| urlStyle<sup>19+</sup> | [RichEditorUrlStyle](#richeditorurlstyle19) | 否 | 是 | url信息。<br/>默认值:undefined <br/>**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。| 1708 1709## RichEditorTextStyle 1710 1711文本样式信息。 1712 1713**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1714 1715| 名称 | 类型 | 只读 | 可选 | 说明 | 1716| ------------------------ | ---------------------------------------- | ---- | ---------|------------------------------- | 1717| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 是 | 文本颜色。<br/> 默认值:$r('sys.color.font_primary')。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1718| fontSize | [Length](ts-types.md#length) \| number | 否| 是 | 设置字体大小,Length为number类型时,使用fp单位。字体默认大小16。不支持设置百分比字符串。字体大小设置为0时,显示默认字体大小。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1719| fontStyle | [FontStyle](ts-appendix-enums.md#fontstyle) | 否 | 是 | 字体样式。<br/>默认值:FontStyle.Normal。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1720| fontWeight | number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string | 否 | 是 | 字体粗细。<br/>number类型取值[100,900],取值间隔为100,默认为400,取值越大,字体越粗。<br/>string类型仅支持number类型取值的字符串形式,例如“400”,以及“bold”、“bolder”、“lighter”、“regular” 、“medium”分别对应FontWeight中相应的枚举值。<br/>默认值:FontWeight.Normal。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1721| fontFamily | [ResourceStr](ts-types.md#resourcestr) | 否 | 是 | 设置字体列表。默认字体'HarmonyOS Sans',当前支持'HarmonyOS Sans'字体和[注册自定义字体](../js-apis-font.md)。 <br/>默认字体:'HarmonyOS Sans'。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1722| decoration | [DecorationStyleInterface](ts-universal-styled-string.md#decorationstyleinterface) | 否 | 是 | 设置文本装饰线的样式、颜色和粗细。<br/>type默认值:TextDecorationType.None <br/>color默认值:跟随字体颜色。<br/>style默认值:TextDecorationStyle.SOLID <br/>thicknessScale默认值:1.0 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1723| textShadow<sup>11+</sup> | [ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions对象说明) \| Array<[ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions对象说明)> | 否 | 是 | 设置文字阴影效果。该接口支持以数组形式入参,实现多重文字阴影。<br/>**说明:**<br/>仅支持设置阴影模糊半径、颜色和偏移量,不支持智能取色。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1724| lineHeight<sup>12+</sup> | number \| string \| [Resource](ts-types.md#resource) | 否 | 是 |设置文本的文本行高,设置值不大于0时,不限制文本行高,自适应字体大小。number类型时单位为fp,不支持设置百分比字符串。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1725| letterSpacing<sup>12+</sup> | number \| string | 否 | 是 | 设置文本字符间距,当取值为负值时,文字会发生压缩,负值过小时会将组件内容区大小压缩为0,导致无内容显示,number类型时单位为fp,不支持设置百分比字符串。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1726| fontFeature<sup>12+</sup> | string | 否 | 是 | 设置文字特性效果,比如数字等宽的特性。如果未设置,默认为变宽数字。设置无效字符保持默认。<br/>格式为:normal \| \<feature-tag-value\><br/>\<feature-tag-value\>的格式为:\<string\> \[ \<integer\> \| on \| off ]<br/>\<feature-tag-value\>的个数可以有多个,中间用','隔开。<br/>例如,使用等宽时钟数字的输入格式为:"ss01" on。<br/>Font Feature当前支持的属性见 [fontFeature属性列表](ts-basic-components-text.md#fontfeature12)。<br/>设置 Font Feature 属性,Font Feature 是 OpenType 字体的高级排版能力,如支持连字、数字等宽等特性,一般用在自定义字体中,其能力需要字体本身支持。<br/>更多 Font Feature 能力介绍可参考 https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop 和 https://sparanoid.com/lab/opentype-features/<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1727| halfLeading<sup>18+</sup> | boolean |否 | 是 | 文本是否将行间距平分至行的顶部与底部。<br/>true表示将行间距平分至行的顶部与底部,false则不平分。<br/>默认值:false。<br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。| 1728| textBackgroundStyle<sup>18+</sup> | [TextBackgroundStyle](ts-basic-components-span.md#textbackgroundstyle11对象说明) | 否 | 是 | 文本背景样式。<br />默认值:<br />{<br /> color: Color.Transparent,<br /> radius: 0<br />} <br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。| 1729 1730## PlaceholderStyle<sup>12+</sup> 1731 1732设置提示文本的字体样式。 1733 1734**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1735 1736**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1737 1738| 名称 | 类型 | 只读 | 可选 | 说明 | 1739| ---------------------------- | ---------------------------------------- | ---- | ----------|---------------- | 1740| font | [Font](ts-types.md#font) | 否 | 是 | 设置placeholder文本样式。<br/>默认值遵循主题设置。| 1741| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 是 | 设置placeholder文本颜色。<br/>默认值遵循主题设置。| 1742 1743## RichEditorImageSpanOptions 1744 1745设置图片的偏移位置和图片样式信息。 1746 1747**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1748 1749| 名称 | 类型 | 只读 | 可选 | 说明 | 1750| --------------------- | ---------------------------------------- | ---- | --------|------------------ | 1751| offset | number | 否 | 是 | 添加图片的位置。省略时,添加到所有内容的末尾。<br/>当值小于0时,设置在所有内容最前面;当值大于所有内容长度时,设置在所有内容最后面。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1752| imageStyle | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | 否 | 是 | 图片样式信息。省略时,使用系统默认图片信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1753| gesture<sup>11+</sup> | [RichEditorGesture](#richeditorgesture11) | 否 | 是 | 行为触发回调。省略时,仅使用系统默认行为。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1754| onHover<sup>14+</sup> | [OnHoverCallback](#onhovercallback14) | 否 | 是 | 鼠标悬停触发回调。省略时,不执行相关行为。 <br/>**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。| 1755 1756## RichEditorImageSpanStyle 1757 1758图片样式。 1759 1760**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1761 1762| 名称 | 类型 | 只读 | 可选 | 说明 | 1763| ------------------------- | ---------------------------------------- | ---- | -------|-------------------------------- | 1764| size | [[Dimension](ts-types.md#dimension10), [Dimension](ts-types.md#dimension10)] | 否| 是 | 图片宽度和高度。默认值:与objectFit的值相关,不同的objectFit值有不同的默认尺寸。objectFit的值为Cover时,图片高度为组件高度减去组件上下内边距,宽度为组件宽度减去组件左右内边距。不支持以Percentage形式设置。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1765| verticalAlign | [ImageSpanAlignment](ts-appendix-enums.md#imagespanalignment10)| 否| 是 | 图片垂直对齐方式。<br/>默认值:ImageSpanAlignment.BOTTOM <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1766| objectFit | [ImageFit](ts-appendix-enums.md#imagefit) | 否| 是 | 图片缩放类型。<br/> 默认值:ImageFit.Cover。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1767| layoutStyle<sup>11+</sup> | [RichEditorLayoutStyle](#richeditorlayoutstyle11) | 否| 是 | 图片布局风格。默认值:{"borderRadius":"","margin":""}<br/> <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 1768 1769## RichEditorSymbolSpanOptions<sup>11+</sup> 1770 1771设置SymbolSpan组件的偏移位置和样式。 1772 1773**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1774 1775**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1776 1777| 名称 | 类型 | 只读 | 可选 | 说明 | 1778| ------ | ---------------------------------------- | ---- | ----------------|---------- | 1779| offset | number | 否 | 是 | 添加组件的位置。省略时,添加到所有内容的最后。<br/>如果值小于0,添加到所有内容的最前面;如果值大于所有内容的长度,添加到所有内容的最后面。 | 1780| style | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | 否 | 是 | 组件样式信息。省略时,使用系统默认样式信息。 | 1781 1782## RichEditorSymbolSpanStyle<sup>11+</sup> 1783 1784组件SymbolSpan样式信息。 1785 1786**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1787 1788**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1789 1790| 名称 | 类型 | 只读 | 可选 | 说明 | 1791| ------ | -------- | ---- | --------------------|------------------ | 1792| fontColor | Array\<[ResourceColor](ts-types.md#resourcecolor)\> | 否| 是 | 设置SymbolSpan组件颜色。<br/> 默认值:不同渲染策略下默认值不同。 | 1793| fontSize | number \| string \| [Resource](ts-types.md#resource) | 否| 是 | 设置SymbolSpan组件大小,默认单位为fp。<br/>默认值:跟随主题。 | 1794| fontWeight | number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string | 否| 是 | 设置SymbolSpan组件粗细。<br/>number类型取值[100,900],取值间隔为100,默认为400,取值越大,字体越粗。<br/>string类型仅支持number类型取值的字符串形式,例如“400”,以及“bold”、“bolder”、“lighter”、“regular” 、“medium”分别对应FontWeight中相应的枚举值。<br/>默认值:FontWeight.Normal。 | 1795| renderingStrategy | [SymbolRenderingStrategy](ts-basic-components-symbolGlyph.md#symbolrenderingstrategy11枚举说明) | 否| 是 | 设置SymbolSpan组件渲染策略。<br/>默认值:SymbolRenderingStrategy.SINGLE。 | 1796| effectStrategy | [SymbolEffectStrategy](ts-basic-components-symbolGlyph.md#symboleffectstrategy11枚举说明) | 否| 是 | 设置SymbolSpan组件动效策略。<br/>默认值:SymbolEffectStrategy.NONE。 | 1797 1798## RichEditorBuilderSpanOptions<sup>11+</sup> 1799 1800设置builder的偏移位置和样式。 1801 1802**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1803 1804**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1805 1806| 名称 | 类型 | 只读 | 可选 | 说明 | 1807| ------ | ------ | ---- | ----------|--------------------------- | 1808| offset | number | 否 | 是 | 添加builder的位置。省略或者为异常值时,添加到所有内容的最后。 | 1809 1810## RichEditorSpan<sup>12+</sup> 1811 1812type RichEditorSpan = RichEditorImageSpanResult | RichEditorTextSpanResult 1813 1814RichEditor span信息。 1815 1816**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1817 1818**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1819 1820| 类型 | 说明 | 1821| ------ | ---------- | 1822| [RichEditorImageSpanResult](#richeditorimagespanresult) | 后端返回的图片信息。 | 1823| [RichEditorTextSpanResult](#richeditortextspanresult) | 后端返回的文本信息。 | 1824 1825## SelectionMenuOptions 1826 1827菜单的选项。 1828 1829**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1830 1831| 名称 | 类型 | 只读 | 可选 | 说明 | 1832| ----------- | ---------- | ---- | -------|------ | 1833| onAppear | [MenuOnAppearCallback](#menuonappearcallback12) | 否 | 是 | 自定义选择菜单弹出时回调。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1834| onDisappear | Callback\<void\> | 否 | 是 | 自定义选择菜单关闭时回调。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1835| menuType<sup>13+</sup> | [MenuType](ts-text-common.md#menutype13枚举说明) | 否 | 是 | 自定义选择菜单类型。<br/>**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。<br/>默认值:MenuType.SELECTION_MENU。 | 1836| onMenuShow<sup>15+</sup> | [MenuCallback](#menucallback15) | 否 | 是 | 自定义选择菜单显示时回调。<br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 | 1837| onMenuHide<sup>15+</sup> | [MenuCallback](#menucallback15) | 否 | 是 | 自定义选择菜单隐藏时回调。<br/>**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 | 1838| previewMenuOptions<sup>18+</sup> | [PreviewMenuOptions](#previewmenuoptions18) | 否 | 是 | 预览菜单的选项。 <br/>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 | 1839 1840## PreviewMenuOptions<sup>18+</sup> 1841 1842预览菜单的选项。 1843 1844**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 1845 1846**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1847 1848| 名称 | 类型 | 只读 | 可选 | 说明 | 1849| ----------- | ---------- | ---- | ----|--------- | 1850| hapticFeedbackMode | [HapticFeedbackMode](ts-universal-attributes-menu.md#hapticfeedbackmode18)| 否 | 是 | 菜单弹出时振动效果,当ImageSpan或BuilderSpan绑定预览菜单时生效。<br/>默认值:HapticFeedbackMode.DISABLED,菜单弹出时不振动。<br/>**说明:** 仅当应用具备ohos.permission.VIBRATE权限,且用户启用了触感反馈时才会生效。| 1851 1852## PasteEvent<sup>11+</sup> 1853 1854定义用户粘贴事件。 1855 1856**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1857 1858**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1859 1860| 名称 |类型 | 只读 | 可选 | 说明 | 1861| -------------- | ----------- | ---- | -----|------------------------ | 1862| preventDefault | Callback\<void\> | 否 | 是 | 阻止系统默认粘贴事件。 | 1863 1864## CutEvent<sup>12+</sup> 1865 1866定义用户剪切事件。 1867 1868**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1869 1870**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1871 1872| 名称 | 类型 | 只读 | 可选 | 说明 | 1873| -------------- | ----------- | ---- | -------|---------------------- | 1874| preventDefault | Callback\<void\> | 否 | 是 | 阻止系统默认剪切事件。 | 1875 1876## CopyEvent<sup>12+</sup> 1877 1878定义用户复制事件。 1879 1880**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1881 1882**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1883 1884| 名称 | 类型 | 只读 | 可选 | 说明 | 1885| -------------- | ----------- | ---- | ---------|-------------------- | 1886| preventDefault | Callback\<void\> | 否 | 是 | 阻止组件的默认复制操作。 | 1887 1888## RichEditorGesture<sup>11+</sup> 1889 1890用户手势事件。 1891 1892**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1893 1894**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1895 1896| 名称 | 类型 | 只读 | 可选 | 说明 | 1897| ----------- | ---------- | ---- | ------|------- | 1898| onClick | Callback\<[ClickEvent](ts-universal-events-click.md#clickevent对象说明)\> | 否 | 是 | [ClickEvent](ts-universal-events-click.md#clickevent对象说明)为用户点击事件。<br/>点击完成时回调事件。<br/>双击时,第一次点击触发回调事件。| 1899| onLongPress | Callback\<[GestureEvent](ts-gesture-common.md#gestureevent对象说明)\> | 否 | 是 | [GestureEvent](ts-gesture-common.md#gestureevent对象说明)为用户长按事件。<br/>长按完成时回调事件。 | 1900 1901## KeyboardOptions<sup>12+</sup> 1902 1903设置自定义键盘是否支持避让功能。 1904 1905**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1906 1907**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1908 1909| 名称 | 类型 | 只读 | 可选 | 说明 | 1910| --------------- | --------------- |---- | -------|----------------------------- | 1911| supportAvoidance | boolean | 否 | 是 | 设置自定义键盘是否支持避让功能。默认值为 `false`,表示不支持避让;`true` 表示支持避让。 | 1912 1913## SubmitCallback<sup>12+</sup> 1914 1915type SubmitCallback = (enterKey: EnterKeyType, event: SubmitEvent) => void 1916 1917软键盘按下回车键时的回调事件。 1918 1919**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1920 1921**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1922 1923**参数:** 1924 1925| 参数名 | 类型 | 必填 | 说明 | 1926| -------- | ------------------------------------------------------------ | ---- | -------------------------------------------------------- | 1927| enterKey | [EnterKeyType](ts-basic-components-textinput.md#enterkeytype枚举说明) | 是 | 软键盘输入法回车键类型。具体类型见EnterKeyType枚举说明。 | 1928| event | [SubmitEvent](ts-basic-components-textinput.md#submitevent11) | 是 | 当提交的时候,提供保持组件编辑状态的方法。EnterKeyType指定为NEW_LINE时,默认保持编辑态。 | 1929 1930## MenuOnAppearCallback<sup>12+</sup> 1931 1932type MenuOnAppearCallback = (start: number, end: number) => void 1933 1934自定义选择菜单弹出时触发的回调事件。 1935 1936**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1937 1938**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1939 1940**参数:** 1941 1942| 参数名 | 类型 | 必填 | 说明 | 1943| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- | 1944| start | number | 是 | 选中内容的起始位置。 | 1945| end | number | 是 | 选中内容的终止位置。 | 1946 1947## MenuCallback<sup>15+</sup> 1948 1949type MenuCallback = (start: number, end: number) => void 1950 1951自定义选择菜单显示或隐藏时触发的回调事件。 1952 1953**原子化服务API:** 从API version 15开始,该接口支持在原子化服务中使用。 1954 1955**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1956 1957**参数:** 1958 1959| 参数名 | 类型 | 必填 | 说明 | 1960| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- | 1961| start | number | 是 | 选中内容的起始位置。 | 1962| end | number | 是 | 选中内容的终止位置。 | 1963 1964## PasteEventCallback<sup>12+</sup> 1965 1966type PasteEventCallback = (event?: PasteEvent) => void 1967 1968粘贴完成前,触发回调。 1969 1970**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1971 1972**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1973 1974**参数:** 1975 1976| 参数名 | 类型 | 必填 | 说明 | 1977| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- | 1978| event | [PasteEvent](#pasteevent11) | 否 | 定义用户粘贴事件。 | 1979 1980## OnHoverCallback<sup>14+</sup> 1981 1982type OnHoverCallback = (status: boolean, event: HoverEvent) => void 1983 1984鼠标悬浮触发回调。 1985 1986**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。 1987 1988**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1989 1990**参数:** 1991 1992| 参数名 | 类型 | 必填 | 说明 | 1993| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- | 1994| status | boolean | 是 | 表示鼠标是否悬浮在组件上,鼠标进入组件时为true,离开组件时为false。| 1995| event | [HoverEvent](ts-universal-events-hover.md#hoverevent10对象说明) | 是 | 设置悬浮事件。 | 1996 1997## RichEditorTextSpan 1998 1999文本Span信息。 2000 2001**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 2002 2003**系统能力:** SystemCapability.ArkUI.ArkUI.Full 2004 2005| 名称 | 类型 | 只读 | 可选 | 说明 | 2006| ----------------------------- | ---------------------------------------- | ---- | ---------|------------- | 2007| spanPosition | [RichEditorSpanPosition](#richeditorspanposition) | 否| 否 | Span位置。| 2008| value | string | 否 | 否 | 文本Span内容。| 2009| textStyle | [RichEditorTextStyle](#richeditortextstyle) | 否| 是 | 文本Span样式信息。| 2010 2011## RichEditorImageSpan 2012 2013图片Span信息。 2014 2015**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 2016 2017**系统能力:** SystemCapability.ArkUI.ArkUI.Full 2018 2019| 名称 | 类型 | 只读 | 可选 | 说明 | 2020|------------------|-------------------------------------------------------------------|-----|----------|--------| 2021| spanPosition | [RichEditorSpanPosition](#richeditorspanposition) | 否 | 否 | Span位置。| 2022| value | [PixelMap](../../apis-image-kit/arkts-apis-image-PixelMap.md) \| [ResourceStr](ts-types.md#resourcestr) | 否 | 否 | 图片内容。| 2023| imageStyle | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | 否 | 是 | 图片样式。| 2024 2025## RichEditorUrlStyle<sup>19+</sup> 2026 2027Url信息。 2028 2029**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。 2030 2031**系统能力:** SystemCapability.ArkUI.ArkUI.Full 2032 2033| 名称 | 类型 | 只读 | 可选| 说明 | 2034|---------|---------------------------------------------|------|----|-----| 2035| url | [ResourceStr](ts-types.md#resourcestr) | 否 | 是 | url地址。<br/>默认值:undefined| 2036 2037## 示例 2038 2039### 示例1(更新文本样式) 2040通过[updateSpanStyle](#updatespanstyle)接口更新已有文本样式,更改样式后,使用[getSpans](#getspans)获取文本新的样式信息。 2041 2042```ts 2043// xxx.ets 2044@Entry 2045@Component 2046struct Index { 2047 controller: RichEditorController = new RichEditorController(); 2048 options: RichEditorOptions = { controller: this.controller }; 2049 private start: number = -1; 2050 private end: number = -1; 2051 @State message: string = "[-1, -1]"; 2052 @State content: string = ""; 2053 2054 build() { 2055 Column() { 2056 Column() { 2057 Text("selection range:").width("100%") 2058 Text() { 2059 Span(this.message) 2060 }.width("100%") 2061 Text("selection content:").width("100%") 2062 Text() { 2063 Span(this.content) 2064 }.width("100%") 2065 } 2066 .borderWidth(1) 2067 .borderColor(Color.Red) 2068 .width("100%") 2069 .height("20%") 2070 2071 Row() { 2072 Button("更新样式:加粗").onClick(() => { 2073 this.controller.updateSpanStyle({ 2074 start: this.start, 2075 end: this.end, 2076 textStyle: 2077 { 2078 fontWeight: FontWeight.Bolder 2079 } 2080 }) 2081 }) 2082 Button("获取选择内容").onClick(() => { 2083 this.content = ""; 2084 this.controller.getSpans({ 2085 start: this.start, 2086 end: this.end 2087 }).forEach(item => { 2088 if(typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined'){ 2089 this.content += (item as RichEditorImageSpanResult).valueResourceStr; 2090 this.content += "\n"; 2091 } else { 2092 if(typeof(item as RichEditorTextSpanResult)['symbolSpanStyle'] != 'undefined') { 2093 this.content += (item as RichEditorTextSpanResult).symbolSpanStyle?.fontSize; 2094 this.content += "\n"; 2095 }else { 2096 this.content += (item as RichEditorTextSpanResult).value; 2097 this.content += "\n"; 2098 } 2099 } 2100 }) 2101 }) 2102 Button("删除选择内容").onClick(() => { 2103 this.controller.deleteSpans({ 2104 start: this.start, 2105 end: this.end 2106 }) 2107 this.start = -1; 2108 this.end = -1; 2109 this.message = "[" + this.start + ", " + this.end + "]"; 2110 }) 2111 } 2112 .borderWidth(1) 2113 .borderColor(Color.Red) 2114 .width("100%") 2115 .height("10%") 2116 2117 Column() { 2118 RichEditor(this.options) 2119 .onReady(() => { 2120 this.controller.addTextSpan("012345", 2121 { 2122 style: 2123 { 2124 fontColor: Color.Orange, 2125 fontSize: 30 2126 } 2127 }) 2128 this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"), 2129 { 2130 style: 2131 { 2132 fontSize: 30 2133 } 2134 }) 2135 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 2136 this.controller.addImageSpan($r('app.media.startIcon'), 2137 { 2138 imageStyle: 2139 { 2140 size: ["57px", "57px"] 2141 } 2142 }) 2143 this.controller.addTextSpan("56789", 2144 { 2145 style: 2146 { 2147 fontColor: Color.Black, 2148 fontSize: 30 2149 } 2150 }) 2151 }) 2152 .onSelect((value: RichEditorSelection) => { 2153 this.start = value.selection[0]; 2154 this.end = value.selection[1]; 2155 this.message = "[" + this.start + ", " + this.end + "]"; 2156 }) 2157 .aboutToIMEInput((value: RichEditorInsertValue) => { 2158 console.info("---------------------- aboutToIMEInput ----------------------"); 2159 console.info("insertOffset:" + value.insertOffset); 2160 console.info("insertValue:" + value.insertValue); 2161 return true; 2162 }) 2163 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 2164 console.info("---------------------- onIMEInputComplete ---------------------"); 2165 console.info("spanIndex:" + value.spanPosition.spanIndex); 2166 console.info("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]"); 2167 console.info("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]"); 2168 console.info("value:" + value.value); 2169 }) 2170 .aboutToDelete((value: RichEditorDeleteValue) => { 2171 console.info("---------------------- aboutToDelete --------------------------"); 2172 console.info("offset:" + value.offset); 2173 console.info("direction:" + value.direction); 2174 console.info("length:" + value.length); 2175 value.richEditorDeleteSpans.forEach(item => { 2176 console.info("---------------------- item --------------------------"); 2177 console.info("spanIndex:" + item.spanPosition.spanIndex); 2178 console.info("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]"); 2179 console.info("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]"); 2180 if (typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 2181 console.info("image:" + (item as RichEditorImageSpanResult).valueResourceStr); 2182 } else { 2183 console.info("text:" + (item as RichEditorTextSpanResult).value); 2184 } 2185 }) 2186 return true; 2187 }) 2188 .onDeleteComplete(() => { 2189 console.info("---------------------- onDeleteComplete ------------------------"); 2190 }) 2191 .placeholder("input...", { 2192 fontColor: Color.Gray, 2193 font: { 2194 size: 16, 2195 weight: FontWeight.Normal, 2196 family: "HarmonyOS Sans", 2197 style: FontStyle.Normal 2198 } 2199 }) 2200 .borderWidth(1) 2201 .borderColor(Color.Green) 2202 .width("100%") 2203 .height("30%") 2204 } 2205 .borderWidth(1) 2206 .borderColor(Color.Red) 2207 .width("100%") 2208 .height("70%") 2209 } 2210 } 2211} 2212``` 2213 2214 2215### 示例2(绑定自定义键盘) 2216通过[customKeyboard](#customkeyboard)给组件绑定自定义键盘。 2217 2218```ts 2219// xxx.ets 2220@Entry 2221@Component 2222struct RichEditorExample { 2223 controller: RichEditorController = new RichEditorController(); 2224 2225 // 自定义键盘组件 2226 @Builder 2227 CustomKeyboardBuilder() { 2228 Column() { 2229 Grid() { 2230 ForEach(['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'], (item: string) => { 2231 GridItem() { 2232 Button(item).width(110).onClick(() => { 2233 this.controller.addTextSpan(item + '', { 2234 offset: this.controller.getCaretOffset(), 2235 style: 2236 { 2237 fontColor: Color.Orange, 2238 fontSize: 30 2239 } 2240 }) 2241 }) 2242 } 2243 }) 2244 }.maxCount(3).columnsGap(10).rowsGap(10).padding(5) 2245 }.backgroundColor(Color.Gray) 2246 } 2247 2248 build() { 2249 Column() { 2250 RichEditor({ controller: this.controller })// 绑定自定义键盘 2251 .customKeyboard(this.CustomKeyboardBuilder()) 2252 .border({ width: 1 }) 2253 .borderWidth(1) 2254 .borderColor(Color.Red) 2255 .margin(10) 2256 .height(200) 2257 .width("100%") 2258 } 2259 } 2260} 2261``` 2262 2263 2264 2265### 示例3(绑定自定义菜单) 2266通过[bindSelectionMenu](#bindselectionmenu)给组件绑定自定义菜单。 2267 2268示例中的粘贴菜单项涉及读取剪贴板数据,因此需按规范[申请访问剪贴板权限](../../../basic-services/pasteboard/get-pastedata-permission-guidelines.md)。 2269 2270```ts 2271// xxx.ets 2272import { BusinessError, pasteboard } from '@kit.BasicServicesKit'; 2273 2274export interface SelectionMenuTheme { 2275 imageSize: number; 2276 buttonSize: number; 2277 menuSpacing: number; 2278 editorOptionMargin: number; 2279 expandedOptionPadding: number; 2280 defaultMenuWidth: number; 2281 imageFillColor: Resource; 2282 backGroundColor: Resource; 2283 iconBorderRadius: Resource; 2284 containerBorderRadius: Resource; 2285 cutIcon: Resource; 2286 copyIcon: Resource; 2287 pasteIcon: Resource; 2288 selectAllIcon: Resource; 2289 shareIcon: Resource; 2290 translateIcon: Resource; 2291 searchIcon: Resource; 2292 arrowDownIcon: Resource; 2293 iconPanelShadowStyle: ShadowStyle; 2294 iconFocusBorderColor: Resource; 2295} 2296 2297export const defaultTheme: SelectionMenuTheme = { 2298 imageSize: 24, 2299 buttonSize: 48, 2300 menuSpacing: 8, 2301 editorOptionMargin: 1, 2302 expandedOptionPadding: 3, 2303 defaultMenuWidth: 256, 2304 imageFillColor: $r('sys.color.ohos_id_color_primary'), 2305 backGroundColor: $r('sys.color.ohos_id_color_dialog_bg'), 2306 iconBorderRadius: $r('sys.float.ohos_id_corner_radius_default_m'), 2307 containerBorderRadius: $r('sys.float.ohos_id_corner_radius_card'), 2308 cutIcon: $r("sys.media.ohos_ic_public_cut"), 2309 copyIcon: $r("sys.media.ohos_ic_public_copy"), 2310 pasteIcon: $r("sys.media.ohos_ic_public_paste"), 2311 selectAllIcon: $r("sys.media.ohos_ic_public_select_all"), 2312 shareIcon: $r("sys.media.ohos_ic_public_share"), 2313 translateIcon: $r("sys.media.ohos_ic_public_translate_c2e"), 2314 searchIcon: $r("sys.media.ohos_ic_public_search_filled"), 2315 arrowDownIcon: $r("sys.media.ohos_ic_public_arrow_down"), 2316 iconPanelShadowStyle: ShadowStyle.OUTER_DEFAULT_MD, 2317 iconFocusBorderColor: $r('sys.color.ohos_id_color_focused_outline') 2318} 2319 2320@Entry 2321@Component 2322struct SelectionMenu { 2323 @State message: string = 'Hello World'; 2324 @State textSize: number = 40; 2325 @State sliderShow: boolean = false; 2326 @State start: number = -1; 2327 @State end: number = -1; 2328 @State colorTransparent: Color = Color.Transparent; 2329 controller: RichEditorController = new RichEditorController(); 2330 options: RichEditorOptions = { controller: this.controller }; 2331 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 2332 private iconArr: Array<Resource> = 2333 [$r('app.media.startIcon'), $r('app.media.startIcon'), $r('app.media.startIcon'), 2334 $r('app.media.startIcon'), $r('app.media.startIcon')]; 2335 @State iconBgColor: ResourceColor[] = new Array(this.iconArr.length).fill(this.colorTransparent); 2336 @State pasteEnable: boolean = false; 2337 @State visibilityValue: Visibility = Visibility.Visible; 2338 @State textStyle: RichEditorTextStyle = {}; 2339 private fontWeightTable: string[] = ["100", "200", "300", "400", "500", "600", "700", "800", "900", "bold", "normal", "bolder", "lighter", "medium", "regular"]; 2340 private theme: SelectionMenuTheme = defaultTheme; 2341 2342 aboutToAppear() { 2343 if (this.controller) { 2344 let richEditorSelection = this.controller.getSelection(); 2345 if (richEditorSelection) { 2346 let start = richEditorSelection.selection[0]; 2347 let end = richEditorSelection.selection[1]; 2348 if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) { 2349 this.visibilityValue = Visibility.None; 2350 } else { 2351 this.visibilityValue = Visibility.Visible; 2352 } 2353 } 2354 } 2355 let sysBoard = pasteboard.getSystemPasteboard() 2356 try { 2357 if (sysBoard && sysBoard.hasDataSync()) { 2358 this.pasteEnable = true 2359 } else { 2360 this.pasteEnable = false 2361 } 2362 } catch (err) { 2363 console.error('Failed to check the PasteData. Cause:' + err.message) 2364 } 2365 } 2366 2367 build() { 2368 Column() { 2369 Column() { 2370 RichEditor(this.options) 2371 .onReady(() => { 2372 this.controller.addTextSpan(this.message, { style: { fontColor: Color.Orange, fontSize: 30 } }) 2373 }) 2374 .onSelect((value: RichEditorSelection) => { 2375 if (value.selection[0] == -1 && value.selection[1] == -1) { 2376 return; 2377 } 2378 this.start = value.selection[0]; 2379 this.end = value.selection[1]; 2380 }) 2381 .bindSelectionMenu(RichEditorSpanType.TEXT, this.panel, ResponseType.LongPress, { onDisappear: () => { 2382 this.sliderShow = false; 2383 }}) 2384 .bindSelectionMenu(RichEditorSpanType.TEXT, this.panel, ResponseType.RightClick, { onDisappear: () => { 2385 this.sliderShow = false; 2386 }}) 2387 .bindSelectionMenu(RichEditorSpanType.IMAGE, this.panel, ResponseType.LongPress, { 2388 menuType : MenuType.PREVIEW_MENU, 2389 previewMenuOptions : { 2390 hapticFeedbackMode : HapticFeedbackMode.ENABLED 2391 } 2392 }) 2393 .borderWidth(1) 2394 .borderColor(Color.Red) 2395 .width(200) 2396 .height(200) 2397 }.width('100%').backgroundColor(Color.White) 2398 }.height('100%') 2399 } 2400 2401 PushDataToPasteboard(richEditorSelection: RichEditorSelection) { 2402 let sysBoard = pasteboard.getSystemPasteboard(); 2403 let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, ''); 2404 if (richEditorSelection.spans && richEditorSelection.spans.length > 0) { 2405 let count = richEditorSelection.spans.length; 2406 for (let i = count - 1; i >= 0; i--) { 2407 let item = richEditorSelection.spans[i] 2408 if ((item as RichEditorTextSpanResult)?.textStyle) { 2409 let span = item as RichEditorTextSpanResult; 2410 let style = span.textStyle; 2411 let data = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_PLAIN, span.value.substring(span.offsetInSpan[0], span.offsetInSpan[1])); 2412 let prop = pasteData.getProperty(); 2413 let temp: Record<string, Object> = { 2414 'color': style.fontColor, 2415 'size': style.fontSize, 2416 'style': style.fontStyle, 2417 'weight': this.fontWeightTable[style.fontWeight], 2418 'fontFamily': style.fontFamily, 2419 'decorationType': style.decoration.type, 2420 'decorationColor': style.decoration.color 2421 }; 2422 prop.additions[i] = temp; 2423 pasteData.addRecord(data) 2424 pasteData.setProperty(prop) 2425 } 2426 } 2427 } 2428 sysBoard.clearData() 2429 sysBoard.setData(pasteData).then(() => { 2430 console.info('SelectionMenu copy option, Succeeded in setting PasteData.'); 2431 this.pasteEnable = true; 2432 }).catch((err: BusinessError) => { 2433 console.error('SelectionMenu copy option, Failed to set PasteData. Cause:' + err.message); 2434 }) 2435 } 2436 2437 PopDataFromPasteboard(richEditorSelection: RichEditorSelection) { 2438 let start = richEditorSelection.selection[0]; 2439 let end = richEditorSelection.selection[1]; 2440 if (start == end && this.controller) { 2441 start = this.controller.getCaretOffset(); 2442 end = this.controller.getCaretOffset(); 2443 } 2444 let moveOffset = 0; 2445 let sysBoard = pasteboard.getSystemPasteboard(); 2446 sysBoard.getData((err, data) => { 2447 if (err) { 2448 return; 2449 } 2450 let count = data.getRecordCount(); 2451 for (let i = 0; i < count; i++) { 2452 const element = data.getRecord(i); 2453 let tex: RichEditorTextStyle = { 2454 fontSize: 16, 2455 fontColor: Color.Black, 2456 fontWeight: FontWeight.Normal, 2457 fontFamily: "HarmonyOS Sans", 2458 fontStyle: FontStyle.Normal, 2459 decoration: { type: TextDecorationType.None, color: "#FF000000", style: TextDecorationStyle.SOLID } 2460 } 2461 if (data.getProperty() && data.getProperty().additions[i]) { 2462 const tmp = data.getProperty().additions[i] as Record<string, Object | undefined>; 2463 if (tmp.color) { 2464 tex.fontColor = tmp.color as ResourceColor; 2465 } 2466 if (tmp.size) { 2467 tex.fontSize = tmp.size as Length | number; 2468 } 2469 if (tmp.style) { 2470 tex.fontStyle = tmp.style as FontStyle; 2471 } 2472 if (tmp.weight) { 2473 tex.fontWeight = tmp.weight as number | FontWeight | string; 2474 } 2475 if (tmp.fontFamily) { 2476 tex.fontFamily = tmp.fontFamily as ResourceStr; 2477 } 2478 if (tmp.decorationType && tex.decoration) { 2479 tex.decoration.type = tmp.decorationType as TextDecorationType; 2480 } 2481 if (tmp.decorationColor && tex.decoration) { 2482 tex.decoration.color = tmp.decorationColor as ResourceColor; 2483 } 2484 if (tex.decoration) { 2485 tex.decoration = { type: tex.decoration.type, color: tex.decoration.color }; 2486 } 2487 } 2488 if (element && element.plainText && element.mimeType === pasteboard.MIMETYPE_TEXT_PLAIN && this.controller) { 2489 this.controller.addTextSpan(element.plainText, 2490 { 2491 style: tex, 2492 offset: start + moveOffset 2493 } 2494 ) 2495 moveOffset += element.plainText.length; 2496 } 2497 } 2498 if (this.controller) { 2499 this.controller.setCaretOffset(start + moveOffset) 2500 this.controller.closeSelectionMenu() 2501 } 2502 if (start != end && this.controller) { 2503 this.controller.deleteSpans({ start: start + moveOffset, end: end + moveOffset }) 2504 } 2505 }) 2506 } 2507 2508 @Builder 2509 panel() { 2510 Column() { 2511 this.iconPanel() 2512 if (!this.sliderShow) { 2513 this.SystemMenu() 2514 } else { 2515 this.sliderPanel() 2516 } 2517 }.width(256) 2518 } 2519 2520 @Builder iconPanel() { 2521 Column() { 2522 Row({ space: 2 }) { 2523 ForEach(this.iconArr, (item:Resource, index ?: number) => { 2524 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 2525 Image(item).fillColor(this.theme.imageFillColor).width(24).height(24).focusable(true).draggable(false) 2526 } 2527 .borderRadius(this.theme.iconBorderRadius) 2528 .width(this.theme.buttonSize) 2529 .height(this.theme.buttonSize) 2530 .onClick(() => { 2531 if (index as number == 0) { 2532 this.sliderShow = false; 2533 if (this.controller) { 2534 let selection = this.controller.getSelection(); 2535 let spans = selection.spans; 2536 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2537 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2538 let span = item as RichEditorTextSpanResult; 2539 this.textStyle = span.textStyle; 2540 let start = span.offsetInSpan[0]; 2541 let end = span.offsetInSpan[1]; 2542 let offset = span.spanPosition.spanRange[0]; 2543 if (this.textStyle.fontWeight != 11) { 2544 this.textStyle.fontWeight = FontWeight.Bolder; 2545 } else { 2546 this.textStyle.fontWeight = FontWeight.Normal; 2547 } 2548 this.controller.updateSpanStyle({ 2549 start: offset + start, 2550 end: offset + end, 2551 textStyle: this.textStyle 2552 }) 2553 } 2554 }) 2555 } 2556 } else if (index as number == 1) { 2557 this.sliderShow = false; 2558 if (this.controller) { 2559 let selection = this.controller.getSelection(); 2560 let spans = selection.spans; 2561 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2562 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2563 let span = item as RichEditorTextSpanResult; 2564 this.textStyle = span.textStyle; 2565 let start = span.offsetInSpan[0]; 2566 let end = span.offsetInSpan[1]; 2567 let offset = span.spanPosition.spanRange[0]; 2568 if (this.textStyle.fontStyle == FontStyle.Italic) { 2569 this.textStyle.fontStyle = FontStyle.Normal; 2570 } else { 2571 this.textStyle.fontStyle = FontStyle.Italic; 2572 } 2573 this.controller.updateSpanStyle({ 2574 start: offset + start, 2575 end: offset + end, 2576 textStyle: this.textStyle 2577 }) 2578 } 2579 }) 2580 } 2581 } else if (index as number == 2) { 2582 this.sliderShow = false; 2583 if (this.controller) { 2584 let selection = this.controller.getSelection(); 2585 let spans = selection.spans; 2586 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2587 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2588 let span = item as RichEditorTextSpanResult; 2589 this.textStyle = span.textStyle; 2590 let start = span.offsetInSpan[0]; 2591 let end = span.offsetInSpan[1]; 2592 let offset = span.spanPosition.spanRange[0]; 2593 if (this.textStyle.decoration) { 2594 if (this.textStyle.decoration.type == TextDecorationType.Underline) { 2595 this.textStyle.decoration.type = TextDecorationType.None; 2596 } else { 2597 this.textStyle.decoration.type = TextDecorationType.Underline; 2598 } 2599 } else { 2600 this.textStyle.decoration = { type: TextDecorationType.Underline, color: Color.Black, style: TextDecorationStyle.SOLID }; 2601 } 2602 this.controller.updateSpanStyle({ 2603 start: offset + start, 2604 end: offset + end, 2605 textStyle: this.textStyle 2606 }) 2607 } 2608 }) 2609 } 2610 } else if (index as number == 3) { 2611 this.sliderShow = !this.sliderShow; 2612 } else if (index as number == 4) { 2613 this.sliderShow = false; 2614 if (this.controller) { 2615 let selection = this.controller.getSelection(); 2616 let spans = selection.spans; 2617 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2618 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2619 let span = item as RichEditorTextSpanResult; 2620 this.textStyle = span.textStyle; 2621 let start = span.offsetInSpan[0]; 2622 let end = span.offsetInSpan[1]; 2623 let offset = span.spanPosition.spanRange[0]; 2624 if (this.textStyle.fontColor == Color.Orange || this.textStyle.fontColor == '#FFFFA500') { 2625 this.textStyle.fontColor = Color.Black; 2626 } else { 2627 this.textStyle.fontColor = Color.Orange; 2628 } 2629 this.controller.updateSpanStyle({ 2630 start: offset + start, 2631 end: offset + end, 2632 textStyle: this.textStyle 2633 }) 2634 } 2635 }) 2636 } 2637 } 2638 }) 2639 .onTouch((event?: TouchEvent | undefined) => { 2640 if(event != undefined){ 2641 if (event.type === TouchType.Down) { 2642 this.iconBgColor[index as number] = $r('sys.color.ohos_id_color_click_effect'); 2643 } 2644 if (event.type === TouchType.Up) { 2645 this.iconBgColor[index as number] = this.colorTransparent; 2646 } 2647 } 2648 }) 2649 .onHover((isHover?: boolean, event?: HoverEvent) => { 2650 this.iconBgColor.forEach((icon:ResourceColor, index1) => { 2651 this.iconBgColor[index1] = this.colorTransparent; 2652 }) 2653 if(isHover != undefined) { 2654 this.iconBgColor[index as number] = $r('sys.color.ohos_id_color_hover'); 2655 } 2656 }) 2657 .backgroundColor(this.iconBgColor[index as number]) 2658 }) 2659 } 2660 } 2661 .clip(true) 2662 .width(this.theme.defaultMenuWidth) 2663 .padding(this.theme.expandedOptionPadding) 2664 .borderRadius(this.theme.containerBorderRadius) 2665 .margin({ bottom: this.theme.menuSpacing }) 2666 .backgroundColor(this.theme.backGroundColor) 2667 .shadow(this.theme.iconPanelShadowStyle) 2668 } 2669 2670 @Builder 2671 SystemMenu() { 2672 Column() { 2673 Menu() { 2674 if (this.controller) { 2675 MenuItemGroup() { 2676 MenuItem({ startIcon: this.theme.cutIcon, content: "剪切", labelInfo: "Ctrl+X" }) 2677 .onClick(() => { 2678 if (!this.controller) { 2679 return 2680 } 2681 let richEditorSelection = this.controller.getSelection(); 2682 this.PushDataToPasteboard(richEditorSelection); 2683 this.controller.deleteSpans({ 2684 start: richEditorSelection.selection[0], 2685 end: richEditorSelection.selection[1] 2686 }) 2687 }) 2688 MenuItem({ startIcon: this.theme.copyIcon, content: "复制", labelInfo: "Ctrl+C" }) 2689 .onClick(() => { 2690 if (!this.controller) { 2691 return; 2692 } 2693 let richEditorSelection = this.controller.getSelection(); 2694 this.PushDataToPasteboard(richEditorSelection) 2695 this.controller.closeSelectionMenu() 2696 }) 2697 MenuItem({ startIcon: this.theme.pasteIcon, content: "粘贴", labelInfo: "Ctrl+V" }) 2698 .enabled(this.pasteEnable) 2699 .onClick(() => { 2700 if (!this.controller) { 2701 return; 2702 } 2703 let richEditorSelection = this.controller.getSelection(); 2704 this.PopDataFromPasteboard(richEditorSelection) 2705 }) 2706 MenuItem({ startIcon: this.theme.selectAllIcon, content: "全选", labelInfo: "Ctrl+A" }) 2707 .visibility(this.visibilityValue) 2708 .onClick(() => { 2709 if (!this.controller) { 2710 return; 2711 } 2712 this.controller.setSelection(-1, -1) 2713 this.visibilityValue = Visibility.None; 2714 }) 2715 MenuItem({ startIcon: this.theme.shareIcon, content: "分享", labelInfo: "" }) 2716 .enabled(false) 2717 MenuItem({ startIcon: this.theme.translateIcon, content: "翻译", labelInfo: "" }) 2718 .enabled(false) 2719 MenuItem({ startIcon: this.theme.searchIcon, content: "搜索", labelInfo: "" }) 2720 .enabled(false) 2721 } 2722 } 2723 } 2724 .onVisibleAreaChange([0.0, 1.0], () => { 2725 if (!this.controller) { 2726 return; 2727 } 2728 let richEditorSelection = this.controller.getSelection(); 2729 let start = richEditorSelection.selection[0]; 2730 let end = richEditorSelection.selection[1]; 2731 if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) { 2732 this.visibilityValue = Visibility.None; 2733 } else { 2734 this.visibilityValue = Visibility.Visible; 2735 } 2736 }) 2737 .radius(this.theme.containerBorderRadius) 2738 .clip(true) 2739 .backgroundColor(Color.White) 2740 .width(this.theme.defaultMenuWidth) 2741 } 2742 .width(this.theme.defaultMenuWidth) 2743 } 2744 2745 @Builder sliderPanel() { 2746 Column() { 2747 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 2748 Text('A').fontSize(15) 2749 Slider({ value: this.textSize, step: 10, style: SliderStyle.InSet }) 2750 .width(210) 2751 .onChange((value: number, mode: SliderChangeMode) => { 2752 if (this.controller) { 2753 let selection = this.controller.getSelection(); 2754 if (mode == SliderChangeMode.End) { 2755 if (this.textSize == undefined) { 2756 this.textSize = 0; 2757 } 2758 let spans = selection.spans; 2759 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2760 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2761 this.textSize = Math.max(this.textSize, (item as RichEditorTextSpanResult).textStyle.fontSize); 2762 } 2763 }) 2764 } 2765 if (mode == SliderChangeMode.Moving || mode == SliderChangeMode.Click) { 2766 this.start = selection.selection[0]; 2767 this.end = selection.selection[1]; 2768 this.textSize = value; 2769 this.controller.updateSpanStyle({ 2770 start: this.start, 2771 end: this.end, 2772 textStyle: { fontSize: this.textSize } 2773 }) 2774 } 2775 } 2776 }) 2777 Text('A').fontSize(20).fontWeight(FontWeight.Medium) 2778 }.borderRadius(this.theme.containerBorderRadius) 2779 } 2780 .shadow(ShadowStyle.OUTER_DEFAULT_MD) 2781 .backgroundColor(Color.White) 2782 .borderRadius(this.theme.containerBorderRadius) 2783 .padding(15) 2784 .height(48) 2785 } 2786} 2787``` 2788> **说明:** 2789> 2790> 系统暂未预置加粗、斜体等图标,示例代码使用系统默认图标,开发者使用时需自行替换iconArr中的资源。 2791 2792 2793 2794### 示例4(更新图片样式) 2795通过[updateSpanStyle](#updatespanstyle)接口更新图片样式。 2796 2797```ts 2798// xxx.ets 2799@Entry 2800@Component 2801struct Index { 2802 controller: RichEditorController = new RichEditorController(); 2803 options: RichEditorOptions = { controller: this.controller }; 2804 private start: number = -1; 2805 private end: number = -1; 2806 @State message: string = "[-1, -1]"; 2807 @State content: string = ""; 2808 @State paddingVal: number = 5; 2809 @State borderRad: number = 4; 2810 2811 build() { 2812 Column() { 2813 Column() { 2814 Text("selection range:").width("100%") 2815 Text() { 2816 Span(this.message) 2817 }.width("100%") 2818 Text("selection content:").width("100%") 2819 Text() { 2820 Span(this.content) 2821 }.width("100%") 2822 } 2823 .borderWidth(1) 2824 .borderColor(Color.Red) 2825 .width("100%") 2826 .height("20%") 2827 2828 Row() { 2829 Button("updateSpanStyle1") 2830 .fontSize(12) 2831 .onClick(() => { 2832 this.controller.updateSpanStyle({ 2833 start: this.start, 2834 textStyle: 2835 { 2836 fontWeight: FontWeight.Bolder 2837 }, 2838 imageStyle: { 2839 size: ["80px", "80px"], 2840 layoutStyle: { 2841 borderRadius: undefined, 2842 margin: undefined 2843 } 2844 } 2845 }) 2846 }) 2847 2848 Button("updateSpanStyle2") 2849 .fontSize(12) 2850 .onClick(() => { 2851 this.controller.updateSpanStyle({ 2852 start: this.start, 2853 textStyle: 2854 { 2855 fontWeight: FontWeight.Bolder 2856 }, 2857 imageStyle: { 2858 size: ["70px", "70px"], 2859 layoutStyle: { 2860 borderRadius: { topLeft: '100px', topRight: '20px', bottomLeft: '100px', bottomRight: '20px' }, 2861 margin: { left: '30px', top: '20px', right: '20px', bottom: '20px' } 2862 } 2863 } 2864 }) 2865 }) 2866 2867 Button("updateSpanStyle3") 2868 .fontSize(12) 2869 .onClick(() => { 2870 this.controller.updateSpanStyle({ 2871 start: this.start, 2872 textStyle: 2873 { 2874 fontWeight: FontWeight.Bolder 2875 }, 2876 imageStyle: { 2877 size: ["60px", "60px"], 2878 layoutStyle: { 2879 borderRadius: '-10px', 2880 margin: '-10px' 2881 } 2882 } 2883 }) 2884 }) 2885 } 2886 .borderWidth(1) 2887 .borderColor(Color.Red) 2888 .width("100%") 2889 .height("10%") 2890 2891 Row() { 2892 Button('addImageSpan1') 2893 .fontSize(12) 2894 .onClick(() => { 2895 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 2896 this.controller.addImageSpan($r('app.media.startIcon'), { 2897 imageStyle: { 2898 size: ["80px", "80px"], 2899 layoutStyle: { 2900 borderRadius: '50px', 2901 margin: '40px' 2902 } 2903 } 2904 }) 2905 }) 2906 2907 Button('addImageSpan2') 2908 .fontSize(12) 2909 .onClick(() => { 2910 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 2911 this.controller.addImageSpan($r('app.media.startIcon'), { 2912 imageStyle: { 2913 size: ["100px", "100px"], 2914 verticalAlign: ImageSpanAlignment.BOTTOM, 2915 layoutStyle: { 2916 borderRadius: undefined, 2917 margin: undefined 2918 } 2919 } 2920 }) 2921 }) 2922 2923 Button('addImageSpan3') 2924 .fontSize(12) 2925 .onClick(() => { 2926 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 2927 this.controller.addImageSpan($r('app.media.startIcon'), { 2928 imageStyle: { 2929 size: ["60px", "60px"], 2930 verticalAlign: ImageSpanAlignment.BOTTOM, 2931 layoutStyle: { 2932 borderRadius: { topLeft: '10px', topRight: '20px', bottomLeft: '30px', bottomRight: '40px' }, 2933 margin: { left: '10px', top: '20px', right: '30px', bottom: '40px' } 2934 } 2935 } 2936 }) 2937 }) 2938 } 2939 .borderWidth(1) 2940 .borderColor(Color.Red) 2941 .width("100%") 2942 .height("10%") 2943 2944 Column() { 2945 RichEditor(this.options) 2946 .onReady(() => { 2947 this.controller.addTextSpan("0123456789", 2948 { 2949 style: 2950 { 2951 fontColor: Color.Orange, 2952 fontSize: 30 2953 } 2954 }) 2955 2956 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 2957 this.controller.addImageSpan($r('app.media.startIcon'), 2958 { 2959 imageStyle: 2960 { 2961 size: ["60px", "60px"], 2962 verticalAlign: ImageSpanAlignment.BOTTOM, 2963 layoutStyle: { 2964 borderRadius: { topLeft: '10px', topRight: '20px', bottomLeft: '30px', bottomRight: '40px' }, 2965 margin: { left: '10px', top: '20px', right: '30px', bottom: '40px' } 2966 } 2967 } 2968 }) 2969 2970 this.controller.addTextSpan("0123456789", 2971 { 2972 style: 2973 { 2974 fontColor: Color.Black, 2975 fontSize: 30 2976 } 2977 }) 2978 }) 2979 .onSelect((value: RichEditorSelection) => { 2980 this.start = value.selection[0]; 2981 this.end = value.selection[1]; 2982 this.message = "[" + this.start + ", " + this.end + "]"; 2983 }) 2984 .aboutToIMEInput((value: RichEditorInsertValue) => { 2985 console.info("---------------------- aboutToIMEInput ----------------------"); 2986 console.info("insertOffset:" + value.insertOffset); 2987 console.info("insertValue:" + value.insertValue); 2988 return true; 2989 }) 2990 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 2991 console.info("---------------------- onIMEInputComplete ---------------------"); 2992 console.info("spanIndex:" + value.spanPosition.spanIndex); 2993 console.info("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]"); 2994 console.info("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]"); 2995 console.info("value:" + value.value); 2996 }) 2997 .aboutToDelete((value: RichEditorDeleteValue) => { 2998 console.info("---------------------- aboutToDelete --------------------------"); 2999 console.info("offset:" + value.offset); 3000 console.info("direction:" + value.direction); 3001 console.info("length:" + value.length); 3002 value.richEditorDeleteSpans.forEach(item => { 3003 console.info("---------------------- item --------------------------"); 3004 console.info("spanIndex:" + item.spanPosition.spanIndex); 3005 console.info("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]"); 3006 console.info("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]"); 3007 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3008 console.info("image:" + (item as RichEditorImageSpanResult).valueResourceStr); 3009 } else { 3010 console.info("text:" + (item as RichEditorTextSpanResult).value); 3011 } 3012 }) 3013 return true; 3014 }) 3015 .onDeleteComplete(() => { 3016 console.info("---------------------- onDeleteComplete ------------------------"); 3017 }) 3018 .borderWidth(1) 3019 .borderColor(Color.Green) 3020 .width("100%") 3021 .height('80.00%') 3022 } 3023 .borderWidth(1) 3024 .borderColor(Color.Red) 3025 .width("100%") 3026 .height("70%") 3027 } 3028 } 3029} 3030``` 3031 3032 3033### 示例5(Span绑定手势事件) 3034为Span绑定[gesture](#richeditorgesture11)回调。 3035 3036```ts 3037// xxx.ets 3038@Entry 3039@Component 3040struct Index { 3041 controller: RichEditorController = new RichEditorController(); 3042 options: RichEditorOptions = { controller: this.controller }; 3043 @State textFlag: string = "TextFlag"; 3044 3045 build() { 3046 Column() { 3047 Column() { 3048 Text(this.textFlag) 3049 .copyOption(CopyOptions.InApp) 3050 .fontSize(50) 3051 .height(150) 3052 } 3053 Divider() 3054 Column() { 3055 RichEditor(this.options) 3056 .onReady(() => { 3057 this.controller.addTextSpan('Area1\n', { 3058 style: 3059 { 3060 fontColor: Color.Orange, 3061 fontSize: 50, 3062 }, 3063 gesture: 3064 { 3065 onClick: () => { 3066 this.textFlag = "Area1 is onClick."; 3067 }, 3068 onLongPress: () => { 3069 this.textFlag = "Area1 is onLongPress."; 3070 } 3071 } 3072 }) 3073 3074 this.controller.addTextSpan('Area2\n', { 3075 style: 3076 { 3077 fontColor: Color.Blue, 3078 fontSize: 50 3079 }, 3080 gesture: 3081 { 3082 onClick: () => { 3083 this.textFlag = "Area2 is onClick."; 3084 }, 3085 onLongPress: () => { 3086 this.textFlag = "Area2 is onLongPress."; 3087 } 3088 } 3089 }) 3090 3091 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 3092 this.controller.addImageSpan($r('app.media.startIcon'), 3093 { 3094 imageStyle: 3095 { 3096 size: ["100px", "100px"], 3097 layoutStyle: { 3098 margin: 5, 3099 borderRadius: 15 3100 } 3101 }, 3102 gesture: 3103 { 3104 onClick: () => { 3105 this.textFlag = "ImageSpan is onClick."; 3106 }, 3107 onLongPress: () => { 3108 this.textFlag = "ImageSpan is onLongPress."; 3109 } 3110 }, 3111 onHover : (status) => { 3112 this.textFlag = "ImageSpan is onHover :" + status; 3113 } 3114 }) 3115 }) 3116 } 3117 .borderWidth(1) 3118 .borderColor(Color.Red) 3119 .width("100%") 3120 .height("70%") 3121 } 3122 } 3123} 3124``` 3125 3126 3127### 示例6(更新和获取段落样式) 3128通过[updateParagraphStyle](#updateparagraphstyle11)接口更新段落样式,通过[getParagraphs](#getparagraphs11)接口获取指定范围段落的信息。 3129 3130```ts 3131// xxx.ets 3132@Entry 3133@Component 3134struct Index { 3135 controller: RichEditorController = new RichEditorController(); 3136 private spanParagraphs: RichEditorParagraphResult[] = []; 3137 3138 build() { 3139 Column() { 3140 RichEditor({ controller: this.controller }) 3141 .onReady(() => { 3142 this.controller.addTextSpan("0123456789\n", { 3143 style: { 3144 fontColor: Color.Pink, 3145 fontSize: "32" 3146 }, 3147 paragraphStyle: { 3148 textAlign: TextAlign.Start, 3149 textVerticalAlign: TextVerticalAlign.BASELINE, 3150 leadingMargin: 16 3151 } 3152 }) 3153 this.controller.addTextSpan("0123456789") 3154 }) 3155 .width("80%") 3156 .height("30%") 3157 .border({ width: 1, radius: 5 }) 3158 .draggable(false) 3159 3160 Column({ space: 5 }) { 3161 Button("段落左对齐").onClick(() => { 3162 this.controller.updateParagraphStyle({ start: -1, end: -1, 3163 style: { 3164 textAlign: TextAlign.Start 3165 } 3166 }) 3167 }) 3168 3169 Button("段落右对齐").onClick(() => { 3170 this.controller.updateParagraphStyle({ start: -1, end: -1, 3171 style: { 3172 textAlign: TextAlign.End 3173 } 3174 }) 3175 }) 3176 3177 Button("段落居中").onClick(() => { 3178 this.controller.updateParagraphStyle({ start: -1, end: -1, 3179 style: { 3180 textAlign: TextAlign.Center 3181 } 3182 }) 3183 }) 3184 3185 Button("段落间距设置50").onClick(() => { 3186 this.controller.updateParagraphStyle({ start: -1, end: -1, 3187 style: { 3188 paragraphSpacing: 50 3189 } 3190 }) 3191 }) 3192 Divider() 3193 Button("getParagraphs").onClick(() => { 3194 this.spanParagraphs = this.controller.getParagraphs({ start: -1, end: -1 }); 3195 console.info("RichEditor getParagraphs:" + JSON.stringify(this.spanParagraphs)); 3196 }) 3197 3198 Button("UpdateSpanStyle1").onClick(() => { 3199 this.controller.updateSpanStyle({ start: -1, end: -1, 3200 textStyle: { 3201 fontColor: Color.Brown, 3202 fontSize: 20 3203 } 3204 }) 3205 }) 3206 3207 Button("UpdateSpanStyle2").onClick(() => { 3208 this.controller.updateSpanStyle({ start: -1, end: -1, 3209 textStyle: { 3210 fontColor: Color.Green, 3211 fontSize: 30 3212 } 3213 }) 3214 }) 3215 } 3216 } 3217 } 3218} 3219``` 3220 3221 3222### 示例7(更新预设样式与缩进) 3223通过[setTypingStyle](#settypingstyle11)接口更新文本预设样式,通过[updateParagraphStyle](#updateparagraphstyle11)接口设置段落缩进。 3224 3225```ts 3226// xxx.ets 3227 3228const canvasWidth = 1000; 3229const canvasHeight = 100; 3230const Indentation = 40; 3231class LeadingMarginCreator { 3232 private settings: RenderingContextSettings = new RenderingContextSettings(true); 3233 private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(canvasWidth, canvasHeight); 3234 private offContext: OffscreenCanvasRenderingContext2D = this.offscreenCanvas.getContext("2d", this.settings); 3235 public static instance: LeadingMarginCreator = new LeadingMarginCreator(); 3236 3237 // 获得字体字号级别,分别是从0到4级 3238 public getFontSizeLevel(fontSize: number) { 3239 const fontScaled: number = Number(fontSize) / 16; 3240 3241 enum FontSizeScaleThreshold { 3242 SMALL = 0.9, 3243 NORMAL = 1.1, 3244 LEVEL_1_LARGE = 1.2, 3245 LEVEL_2_LARGE = 1.4, 3246 LEVEL_3_LARGE = 1.5 3247 } 3248 3249 let fontSizeLevel: number = 1; 3250 3251 if (fontScaled < FontSizeScaleThreshold.SMALL) { 3252 fontSizeLevel = 0; 3253 } else if (fontScaled < FontSizeScaleThreshold.NORMAL) { 3254 fontSizeLevel = 1; 3255 } else if (fontScaled < FontSizeScaleThreshold.LEVEL_1_LARGE) { 3256 fontSizeLevel = 2; 3257 } else if (fontScaled < FontSizeScaleThreshold.LEVEL_2_LARGE) { 3258 fontSizeLevel = 3; 3259 } else if (fontScaled < FontSizeScaleThreshold.LEVEL_3_LARGE) { 3260 fontSizeLevel = 4; 3261 } else { 3262 fontSizeLevel = 1; 3263 } 3264 3265 return fontSizeLevel; 3266 } 3267 // 获得字体字号级别,分别是从0到4级 3268 public getmarginLevel(Width: number) { 3269 let marginlevel: number = 1; 3270 if (Width == 40) { 3271 marginlevel = 2.0; 3272 } else if (Width == 80) { 3273 marginlevel = 1.0; 3274 } else if (Width == 120) { 3275 marginlevel = 2/3; 3276 } else if (Width == 160) { 3277 marginlevel = 0.5; 3278 } else if (Width == 200) { 3279 marginlevel = 0.4; 3280 } 3281 return marginlevel; 3282 } 3283 3284 public genStrMark(fontSize: number, str: string): PixelMap { 3285 this.offContext = this.offscreenCanvas.getContext("2d", this.settings); 3286 this.clearCanvas() 3287 this.offContext.font = fontSize + 'vp sans-serif'; 3288 this.offContext.fillText(str + '.', 0, fontSize * 0.9) 3289 return this.offContext.getPixelMap(0, 0, fontSize * (str.length + 1) / 1.75, fontSize) 3290 } 3291 3292 public genSquareMark(fontSize: number): PixelMap { 3293 this.offContext = this.offscreenCanvas.getContext("2d", this.settings); 3294 this.clearCanvas() 3295 const coordinate = fontSize * (1 - 1 / 1.5) / 2; 3296 const sideLength = fontSize / 1.5; 3297 this.offContext.fillRect(coordinate, coordinate, sideLength, sideLength) 3298 return this.offContext.getPixelMap(0, 0, fontSize, fontSize) 3299 } 3300 3301 // 生成圆圈符号 3302 public genCircleMark(fontSize: number, width: number, level?: number ): PixelMap { 3303 const indentLevel = level ?? 1; 3304 const offsetLevel = [22, 28, 32, 34, 38]; 3305 const fontSizeLevel = this.getFontSizeLevel(fontSize); 3306 const marginlevel = this.getmarginLevel(width); 3307 const newCanvas = new OffscreenCanvas(canvasWidth, canvasHeight); 3308 const newOffContext: OffscreenCanvasRenderingContext2D = newCanvas.getContext("2d", this.settings); 3309 const centerCoordinate = 50; 3310 const radius = 10; 3311 this.clearCanvas() 3312 newOffContext.ellipse(100 * (indentLevel + 1) - centerCoordinate * marginlevel, offsetLevel[fontSizeLevel], radius * marginlevel, radius, 0, 0, 2 * Math.PI) 3313 newOffContext.fillStyle = '66FF0000'; 3314 newOffContext.fill() 3315 return newOffContext.getPixelMap(0, 0, 100 + 100 * indentLevel, 100) 3316 } 3317 3318 private clearCanvas() { 3319 this.offContext.clearRect(0, 0, canvasWidth, canvasHeight) 3320 } 3321} 3322 3323@Entry 3324@Component 3325struct Index { 3326 controller: RichEditorController = new RichEditorController(); 3327 options: RichEditorOptions = { controller: this.controller }; 3328 private leadingMarkCreatorInstance = LeadingMarginCreator.instance; 3329 private fontNameRawFile: string = 'MiSans-Bold'; 3330 @State fs: number = 30; 3331 @State cl: number = Color.Black; 3332 private leftMargin: Dimension = 0; 3333 private richEditorTextStyle: RichEditorTextStyle = {}; 3334 3335 aboutToAppear() { 3336 this.getUIContext().getFont().registerFont({ 3337 familyName: 'MiSans-Bold', 3338 familySrc: '/font/MiSans-Bold.ttf' 3339 }) 3340 } 3341 3342 build() { 3343 Scroll() { 3344 Column() { 3345 RichEditor(this.options) 3346 .onReady(() => { 3347 this.controller.addTextSpan("0123456789\n", 3348 { 3349 style: 3350 { 3351 fontWeight: 'medium', 3352 fontFamily: this.fontNameRawFile, 3353 fontColor: Color.Red, 3354 fontSize: 50, 3355 fontStyle: FontStyle.Italic, 3356 decoration: { type: TextDecorationType.Underline, color: Color.Green } 3357 } 3358 }) 3359 3360 this.controller.addTextSpan("abcdefg", 3361 { 3362 style: 3363 { 3364 fontWeight: FontWeight.Lighter, 3365 fontFamily: 'HarmonyOS Sans', 3366 fontColor: 'rgba(0,128,0,0.5)', 3367 fontSize: 30, 3368 fontStyle: FontStyle.Normal, 3369 decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' } 3370 } 3371 }) 3372 }) 3373 .borderWidth(1) 3374 .borderColor(Color.Green) 3375 .width("100%") 3376 .height("50%") 3377 3378 Row({ space: 5 }) { 3379 Button('setTypingStyle1') 3380 .fontSize(10) 3381 .onClick(() => { 3382 this.controller.setTypingStyle( 3383 { 3384 fontWeight: 'medium', 3385 fontFamily: this.fontNameRawFile, 3386 fontColor: Color.Blue, 3387 fontSize: 50, 3388 fontStyle: FontStyle.Italic, 3389 decoration: { type: TextDecorationType.Underline, color: Color.Green } 3390 }) 3391 }) 3392 3393 Button('setTypingStyle2') 3394 .fontSize(10) 3395 .onClick(() => { 3396 this.controller.setTypingStyle( 3397 { 3398 fontWeight: FontWeight.Lighter, 3399 fontFamily: 'HarmonyOS Sans', 3400 fontColor: Color.Green, 3401 fontSize: '30', 3402 fontStyle: FontStyle.Normal, 3403 decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' } 3404 }) 3405 }) 3406 } 3407 Divider() 3408 Button("getTypingStyle").onClick(() => { 3409 this.richEditorTextStyle = this.controller.getTypingStyle(); 3410 console.info("RichEditor getTypingStyle:" + JSON.stringify(this.richEditorTextStyle)); 3411 }) 3412 Divider() 3413 Row({ space: 5 }) { 3414 Button("向右列表缩进").onClick(() => { 3415 let margin = Number(this.leftMargin); 3416 if (margin < 200) { 3417 margin += Indentation; 3418 this.leftMargin = margin; 3419 } 3420 this.controller.updateParagraphStyle({ 3421 start: -10, 3422 end: -10, 3423 style: { 3424 leadingMargin : { 3425 pixelMap : this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1), 3426 size: [margin, 40] 3427 } 3428 } 3429 }) 3430 }) 3431 3432 Button("向左列表缩进").onClick(() => { 3433 let margin = Number(this.leftMargin); 3434 if (margin > 0) { 3435 margin -= Indentation; 3436 this.leftMargin = margin; 3437 } 3438 this.controller.updateParagraphStyle({ 3439 start: -10, 3440 end: -10, 3441 style: { 3442 leadingMargin : { 3443 pixelMap : this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1), 3444 size: [margin, 40] 3445 } 3446 } 3447 }) 3448 }) 3449 } 3450 Divider() 3451 Row({ space: 5 }) { 3452 Button("向右空白缩进").onClick(() => { 3453 let margin = Number(this.leftMargin); 3454 if (margin < 200) { 3455 margin += Indentation; 3456 this.leftMargin = margin; 3457 } 3458 this.controller.updateParagraphStyle({ 3459 start: -10, 3460 end: -10, 3461 style: { 3462 leadingMargin: margin 3463 } 3464 }) 3465 }) 3466 3467 Button("向左空白缩进").onClick(() => { 3468 let margin = Number(this.leftMargin) 3469 if (margin > 0) { 3470 margin -= Indentation; 3471 this.leftMargin = margin; 3472 } 3473 this.controller.updateParagraphStyle({ 3474 start: -10, 3475 end: -10, 3476 style: { 3477 leadingMargin: margin 3478 } 3479 }) 3480 }) 3481 } 3482 }.borderWidth(1).borderColor(Color.Red) 3483 } 3484 } 3485} 3486``` 3487 3488 3489### 示例8(设置文本字重与阴影) 3490通过[updateParagraphStyle](#updateparagraphstyle11)接口设置文本字重与阴影。 3491 3492``` ts 3493@Entry 3494@Component 3495struct Index { 3496 controller: RichEditorController = new RichEditorController(); 3497 options: RichEditorOptions = { controller: this.controller }; 3498 private start: number = -1; 3499 private end: number = -1; 3500 @State message: string = "[-1, -1]" 3501 @State content: string = "" 3502 @State textShadows : Array<ShadowOptions> = [ 3503 { radius: 10, color: Color.Red, offsetX: 10, offsetY: 0 }, 3504 { radius: 10, color: Color.Black, offsetX: 20, offsetY: 0 }, 3505 { radius: 10, color: Color.Brown, offsetX: 30, offsetY: 0 }, 3506 { radius: 10, color: Color.Green, offsetX: 40, offsetY: 0 }, 3507 { radius: 10, color: Color.Yellow, offsetX: 100, offsetY: 0 } 3508 ]; 3509 3510 build() { 3511 Column() { 3512 Column() { 3513 Text("selection range:").width("100%") 3514 Text() { 3515 Span(this.message) 3516 }.width("100%") 3517 Text("selection content:").width("100%") 3518 Text() { 3519 Span(this.content) 3520 }.width("100%") 3521 } 3522 .borderWidth(1) 3523 .borderColor(Color.Red) 3524 .width("100%") 3525 .height("20%") 3526 Row() { 3527 Button("更新样式: 加粗 & 文本阴影").onClick(() => { 3528 this.controller.updateSpanStyle({ 3529 start: this.start, 3530 end: this.end, 3531 textStyle: 3532 { 3533 fontWeight: FontWeight.Bolder, 3534 textShadow: this.textShadows 3535 } 3536 }) 3537 }) 3538 } 3539 .borderWidth(1) 3540 .borderColor(Color.Red) 3541 .width("100%") 3542 .height("10%") 3543 Column() { 3544 RichEditor(this.options) 3545 .onReady(() => { 3546 this.controller.addTextSpan("0123456789", 3547 { 3548 style: 3549 { 3550 fontColor: Color.Orange, 3551 fontSize: 30, 3552 textShadow: { radius: 10, color: Color.Blue, offsetX: 10, offsetY: 0 } 3553 } 3554 }) 3555 }) 3556 .borderWidth(1) 3557 .borderColor(Color.Green) 3558 .width("100%") 3559 .height("30%") 3560 } 3561 .borderWidth(1) 3562 .borderColor(Color.Red) 3563 .width("100%") 3564 .height("70%") 3565 } 3566 } 3567} 3568``` 3569 3570 3571 3572### 示例9(添加用户自定义布局Span) 3573通过[addBuilderSpan](#addbuilderspan11)接口添加用户自定义布局Span。 3574 3575``` ts 3576@Builder 3577function placeholderBuilder2() { 3578 Row({ space: 2 }) { 3579 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 3580 Image($r('app.media.startIcon')).width(24).height(24).margin({ left: -5 }) 3581 Text('okokokok').fontSize(10) 3582 }.width('20%').height(50).padding(10).backgroundColor(Color.Red) 3583} 3584 3585// xxx.ets 3586@Entry 3587@Component 3588struct Index { 3589 controller: RichEditorController = new RichEditorController(); 3590 option: RichEditorOptions = { controller: this.controller }; 3591 private start: number = 2; 3592 private end: number = 4; 3593 @State message: string = "[-1, -1]"; 3594 @State content: string = ""; 3595 private my_offset: number | undefined = undefined; 3596 private my_builder: CustomBuilder = undefined; 3597 @BuilderParam my_builder2:() => void = placeholderBuilder2; 3598 3599 @Builder 3600 placeholderBuilder() { 3601 Row({ space: 2 }) { 3602 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 3603 Image($r('app.media.startIcon')).width(24).height(24).margin({ left: -5 }) 3604 Text('Custom Popup').fontSize(10) 3605 }.width(100).height(50).padding(5) 3606 } 3607 3608 @Builder 3609 placeholderBuilder3() { 3610 Text("hello").padding('20').borderWidth(1).width('100%') 3611 } 3612 3613 @Builder 3614 placeholderBuilder4() { 3615 Column() { 3616 Column({ space: 5 }) { 3617 Text('direction:Row').fontSize(9).fontColor(0xCCCCCC).width('90%') 3618 Flex({ direction: FlexDirection.Row }) { // 子组件在容器主抽上行布局 3619 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3620 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3621 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3622 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3623 } 3624 .height(70) 3625 .width('90%') 3626 .padding(10) 3627 .backgroundColor(0xAFEEEE) 3628 3629 Text('direction:RowReverse').fontSize(9).fontColor(0xCCCCCC).width('90%') 3630 Flex({ direction: FlexDirection.RowReverse }) { // 子组件在容器主抽上反向行布局 3631 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3632 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3633 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3634 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3635 } 3636 .height(70) 3637 .width('90%') 3638 .padding(10) 3639 .backgroundColor(0xAFEEEE) 3640 3641 Text('direction:Column').fontSize(9).fontColor(0xCCCCCC).width('90%') 3642 Flex({ direction: FlexDirection.Column }) { // 子组件在容器主抽上列布局 3643 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3644 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3645 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3646 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3647 } 3648 .height(160) 3649 .width('90%') 3650 .padding(10) 3651 .backgroundColor(0xAFEEEE) 3652 3653 Text('direction:ColumnReverse').fontSize(9).fontColor(0xCCCCCC).width('90%') 3654 Flex({ direction: FlexDirection.ColumnReverse }) { // 子组件在容器主抽上反向列布局 3655 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3656 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3657 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3658 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3659 } 3660 .height(160) 3661 .width('90%') 3662 .padding(10) 3663 .backgroundColor(0xAFEEEE) 3664 }.width('100%').margin({ top: 5 }) 3665 }.width('100%') 3666 } 3667 3668 @Builder 3669 MyMenu() { 3670 Menu() { 3671 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 3672 MenuItem({ startIcon: $r('app.media.startIcon'), content: "菜单选项1" }) 3673 MenuItem({ startIcon: $r('app.media.startIcon'), content: "菜单选项2" }) 3674 .enabled(false) 3675 } 3676 } 3677 3678 build() { 3679 Column() { 3680 Column() { 3681 Text("selection range:").width("100%") 3682 Text() { 3683 Span(this.message) 3684 }.width("100%") 3685 3686 Text("selection content:").width("100%") 3687 Text() { 3688 Span(this.content) 3689 }.width("100%") 3690 } 3691 .borderWidth(1) 3692 .borderColor(Color.Red) 3693 .width("100%") 3694 .height("20%") 3695 3696 Row() { 3697 Button("获取选择内容 getSpans").onClick(() => { 3698 console.info('getSpans='+JSON.stringify(this.controller.getSpans({ start:1, end:5 }))); 3699 console.info('getParagraphs='+JSON.stringify(this.controller.getParagraphs({ start:1, end:5 }))); 3700 this.content = ""; 3701 this.controller.getSpans({ 3702 start: this.start, 3703 end: this.end 3704 }).forEach(item => { 3705 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3706 if ((item as RichEditorImageSpanResult).valueResourceStr == "") { 3707 console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + 3708 (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1]) 3709 } else { 3710 console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " + 3711 (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + 3712 (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1]) 3713 } 3714 } else { 3715 this.content += (item as RichEditorTextSpanResult).value; 3716 this.content += "\n"; 3717 console.info("text span: " + (item as RichEditorTextSpanResult).value); 3718 } 3719 }) 3720 }) 3721 Button("获取选择内容 getSelection").onClick(() => { 3722 this.content = ""; 3723 let select = this.controller.getSelection(); 3724 console.info("selection start " + select.selection[0] + " end " + select.selection[1]); 3725 select.spans.forEach(item => { 3726 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3727 if ((item as RichEditorImageSpanResult).valueResourceStr == "") { 3728 console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + 3729 (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1]) 3730 } else { 3731 console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " + 3732 (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + 3733 (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1]) 3734 } 3735 } else { 3736 this.content += (item as RichEditorTextSpanResult).value; 3737 this.content += "\n"; 3738 console.info("text span: " + (item as RichEditorTextSpanResult).value); 3739 } 3740 }) 3741 }) 3742 Button("删除选择内容").onClick(() => { 3743 this.controller.deleteSpans({ 3744 start: this.start, 3745 end: this.end 3746 }) 3747 }) 3748 } 3749 .borderWidth(1) 3750 .borderColor(Color.Red) 3751 .width("100%") 3752 .height("10%") 3753 3754 Column() { 3755 RichEditor(this.option) 3756 .onReady(() => { 3757 this.controller.addTextSpan("0123456789", 3758 { 3759 style: 3760 { 3761 fontColor: Color.Orange, 3762 fontSize: 30 3763 } 3764 }) 3765 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 3766 this.controller.addImageSpan($r('app.media.startIcon'), 3767 { 3768 imageStyle: 3769 { 3770 size: ["57px", "57px"] 3771 } 3772 }) 3773 }) 3774 .onSelect((value: RichEditorSelection) => { 3775 this.start = value.selection[0]; 3776 this.end = value.selection[1]; 3777 this.message = "[" + this.start + ", " + this.end + "]"; 3778 console.info("onSelect="+JSON.stringify(value)); 3779 }) 3780 .aboutToIMEInput((value: RichEditorInsertValue) => { 3781 console.info("---------------------- aboutToIMEInput --------------------"); 3782 console.info("aboutToIMEInput="+JSON.stringify(value)); 3783 console.info("insertOffset:" + value.insertOffset); 3784 console.info("insertValue:" + value.insertValue); 3785 return true; 3786 }) 3787 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 3788 console.info("---------------------- onIMEInputComplete --------------------"); 3789 console.info("onIMEInputComplete="+JSON.stringify(value)); 3790 console.info("spanIndex:" + value.spanPosition.spanIndex); 3791 console.info("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]"); 3792 console.info("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]"); 3793 console.info("value:" + value.value); 3794 }) 3795 .aboutToDelete((value: RichEditorDeleteValue) => { 3796 value.richEditorDeleteSpans.forEach(item => { 3797 console.info("---------------------- item --------------------"); 3798 console.info("spanIndex=" + item.spanPosition.spanIndex); 3799 console.info("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]"); 3800 console.info("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]"); 3801 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3802 if ((item as RichEditorImageSpanResult).valueResourceStr == "") { 3803 console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + 3804 (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1]) 3805 } else { 3806 console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " + 3807 (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + 3808 (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1]) 3809 } 3810 } else { 3811 console.info("delete text: " + (item as RichEditorTextSpanResult).value); 3812 } 3813 }) 3814 return true; 3815 }) 3816 .borderWidth(1) 3817 .borderColor(Color.Green) 3818 .width("100%") 3819 .height("30%") 3820 3821 Button("add span") 3822 .onClick(() => { 3823 let num = this.controller.addBuilderSpan(this.my_builder, { offset: this.my_offset }); 3824 console.info('addBuilderSpan return ' + num); 3825 }) 3826 Button("add image") 3827 .onClick(() => { 3828 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 3829 let num = this.controller.addImageSpan($r('app.media.startIcon'), { 3830 imageStyle: { 3831 size: ["50px", "50px"], 3832 verticalAlign: ImageSpanAlignment.BOTTOM, 3833 layoutStyle: { 3834 borderRadius: undefined, 3835 margin: undefined 3836 } 3837 } 3838 }) 3839 console.info('addImageSpan return' + num); 3840 }) 3841 Row() { 3842 Button('builder1').onClick(() => { 3843 this.my_builder = () => { 3844 this.placeholderBuilder() 3845 }; 3846 }) 3847 Button('builder2').onClick(() => { 3848 this.my_builder = () => { 3849 this.my_builder2() 3850 }; 3851 }) 3852 Button('builder3').onClick(() => { 3853 this.my_builder = () => { 3854 this.placeholderBuilder3() 3855 }; 3856 }) 3857 Button('builder4').onClick(() => { 3858 this.my_builder = () => { 3859 this.placeholderBuilder4() 3860 }; 3861 }) 3862 } 3863 } 3864 .borderWidth(1) 3865 .borderColor(Color.Red) 3866 .width("100%") 3867 .height("70%") 3868 } 3869 } 3870} 3871``` 3872 3873 3874### 示例10(使用和管理组件内的BuilderSpan) 3875通过[addBuilderSpan](#addbuilderspan11)接口添加的自定义布局Span,[getSpans](#getspans)、[onWillChange](#onwillchange12)等API不会返回BuilderSpan内部的信息。开发者需要自行维护BuilderSpan的状态,并且在组件内容发生变化时同步更新。 3876 3877```ts 3878const TAG = 'BuilderSpanDemo'; 3879 3880class BuilderObject { 3881 content: string 3882 imageUri?: string 3883 type: string 3884 id?: string 3885 3886 constructor(content: string, type: string, imageUri?: string, id?: string) { 3887 this.content = content 3888 this.imageUri = imageUri 3889 this.type = type 3890 this.id = id 3891 } 3892} 3893 3894@Entry 3895@Component 3896struct Index { 3897 controller: RichEditorController = new RichEditorController() 3898 option: RichEditorOptions = { controller: this.controller } 3899 @State content: string = ""; 3900 @State start: number = 0; 3901 @State end: number = 0; 3902 private customBuilder: CustomBuilder = undefined; 3903 private builderArray: BuilderObject[] = []; 3904 private indicesToRemove: number[] = []; 3905 private builderId: number = 0; 3906 3907 @Builder 3908 imageTextBuilder(builder: BuilderObject) { 3909 Row({ space: 2 }) { 3910 Image($r(builder.imageUri)).width(24).height(24).margin({ left: -5 }) 3911 Text(builder.content).fontSize(10) 3912 }.width(110).height(50).padding(5) 3913 } 3914 3915 @Builder 3916 chipBuilder(builder: BuilderObject) { 3917 Row() { 3918 Text(builder.content) 3919 .fontSize(14) 3920 .fontColor(Color.Black) 3921 .fontFamily('HarmonyHeiTi') 3922 .margin({ right: 4 }) 3923 3924 SymbolGlyph($r('sys.symbol.xmark')) 3925 .width(16) 3926 .height(16) 3927 .id(builder.id) 3928 .onClick((event: ClickEvent) => { 3929 this.deleteChipBuilder(event.target.id) 3930 }) 3931 } 3932 .width('auto') 3933 .height(28) 3934 .backgroundColor(Color.Gray) 3935 .borderRadius(10) 3936 .padding({ 3937 top: 4, 3938 bottom: 4, 3939 left: 12, 3940 right: 12 3941 }) 3942 } 3943 3944 private deleteChipBuilder(builderId?: string) { 3945 if (builderId == null || builderId == "") { 3946 console.info(TAG, "delete chipBuilder error"); 3947 return 3948 } 3949 let deleteRange: number[] = this.getTargetBuilderSpanRange(builderId) 3950 if (deleteRange.length == 0) { 3951 console.error(TAG, "getTargetBuilderSpanRange failed" + builderId); 3952 return 3953 } 3954 this.builderArray = this.builderArray.filter(item => item.id !== builderId); 3955 this.controller.deleteSpans({ start: deleteRange[0], end: deleteRange[1] }); 3956 console.info(TAG, `deleteChipBuilder start = ${deleteRange[0]}, end = ${deleteRange[1]}`); 3957 console.info(TAG, `deleteChipBuilder builderArray + ${this.builderArray.length}`); 3958 } 3959 3960 private getTargetBuilderSpanRange(builderId: string): number[] { 3961 let allSpans = this.controller.getSpans(); 3962 let result: number[] = []; 3963 let chitBuilderIndex = 0; 3964 for (let spanIndex = 0; spanIndex < allSpans.length; spanIndex++) { 3965 if (!this.isBuilderSpanResult(allSpans[spanIndex])) { 3966 continue; 3967 } 3968 if (this.builderArray.length <= chitBuilderIndex) { 3969 break; 3970 } 3971 if (this.builderArray[chitBuilderIndex].id === builderId) { 3972 result = allSpans[spanIndex].spanPosition.spanRange; 3973 break; 3974 } 3975 chitBuilderIndex++; 3976 } 3977 return result; 3978 } 3979 3980 private isTextSpanResult(item: RichEditorImageSpanResult | RichEditorTextSpanResult): boolean { 3981 return typeof (item as RichEditorImageSpanResult)['imageStyle'] == 'undefined'; 3982 } 3983 3984 private isBuilderSpanResult(item: RichEditorImageSpanResult | RichEditorTextSpanResult): boolean { 3985 return typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined' 3986 && ((item as RichEditorImageSpanResult).valueResourceStr == " " 3987 || (item as RichEditorImageSpanResult).valueResourceStr == ""); 3988 } 3989 3990 build() { 3991 Column() { 3992 Scroll() { 3993 Column() { 3994 Text("Builder Info:").width("100%") 3995 Text() { 3996 Span(this.content) 3997 }.width("100%") 3998 } 3999 } 4000 .borderWidth(1) 4001 .borderColor(Color.Red) 4002 .width("100%") 4003 .height("20%") 4004 4005 // 添加Builder时,记录builder的相对顺序,以及builder信息 4006 // getSpans接口valueResourceStr == " "或""的Span是builderSpan,并且会按顺序返回builder 4007 // 可以根据上面两点,在查询时还原builder信息 4008 Button("addImageTextBuilder") 4009 .onClick(() => { 4010 let insertOffset = this.controller.getCaretOffset(); 4011 // 'app.media.startIcon'需要替换为开发者所需的图像资源文件。 4012 let builder = new BuilderObject('Custom PopUP ' + this.builderId, 'imageTextBuilder', 'app.media.startIcon'); 4013 this.customBuilder = () => { 4014 this.imageTextBuilder(builder); 4015 } 4016 let addIndex = this.addBuilderByIndex(insertOffset); 4017 console.info(TAG, "add imageTextBuilder index = " + addIndex); 4018 this.builderArray.splice(addIndex, 0, builder); 4019 this.controller.addBuilderSpan(this.customBuilder, { offset: insertOffset }); 4020 this.builderId++; 4021 console.info(TAG, "add imageTextBuilder success"); 4022 }) 4023 Button("addChipBuilder") 4024 .onClick(() => { 4025 let insertOffset = this.controller.getCaretOffset(); 4026 let builder = new BuilderObject('Hello World ' + this.builderId, 'chipBuilder', '', 4027 'chipBuilder' + this.builderId); 4028 this.customBuilder = () => { 4029 this.chipBuilder(builder); 4030 } 4031 let addIndex = this.addBuilderByIndex(insertOffset); 4032 console.info(TAG, "add addChipBuilder index = " + addIndex); 4033 this.builderArray.splice(addIndex, 0, builder); 4034 this.controller.addBuilderSpan(this.customBuilder, { offset: insertOffset }); 4035 this.builderId++; 4036 console.info(TAG, "add chipBuilder success"); 4037 }) 4038 4039 Row() { 4040 Button("getSpans").onClick(() => { 4041 console.info(TAG, "getSpans = " + JSON.stringify(this.controller.getSpans())); 4042 this.content = ""; 4043 let allSpans = this.controller.getSpans(); 4044 let builderSpanIndex = 0; 4045 allSpans.forEach(item => { 4046 if (this.isTextSpanResult(item)) { 4047 console.info(TAG, "text span value: " + (item as RichEditorTextSpanResult).value); 4048 } else if (this.isBuilderSpanResult(item)) { 4049 let builderOrder = "This is builderSpan " + builderSpanIndex + ":" 4050 console.info(TAG, builderOrder); 4051 this.content += builderOrder + "\n"; 4052 let builderResult = (item as RichEditorImageSpanResult); 4053 let builderIndex = "index: " + builderResult.spanPosition.spanIndex 4054 + ", range: " + builderResult.spanPosition.spanRange[0] + ", " 4055 + builderResult.spanPosition.spanRange[1]; 4056 console.info(TAG, builderIndex); 4057 this.content += builderIndex + "\n"; 4058 if (builderSpanIndex >= this.builderArray.length) { 4059 console.error(TAG, "getSpans error, builderSpanIndex = " + builderSpanIndex 4060 + ", builderArray.length = " + this.builderArray.length); 4061 return; 4062 } 4063 let builderInfo = "content: " + this.builderArray[builderSpanIndex].content 4064 + ", image uri: " + this.builderArray[builderSpanIndex].imageUri 4065 + ", id: " + this.builderArray[builderSpanIndex].id + "\n\n"; 4066 console.info(TAG, builderInfo); 4067 this.content += builderInfo; 4068 builderSpanIndex++; 4069 } else { 4070 let imageResult = (item as RichEditorImageSpanResult); 4071 console.info(TAG, "image span " + imageResult.valueResourceStr + ", index: " + 4072 imageResult.spanPosition.spanIndex + ", range: " + 4073 imageResult.offsetInSpan[0] + ", " + imageResult.offsetInSpan[1] + ", size: " + 4074 imageResult.imageStyle.size[0] + ", " + imageResult.imageStyle.size[1]); 4075 } 4076 }) 4077 }) 4078 Button("deleteSelectedSpans") 4079 .onClick(() => { 4080 this.start = this.controller.getSelection().selection[0]; 4081 this.end = this.controller.getSelection().selection[1]; 4082 if (this.start == this.end) { 4083 return; 4084 } 4085 let allSpans = this.controller.getSpans(); 4086 let needRemoveIndex = 0; 4087 for (let i = 0; i < allSpans.length; i++) { 4088 if (!this.isBuilderSpanResult(allSpans[i])) { 4089 continue; 4090 } 4091 let builderIndex = (allSpans[i] as RichEditorImageSpanResult).spanPosition.spanRange[0]; 4092 if (builderIndex < this.start || builderIndex >= this.end) { 4093 needRemoveIndex++; 4094 continue; 4095 } 4096 this.indicesToRemove.push(needRemoveIndex); 4097 needRemoveIndex++; 4098 } 4099 console.info(TAG, "deleteSpans indicesToRemove = " + this.indicesToRemove.toString()); 4100 this.deleteBuilderByIndices(); 4101 console.info(TAG, "deleteSpans builderArray = " + this.builderArray.length); 4102 this.controller.deleteSpans({ start: this.start, end: this.end }); 4103 }) 4104 } 4105 .borderWidth(1) 4106 .borderColor(Color.Red) 4107 .width("100%") 4108 .height("5%") 4109 4110 Column() { 4111 RichEditor(this.option) 4112 .onReady(() => { 4113 this.controller.addTextSpan("0123456789", 4114 { 4115 style: 4116 { 4117 fontColor: Color.Orange, 4118 fontSize: 30 4119 } 4120 }) 4121 }) 4122 .aboutToDelete((value: RichEditorDeleteValue) => { 4123 console.info(TAG, "aboutToDelete = " + JSON.stringify(value)); 4124 let isBuilderAboutToDelete = this.isBuilderAboutToDelete(value); 4125 console.info(TAG, "aboutToDelete isBuilderAboutToDelete = " + isBuilderAboutToDelete); 4126 this.getIndicesToRemove(value, isBuilderAboutToDelete); 4127 console.info(TAG, "indicesToRemove = " + this.indicesToRemove.toString()); 4128 this.deleteBuilderByIndices(); 4129 console.info(TAG, "builderArray = " + this.builderArray.length); 4130 return true; 4131 }) 4132 .borderWidth(1) 4133 .borderColor(Color.Green) 4134 .width("100%") 4135 .height("30%") 4136 } 4137 .margin({ top: 60 }) 4138 .borderWidth(1) 4139 .borderColor(Color.Red) 4140 .width("100%") 4141 .height("70%") 4142 } 4143 } 4144 4145 private isBuilderAboutToDelete(value: RichEditorDeleteValue): boolean { 4146 let flag = false; 4147 for (let i = 0; i < value.richEditorDeleteSpans.length; i++) { 4148 if (this.isBuilderSpanResult(value.richEditorDeleteSpans[i])) { 4149 flag = true; 4150 break; 4151 } 4152 } 4153 return flag; 4154 } 4155 4156 private getIndicesToRemove(value: RichEditorDeleteValue, isBuilderAboutToDelete: boolean): void { 4157 if (!isBuilderAboutToDelete) { 4158 return 4159 } 4160 let allSpans = this.controller.getSpans(); 4161 for (let i = 0; i < value.richEditorDeleteSpans.length; i++) { 4162 let needRemoveIndex = 0; 4163 let item = value.richEditorDeleteSpans[i]; 4164 if (!this.isBuilderSpanResult(item)) { 4165 continue; 4166 } 4167 let aboutToDeleteBuilderIndex = (item as RichEditorImageSpanResult).spanPosition.spanIndex 4168 for (let j = 0; j < allSpans.length; j++) { 4169 if (!this.isBuilderSpanResult(allSpans[j])) { 4170 continue; 4171 } 4172 let builderIndex = (allSpans[j] as RichEditorImageSpanResult).spanPosition.spanIndex 4173 if (builderIndex == aboutToDeleteBuilderIndex) { 4174 this.indicesToRemove.push(needRemoveIndex) 4175 break; 4176 } 4177 needRemoveIndex++; 4178 } 4179 } 4180 } 4181 4182 private deleteBuilderByIndices(): void { 4183 let indicesSet: Set<number> = new Set(this.indicesToRemove); 4184 let newLength = 0; 4185 for (let i = 0; i < this.builderArray.length; i++) { 4186 if (!indicesSet.has(i)) { 4187 this.builderArray[newLength] = this.builderArray[i]; 4188 newLength++; 4189 } 4190 } 4191 this.builderArray.length = newLength; 4192 this.indicesToRemove.length = 0; 4193 } 4194 4195 private addBuilderByIndex(insertOffset: number): number { 4196 if (insertOffset == 0 || this.builderArray.length == 0) { 4197 return 0; 4198 } 4199 let allSpans = this.controller.getSpans(); 4200 let addIndex = 0; 4201 for (let i = 0; i < allSpans.length; i++) { 4202 if (!this.isBuilderSpanResult(allSpans[i])) { 4203 continue; 4204 } 4205 let builderIndex = (allSpans[i] as RichEditorImageSpanResult).spanPosition.spanRange[0]; 4206 if (builderIndex < insertOffset) { 4207 addIndex++; 4208 continue; 4209 } 4210 break; 4211 } 4212 return addIndex; 4213 } 4214} 4215``` 4216 4217 4218### 示例11(设置文本识别配置) 4219设置[enableDataDetector](#enabledatadetector11)为true时,通过[dataDetectorConfig](#datadetectorconfig11)接口设置文本识别配置。 4220 4221```ts 4222@Entry 4223@Component 4224struct TextExample7 { 4225 controller: RichEditorController = new RichEditorController(); 4226 options: RichEditorOptions = { controller: this.controller }; 4227 @State phoneNumber: string = '(86) (755) ********'; 4228 @State url: string = 'www.********.com'; 4229 @State email: string = '***@example.com'; 4230 @State address: string = 'XX省XX市XX区XXXX'; 4231 @State enableDataDetector: boolean = true; 4232 @State enablePreviewText: boolean = false; 4233 @State types: TextDataDetectorType[] = []; 4234 4235 build() { 4236 Row() { 4237 Column() { 4238 RichEditor(this.options) 4239 .onReady(() => { 4240 this.controller.addTextSpan('电话号码:' + this.phoneNumber + '\n', 4241 { 4242 style: 4243 { 4244 fontSize: 30 4245 } 4246 }) 4247 this.controller.addTextSpan('链接:' + this.url + '\n', 4248 { 4249 style: 4250 { 4251 fontSize: 30 4252 } 4253 }) 4254 this.controller.addTextSpan('邮箱:' + this.email + '\n', 4255 { 4256 style: 4257 { 4258 fontSize: 30 4259 } 4260 }) 4261 this.controller.addTextSpan('地址:' + this.address, 4262 { 4263 style: 4264 { 4265 fontSize: 30 4266 } 4267 }) 4268 }) 4269 .copyOptions(CopyOptions.InApp) 4270 .enableDataDetector(this.enableDataDetector) 4271 .dataDetectorConfig({types : this.types, onDetectResultUpdate: (result: string)=>{}}) 4272 .enablePreviewText(this.enablePreviewText) 4273 .borderWidth(1) 4274 .padding(10) 4275 .width('100%') 4276 } 4277 .width('100%') 4278 } 4279 } 4280} 4281``` 4282### 示例12(设置光标、手柄和底板颜色) 4283通过[caretColor](#caretcolor12)属性设置输入框光标、手柄颜色,通过[selectedBackgroundColor](#selectedbackgroundcolor12)属性设置文本选中底板颜色。 4284 4285``` ts 4286@Entry 4287@Component 4288struct RichEditorDemo { 4289 @State color: Color = Color.Black; 4290 controller: RichEditorController = new RichEditorController(); 4291 4292 build() { 4293 Column() { 4294 Row() { 4295 Button("改为红色").onClick(() => { 4296 this.color = Color.Red; 4297 }) 4298 }.margin({ top: 50 }) 4299 4300 RichEditor({ controller: this.controller }) 4301 .onReady(() => { 4302 this.controller.addTextSpan('通过caretColor和selectedBackgroundColor属性设置光标和选中背景色'); 4303 }) 4304 .width("100%") 4305 .border({ width: 1, radius: 5 }) 4306 .key('RichEditor') 4307 .caretColor(this.color)//光标颜色 4308 .selectedBackgroundColor(this.color)//选中背景色 4309 .margin({ top: 50 }) 4310 } 4311 .width('100%') 4312 } 4313} 4314``` 4315 4316 4317### 示例13(设置行高和字符间距) 4318通过[updateSpanStyle](#updatespanstyle)接口配置文本行高([lineHeight](#richeditortextstyle))和字符间距([letterSpacing](#richeditortextstyle))。 4319 4320```ts 4321@Entry 4322@Component 4323struct RichEditorDemo03 { 4324 controller: RichEditorController = new RichEditorController(); 4325 options: RichEditorOptions = { controller: this.controller }; 4326 @State start: number = -1; 4327 @State end: number = -1; 4328 @State LH:number = 50; 4329 @State LS:number = 20; 4330 4331 build() { 4332 Column() { 4333 Scroll(){ 4334 Column(){ 4335 Row() { 4336 Button("行高++").onClick(()=>{ 4337 this.LH = this.LH + 5; 4338 this.controller.updateSpanStyle({ 4339 start: this.start, 4340 end: this.end, 4341 textStyle: 4342 { 4343 lineHeight: this.LH 4344 } 4345 }) 4346 }) 4347 Button("行高--").onClick(()=>{ 4348 this.LH = this.LH - 5; 4349 this.controller.updateSpanStyle({ 4350 start: this.start, 4351 end: this.end, 4352 textStyle: 4353 { 4354 lineHeight: this.LH 4355 } 4356 }) 4357 }) 4358 Button("字符间距++").onClick(()=>{ 4359 this.LS = this.LS + 5 4360 this.controller.updateSpanStyle({ 4361 start: this.start, 4362 end: this.end, 4363 textStyle: 4364 { 4365 letterSpacing: this.LS 4366 } 4367 }) 4368 }) 4369 Button("字符间距--").onClick(()=>{ 4370 this.LS = this.LS - 5 4371 this.controller.updateSpanStyle({ 4372 start: this.start, 4373 end: this.end, 4374 textStyle: 4375 { 4376 letterSpacing: this.LS 4377 } 4378 }) 4379 }) 4380 } 4381 } 4382 }.borderWidth(1) 4383 .borderColor(Color.Red) 4384 .width("100%") 4385 .height("20%") 4386 .margin({top: 20}) 4387 4388 Scroll(){ 4389 Column() { 4390 Text("LineHeight:" + this.LH).width("100%") 4391 Text("LetterSpacing:" + this.LS).width("100%") 4392 } 4393 } 4394 .borderWidth(1) 4395 .borderColor(Color.Red) 4396 .width("100%") 4397 .height("20%") 4398 .margin({bottom: 20}) 4399 4400 Column() { 4401 RichEditor(this.options).clip(true).padding(10) 4402 .onReady(() => { 4403 this.controller.addTextSpan("012345", 4404 { 4405 style: 4406 { 4407 fontColor: Color.Orange, 4408 fontSize: 30, 4409 lineHeight: this.LH, 4410 letterSpacing: this.LS 4411 } 4412 }) 4413 this.controller.addTextSpan("6789", 4414 { 4415 style: 4416 { 4417 fontColor: Color.Black, 4418 fontSize: 30, 4419 lineHeight: this.LH, 4420 letterSpacing: this.LS 4421 } 4422 }) 4423 }) 4424 .borderWidth(1) 4425 .borderColor(Color.Green) 4426 .width(400) 4427 .height(400) 4428 } 4429 .borderWidth(1) 4430 .borderColor(Color.Red) 4431 .width("100%") 4432 .height("60%") 4433 } 4434 } 4435} 4436``` 4437 4438 4439### 示例14(自定义粘贴事件) 4440为组件添加[onPaste](#onpaste11)事件,通过[PasteEvent](#pasteevent11)自定义用户粘贴事件。 4441 4442```ts 4443@Entry 4444@Component 4445struct RichEditorDemo { 4446 controller: RichEditorController = new RichEditorController(); 4447 options: RichEditorOptions = { controller: this.controller }; 4448 4449 build() { 4450 Column({ space: 2 }) { 4451 RichEditor(this.options) 4452 .onReady(() => { 4453 this.controller.addTextSpan('RichEditor preventDefault') 4454 }) 4455 .onPaste((event?: PasteEvent) => { 4456 if (event != undefined && event.preventDefault) { 4457 event.preventDefault(); 4458 } 4459 }) 4460 .borderWidth(1) 4461 .borderColor(Color.Green) 4462 .width('100%') 4463 .height('40%') 4464 } 4465 } 4466} 4467``` 4468 4469 4470### 示例15(配置文字特性效果) 4471通过[addTextSpan](#addtextspan)接口设置文字特性效果([fontFeature](#richeditortextstyle))。当添加“ss01”特性的FontFeature属性时,数字“0”由原来的椭圆形改变为带有倒圆角形。 4472 4473```ts 4474@Entry 4475@Component 4476struct RichEditorExample { 4477 controller: RichEditorController = new RichEditorController(); 4478 options: RichEditorOptions = { controller: this.controller }; 4479 @State enableDataDetector: boolean = true; 4480 @State types: TextDataDetectorType[] = []; 4481 build() { 4482 Row() { 4483 Column() { 4484 RichEditor(this.options) 4485 .onReady(() => { 4486 this.controller.addTextSpan('This is ss01 off :' + '0000' + '\n', 4487 { 4488 style: 4489 { 4490 fontSize: 30 4491 } 4492 }) 4493 this.controller.addTextSpan('This is ss01 on :' + '0000' + '\n', 4494 { 4495 style: 4496 { 4497 fontSize: 30, 4498 fontFeature: "\"ss01\" 1" 4499 } 4500 }) 4501 }) 4502 .copyOptions(CopyOptions.InApp) 4503 .enableDataDetector(this.enableDataDetector) 4504 .dataDetectorConfig({types : this.types, onDetectResultUpdate: (result: string)=>{}}) 4505 .borderWidth(1) 4506 .padding(10) 4507 .width('100%') 4508 } 4509 .width('100%') 4510 .margin({top:150}) 4511 } 4512 } 4513} 4514``` 4515 4516 4517### 示例16(自定义键盘避让) 4518通过[customKeyboard](#customkeyboard)属性绑定自定义键盘,通过参数[KeyboardOptions](#keyboardoptions12)设置自定义键盘是否支持避让功能。 4519 4520```ts 4521@Entry 4522@Component 4523struct RichEditorExample { 4524 controller: RichEditorController = new RichEditorController(); 4525 @State height1: string | number = '80%'; 4526 @State height2: number = 100; 4527 @State supportAvoidance: boolean = true; 4528 4529 // 自定义键盘组件 4530 @Builder 4531 CustomKeyboardBuilder() { 4532 Column() { 4533 Row() { 4534 Button('增加特表情包').onClick(() => { 4535 this.controller.addTextSpan("\uD83D\uDE0A", 4536 { 4537 style: 4538 { 4539 fontColor: Color.Orange 4540 } 4541 }) 4542 }) 4543 } 4544 4545 Grid() { 4546 ForEach(['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'], (item: string) => { 4547 GridItem() { 4548 Button(item).width(110).onClick(() => { 4549 this.controller.addTextSpan(item, { 4550 offset: this.controller.getCaretOffset(), 4551 style: 4552 { 4553 fontColor: Color.Orange, 4554 fontSize: 30 4555 } 4556 }) 4557 this.controller.setCaretOffset(this.controller.getCaretOffset() + item.toString().length) 4558 }) 4559 } 4560 }) 4561 }.maxCount(3).columnsGap(10).rowsGap(10).padding(5) 4562 }.backgroundColor(Color.Gray) 4563 } 4564 4565 build() { 4566 Column() { 4567 Row() { 4568 Button("20%") 4569 .fontSize(24) 4570 .onClick(() => { 4571 this.height1 = "20%"; 4572 }) 4573 Button("80%") 4574 .fontSize(24) 4575 .margin({ left: 20 }) 4576 .onClick(() => { 4577 this.height1 = "80%"; 4578 }) 4579 } 4580 .justifyContent(FlexAlign.Center) 4581 .alignItems(VerticalAlign.Bottom) 4582 .height(this.height1) 4583 .width("100%") 4584 .padding({ bottom: 50 }) 4585 4586 RichEditor({ controller: this.controller })// 绑定自定义键盘 4587 .customKeyboard(this.CustomKeyboardBuilder(), { supportAvoidance: this.supportAvoidance }) 4588 .margin(10) 4589 .border({ width: 1 }) 4590 .borderWidth(1) 4591 .borderColor(Color.Red) 4592 .width("100%") 4593 } 4594 } 4595} 4596``` 4597 4598 4599### 示例17(查看编辑状态) 4600通过[isEditing](#isediting12)接口获取当前富文本的编辑状态。为组件添加[onEditingChange](#oneditingchange12)事件,可通过打印日志,获取当前组件是否在编辑态。 4601 4602```ts 4603@Entry 4604@Component 4605struct RichEditor_onEditingChange { 4606 controller: RichEditorController = new RichEditorController(); 4607 @State controllerIsEditing: boolean = false; 4608 @Builder 4609 4610 build() { 4611 Column() { 4612 Row() { 4613 Button("点击查看编辑状态isEditing():").onClick(() => { 4614 this.controllerIsEditing = this.controller.isEditing(); 4615 }) 4616 .padding(5) 4617 Text('' + this.controllerIsEditing) 4618 .width('100%') 4619 .padding(5) 4620 .fontColor(Color.Orange) 4621 .fontSize(20) 4622 } 4623 RichEditor({ controller: this.controller }) 4624 .onEditingChange((isEditing: boolean) => { 4625 console.info("Current Editing Status:" + isEditing); 4626 }) 4627 .height(400) 4628 .borderWidth(1) 4629 .borderColor(Color.Red) 4630 .width("100%") 4631 } 4632 } 4633} 4634``` 4635 4636 4637 4638### 示例18(配置文本变化回调) 4639为组件添加[onWillChange](#onwillchange12)事件,能够在组件执行增删操作前,触发回调。 4640 4641```ts 4642@Entry 4643@Component 4644struct RichEditorExample { 4645 controller: RichEditorController = new RichEditorController(); 4646 build() { 4647 Column() { 4648 RichEditor({ controller: this.controller }) 4649 .height(200) 4650 .borderWidth(1) 4651 .borderColor(Color.Red) 4652 .width("100%") 4653 .onReady(() => { 4654 this.controller.addTextSpan('测试文字TestWord', { style: { fontColor: Color.Orange, fontSize: 30 } }) 4655 this.controller.updateSpanStyle({ 4656 start: -1, 4657 end: -1, 4658 textStyle: 4659 { 4660 fontWeight: FontWeight.Bolder 4661 } 4662 }) 4663 }) 4664 .onWillChange((value: RichEditorChangeValue) => { 4665 console.info('测试log: onWillChange'); 4666 console.info('rangeBefore: ' + JSON.stringify(value.rangeBefore)); 4667 console.info('print replacedSpans'); 4668 value.replacedSpans.forEach((item: RichEditorTextSpanResult) => { 4669 console.info('spanPosition:' + JSON.stringify(item.spanPosition)); 4670 console.info('value:' + item.value); 4671 console.info('textStyle:' + JSON.stringify(item.textStyle)); 4672 console.info('offsetInSpan:' + item.offsetInSpan); 4673 console.info('valueResource:' + item.valueResource); 4674 console.info('paragraphStyle:' + JSON.stringify(item.paragraphStyle)); 4675 }) 4676 console.info('print replacedImageSpans'); 4677 value.replacedImageSpans.forEach((item: RichEditorImageSpanResult) => { 4678 console.info('spanPosition:' + JSON.stringify(item.spanPosition)); 4679 console.info('valuePixelMap:' + JSON.stringify(item.valuePixelMap)); 4680 console.info('valueResourceStr:' + item.valueResourceStr); 4681 console.info('imageStyle:' + JSON.stringify(item.imageStyle)); 4682 console.info('offsetInSpan:' + item.offsetInSpan); 4683 }) 4684 console.info('print replacedSymbolSpans'); 4685 value.replacedSymbolSpans.forEach((item: RichEditorTextSpanResult) => { 4686 console.info('spanPosition:' + JSON.stringify(item.spanPosition)); 4687 console.info('value:' + item.value); 4688 console.info('offsetInSpan:' + item.offsetInSpan); 4689 console.info('symbolSpanStyle:' + JSON.stringify(item.symbolSpanStyle)); 4690 console.info('valueResource:' + item.valueResource); 4691 console.info('paragraphStyle:' + JSON.stringify(item.paragraphStyle)); 4692 }) 4693 return true; 4694 }) 4695 .onDidChange((rangeBefore: TextRange, rangeAfter: TextRange) => { 4696 console.info('测试log: onDidChange'); 4697 console.info('rangeBefore:' + JSON.stringify(rangeBefore)); 4698 console.info('rangeAfter:' + JSON.stringify(rangeAfter)); 4699 }) 4700 .onCut((event:CutEvent) => { 4701 event.preventDefault!() 4702 console.info('测试log:onCut'); 4703 }) 4704 .onCopy((event:CopyEvent) => { 4705 event.preventDefault!() 4706 console.info('测试log:onCopy'); 4707 }) 4708 .onPaste(()=>{ 4709 console.info('测试log:onPaste'); 4710 }) 4711 Text('测试文字Hello') 4712 .lineHeight(50) 4713 .fontSize(24) 4714 .draggable(true) 4715 .onDragStart(()=>{}) 4716 TextInput({text:'测试文字NiHao'}) 4717 .draggable(true) 4718 .margin(20) 4719 } 4720 } 4721} 4722``` 4723### 示例19(配置输入法enter键功能) 4724通过[enterKeyType](#enterkeytype12)属性设置软键盘输入法回车键类型。 4725 4726```ts 4727@Entry 4728@Component 4729struct SoftKeyboardEnterTypeExample { 4730 controller: RichEditorController = new RichEditorController(); 4731 4732 build() { 4733 Column() { 4734 Button("停止编辑").onClick(()=>{ 4735 this.controller.stopEditing() 4736 }) 4737 RichEditor({ controller: this.controller }) 4738 .margin(10) 4739 .border({ width: 1 }) 4740 .height(200) 4741 .borderWidth(1) 4742 .borderColor(Color.Red) 4743 .width("100%") 4744 .enterKeyType(EnterKeyType.Search) 4745 .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { 4746 console.info("trigger richeditor onsubmit" + enterKey); 4747 this.controller.addTextSpan(" type["+ enterKey +"] triggerred") 4748 event.keepEditableState() 4749 }) 4750 }.height("100%").justifyContent(FlexAlign.Center) 4751 } 4752} 4753``` 4754 4755 4756 4757### 示例20(设置段落折行规则) 4758通过[updateParagraphStyle](#updateparagraphstyle11)接口设置折行类型([lineBreakStrategy](#richeditorparagraphstyle11)),通过[getParagraphs](#getparagraphs11)接口获取当前段落的折行类型。 4759 4760```ts 4761@Entry 4762@Component 4763struct LineBreakStrategyExample { 4764 controller: RichEditorController = new RichEditorController(); 4765 private spanParagraphs: RichEditorParagraphResult[] = []; 4766 @State lineBreakOptionStr: string[] = ['GREEDY', 'HIGH_QUALITY', 'BALANCED']; 4767 @State attributeValue: string = ""; 4768 @State testStr: string = "0123456789,0123456789,0123456789,0123456789,0123456789."; 4769 build() { 4770 Column() { 4771 RichEditor({ controller: this.controller }) 4772 .onReady(() => { 4773 this.controller.addTextSpan(this.testStr, { 4774 style: { 4775 fontColor: Color.Black, 4776 fontSize: "32" 4777 }, 4778 paragraphStyle: { 4779 textAlign: TextAlign.Start, 4780 lineBreakStrategy: LineBreakStrategy.GREEDY 4781 } 4782 }) 4783 }) 4784 .width(400) 4785 .height(300) 4786 .margin({bottom:20}) 4787 .draggable(false) 4788 Column(){ 4789 Text('linebreak属性值为:' + this.attributeValue).fontSize(20).fontColor(Color.Black) 4790 }.margin({bottom: 10}) 4791 Column({ space: 10 }) { 4792 Button("设置折行类型GREEDY").onClick(() => { 4793 this.controller.updateParagraphStyle({ start: -1, end: -1, 4794 style: { 4795 lineBreakStrategy: LineBreakStrategy.GREEDY 4796 } 4797 }) 4798 }) 4799 Button("设置折行类型HIGH_QUALITY").onClick(() => { 4800 this.controller.updateParagraphStyle({ start: -1, end: -1, 4801 style: { 4802 lineBreakStrategy: LineBreakStrategy.HIGH_QUALITY 4803 } 4804 }) 4805 }) 4806 Button("设置折行类型BALANCED").onClick(() => { 4807 this.controller.updateParagraphStyle({ start: -1, end: -1, 4808 style: { 4809 lineBreakStrategy: LineBreakStrategy.BALANCED 4810 } 4811 }) 4812 }) 4813 Divider() 4814 Row(){ 4815 Button("获取linebreak属性值").onClick(() => { 4816 this.spanParagraphs = this.controller.getParagraphs({ start: -1, end: -1 }); 4817 console.info("RichEditor getParagraphs:" + JSON.stringify(this.spanParagraphs)); 4818 this.spanParagraphs.forEach(item => { 4819 if(typeof(item as RichEditorParagraphResult)['style'] != 'undefined'){ 4820 this.attributeValue = ""; 4821 console.info('lineBreakStrategy:'+ JSON.stringify((item as RichEditorParagraphResult)['style'])); 4822 this.attributeValue += this.lineBreakOptionStr[Number((item as RichEditorParagraphResult)['style'].lineBreakStrategy)]; 4823 } 4824 }) 4825 }) 4826 } 4827 } 4828 } 4829 } 4830} 4831``` 4832 4833 4834 4835### 示例21(属性字符串基本功能) 4836从API version 20开始,该示例中[属性字符串](./ts-universal-styled-string.md)通过[RichEditorStyledStringController](#richeditorstyledstringcontroller12)中的[setStyledString](#setstyledstring12)方法与RichEditor组件绑定。通过[getStyledString](#getstyledstring12)接口获取富文本组件显示的属性字符串。 4837 4838```ts 4839// xxx.ets 4840import { LengthMetrics } from '@kit.ArkUI' 4841 4842@Entry 4843@Component 4844struct Index { 4845 stringLength: number = 0; 4846 @State selection: string = ""; 4847 @State content: string = ""; 4848 @State range: string = ""; 4849 @State replaceString: string = ""; 4850 @State rangeBefore: string = ""; 4851 @State rangeAfter: string = ""; 4852 richEditorStyledString: MutableStyledString = new MutableStyledString(""); 4853 textStyle: TextStyle = new TextStyle({ 4854 fontWeight: FontWeight.Lighter, 4855 fontFamily: 'HarmonyOS Sans', 4856 fontColor: Color.Green, 4857 fontSize: LengthMetrics.vp(30), 4858 fontStyle: FontStyle.Normal 4859 }) 4860 fontStyle1: TextStyle = new TextStyle({ fontColor: Color.Blue }); 4861 fontStyle2: TextStyle = new TextStyle({ 4862 fontWeight: FontWeight.Bolder, 4863 fontFamily: 'Arial', 4864 fontColor: Color.Orange, 4865 fontSize: LengthMetrics.vp(30), 4866 fontStyle: FontStyle.Italic 4867 }) 4868 4869 controller1: RichEditorController = new RichEditorController(); 4870 options1: RichEditorOptions = { controller: this.controller1 }; 4871 // 创建属性字符串对象 4872 mutableStyledString: MutableStyledString = new MutableStyledString("初始属性字符串", 4873 [{ start: 0, length: 5, styledKey: StyledStringKey.FONT, styledValue: this.fontStyle1 }]); 4874 styledString: StyledString = new StyledString("插入属性字符串", 4875 [{ start: 2, length: 4, styledKey: StyledStringKey.FONT, styledValue: this.fontStyle2 }]); 4876 controller: RichEditorStyledStringController = new RichEditorStyledStringController(); 4877 options: RichEditorStyledStringOptions = {controller: this.controller}; 4878 // 文本内容变化回调 4879 contentChangedListener: StyledStringChangedListener = { 4880 onWillChange: (value: StyledStringChangeValue) => { 4881 this.range = '[ ' + value.range.start + ' , ' + value.range.end + ' ]'; 4882 this.replaceString = value.replacementString.getString(); 4883 return true; 4884 }, 4885 onDidChange: (rangeBefore, rangeAfter) => { 4886 this.rangeBefore = '[ ' + rangeBefore.start + ' , ' + rangeBefore.end + ' ]'; 4887 this.rangeAfter = '[ ' + rangeAfter.start + ' , ' + rangeAfter.end + ' ]'; 4888 } 4889 } 4890 4891 build() { 4892 Column({space:6}) { 4893 Column() { 4894 Text("选中区信息") 4895 .fontSize(20) 4896 .width("100%") 4897 Text("selection range: " + this.selection).width("100%") 4898 Text("selection content: " + this.content).width("100%") 4899 } 4900 .width("100%") 4901 .height("10%") 4902 4903 Column() { 4904 Text("onWillChange回调信息") 4905 .fontSize(20) 4906 .width("100%") 4907 Text("range: " + this.range).width("100%") 4908 Text("replacementString: " + this.replaceString).width("100%") 4909 Text("onWillChange回调信息") 4910 .fontSize(20) 4911 .width("100%") 4912 Text("rangeBefore: " + this.rangeBefore).width("100%") 4913 Text("rangeAfter: " + this.rangeAfter).width("100%") 4914 } 4915 .borderWidth(1) 4916 .borderColor(Color.Black) 4917 .width("100%") 4918 .height("20%") 4919 4920 RichEditor(this.options) 4921 .onReady(() => { 4922 // 注册文本变化回调 4923 this.controller.onContentChanged(this.contentChangedListener); 4924 // 设定组件展示的属性字符串 4925 this.controller.setStyledString(this.mutableStyledString); 4926 }) 4927 .height("20%") 4928 .width("100%") 4929 4930 RichEditor(this.options1) 4931 .onReady(() => { 4932 this.controller1.addTextSpan("把这些文字转换成属性字符串"); 4933 }) 4934 .height("10%") 4935 .width("100%") 4936 .borderWidth(1) 4937 .borderColor(Color.Black) 4938 4939 Row({space:2}) { 4940 Button("插入图片") 4941 .stateEffect(true) 4942 .onClick(() => { 4943 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 4944 let imageStyledString = new MutableStyledString(new ImageAttachment({ 4945 resourceValue: $r('app.media.startIcon'), 4946 size: { width: 50, height: 50 }, 4947 layoutStyle: { borderRadius: LengthMetrics.vp(10) }, 4948 verticalAlign: ImageSpanAlignment.BASELINE, 4949 objectFit: ImageFit.Contain, 4950 syncLoad: true 4951 })); 4952 // 获取组件展示的属性字符串 4953 this.richEditorStyledString = this.controller.getStyledString(); 4954 this.richEditorStyledString.appendStyledString(imageStyledString) 4955 // 使插入图片后的属性字符串展示在组件上 4956 this.controller.setStyledString(this.richEditorStyledString) 4957 this.controller.setCaretOffset(this.richEditorStyledString.length) 4958 }) 4959 Button("插入文本").onClick(() => { 4960 // 获取组件展示的属性字符串 4961 this.richEditorStyledString = this.controller.getStyledString(); 4962 this.richEditorStyledString.appendStyledString(this.styledString) 4963 // 使插入文本后的属性字符串展示在组件上 4964 this.controller.setStyledString(this.richEditorStyledString) 4965 this.controller.setCaretOffset(this.richEditorStyledString.length) 4966 }) 4967 Button("删除选中内容").onClick(() => { 4968 // 获取选中范围 4969 let richEditorSelection = this.controller.getSelection(); 4970 let start = richEditorSelection.start ? richEditorSelection.start : 0; 4971 let end = richEditorSelection.end ? richEditorSelection.end : 0; 4972 if (start < 0 || end <= start) { 4973 return; 4974 } 4975 // 获取组件展示的属性字符串 4976 this.richEditorStyledString = this.controller.getStyledString(); 4977 this.richEditorStyledString.removeString(start, end - start) 4978 // 使删除内容后的属性字符串展示在组件上 4979 this.controller.setStyledString(this.richEditorStyledString) 4980 }) 4981 } 4982 Row({space:2}) { 4983 Button("获取选中内容").onClick(() => { 4984 // 获取选中范围 4985 let richEditorSelection = this.controller.getSelection(); 4986 let start = richEditorSelection.start ? richEditorSelection.start : 0; 4987 let end = richEditorSelection.end ? richEditorSelection.end : 0; 4988 // 获取组件展示的属性字符串 4989 this.richEditorStyledString = this.controller.getStyledString(); 4990 this.selection = '[ ' + start + ' , ' + end + ' ]'; 4991 if (start == end) { 4992 this.content = ""; 4993 } else { 4994 this.content = this.richEditorStyledString.subStyledString(start, end - start).getString(); 4995 } 4996 }) 4997 Button("更新选中样式").onClick(() => { 4998 // 获取选中范围 4999 let richEditorSelection = this.controller.getSelection(); 5000 let start = richEditorSelection.start ? richEditorSelection.start : 0; 5001 let end = richEditorSelection.end ? richEditorSelection.end : 0; 5002 if (start < 0 || end <= start) { 5003 return; 5004 } 5005 // 获取组件展示的属性字符串 5006 this.richEditorStyledString = this.controller.getStyledString(); 5007 this.richEditorStyledString.setStyle({ 5008 start: start, 5009 length: end - start, 5010 styledKey: StyledStringKey.FONT, 5011 styledValue: this.textStyle 5012 }) 5013 // 使变更样式后的属性字符串展示在组件上 5014 this.controller.setStyledString(this.richEditorStyledString) 5015 }) 5016 } 5017 Row({space:2}){ 5018 //将属性字符串转换成span信息 5019 Button("调用fromStyledString").onClick(() => { 5020 this.controller1.addTextSpan("调用fromStyledString:" +JSON.stringify(this.controller1.fromStyledString(this.mutableStyledString))) 5021 }) 5022 //将给定范围的组件内容转换成属性字符串 5023 Button("调用toStyledString").onClick(() => { 5024 this.controller.setStyledString(this.controller1.toStyledString({start:0,end:13})) 5025 }) 5026 } 5027 } 5028 } 5029} 5030``` 5031 5032 5033 5034### 示例22(获取布局信息) 5035通过[getLayoutManager](#getlayoutmanager12)接口获取布局管理器对象,通过[getLineCount](ts-text-common.md#getlinecount)接口获取组件内容或[placeholder](#placeholder12)的总行数,通过[getGlyphPositionAtCoordinate](ts-text-common.md#getglyphpositionatcoordinate)接口获取较为接近给定坐标的字形的位置信息,通过[getLineMetrics](ts-text-common.md#getlinemetrics)接口获取指定行的行信息、文本样式信息、以及字体属性信息。 5036 5037```ts 5038@Entry 5039@Component 5040export struct Index { 5041 @State lineCount: string = "" 5042 @State glyphPositionAtCoordinate: string = "" 5043 @State lineMetrics: string = "" 5044 controller: RichEditorController = new RichEditorController(); 5045 @State textStr: string = 5046 'Hello World! 你好,世界!' 5047 5048 build() { 5049 Scroll() { 5050 Column() { 5051 Text('RichEditor组件getLayoutManager接口获取相对于组件的布局信息') 5052 .fontSize(9) 5053 .fontColor(0xCCCCCC) 5054 .width('90%') 5055 .padding(10) 5056 RichEditor({ controller: this.controller }) 5057 .borderColor(Color.Red) 5058 .borderWidth(1) 5059 .onReady(() => { 5060 this.controller.addTextSpan(this.textStr) 5061 }) 5062 .onAreaChange(() => { 5063 let layoutManager = this.controller.getLayoutManager(); 5064 this.lineCount = "LineCount: " + layoutManager.getLineCount(); 5065 }) 5066 5067 Text('LineCount').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10) 5068 Text(this.lineCount) 5069 5070 Text('GlyphPositionAtCoordinate').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10) 5071 Button("相对组件坐标[150,50]字形信息") 5072 .onClick(() => { 5073 let layoutManager: LayoutManager = this.controller.getLayoutManager(); 5074 let position = layoutManager.getGlyphPositionAtCoordinate(150, 50); 5075 this.glyphPositionAtCoordinate = 5076 "相对组件坐标[150,50] glyphPositionAtCoordinate position: " + position.position + " affinity: " + 5077 position.affinity; 5078 }) 5079 .margin({ bottom: 20, top: 10 }) 5080 Text(this.glyphPositionAtCoordinate) 5081 5082 Text('LineMetrics').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10) 5083 Button("首行行信息、文本样式信息、以及字体属性信息") 5084 .onClick(() => { 5085 let layoutManager: LayoutManager = this.controller.getLayoutManager(); 5086 let lineMetrics = layoutManager.getLineMetrics(0); 5087 this.lineMetrics = "lineMetrics is " + JSON.stringify(lineMetrics) + '\n\n'; 5088 let runMetrics = lineMetrics.runMetrics; 5089 runMetrics.forEach((value, key) => { 5090 this.lineMetrics += "runMetrics key is " + key + " " + JSON.stringify(value) + "\n\n"; 5091 }); 5092 }) 5093 .margin({ bottom: 20, top: 10 }) 5094 Text(this.lineMetrics) 5095 } 5096 .margin({ top: 100, left: 8, right: 8 }) 5097 } 5098 } 5099} 5100``` 5101 5102 5103 5104### 示例23(设置系统默认菜单扩展项) 5105从API version 20开始,该示例通过[editMenuOptions](#editmenuoptions12)属性设置系统默认菜单的扩展项,允许配置扩展项的文本内容、图标和回调方法。 5106 5107```ts 5108// xxx.ets 5109@Entry 5110@Component 5111struct RichEditorExample { 5112 controller: RichEditorController = new RichEditorController(); 5113 options: RichEditorOptions = { controller: this.controller }; 5114 @State endIndex: number | undefined = 0; 5115 onCreateMenu = (menuItems: Array<TextMenuItem>) => { 5116 const idsToFilter: TextMenuItemId[] = [ 5117 TextMenuItemId.TRANSLATE, 5118 TextMenuItemId.SHARE, 5119 TextMenuItemId.SEARCH, 5120 TextMenuItemId.AI_WRITER 5121 ] 5122 const items = menuItems.filter(item => !idsToFilter.some(id => id.equals(item.id))) 5123 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5124 let item1: TextMenuItem = { 5125 content: 'create1', 5126 icon: $r('app.media.startIcon'), 5127 id: TextMenuItemId.of('create1'), 5128 }; 5129 let item2: TextMenuItem = { 5130 content: 'create2', 5131 id: TextMenuItemId.of('create2'), 5132 icon: $r('app.media.startIcon'), 5133 }; 5134 items.push(item1); 5135 items.unshift(item2); 5136 return items; 5137 } 5138 onMenuItemClick = (menuItem: TextMenuItem, textRange: TextRange) => { 5139 if (menuItem.id.equals(TextMenuItemId.of("create2"))) { 5140 console.info("拦截 id: create2 start:" + textRange.start + "; end:" + textRange.end); 5141 return true; 5142 } 5143 if (menuItem.id.equals(TextMenuItemId.of("prepare1"))) { 5144 console.info("拦截 id: prepare1 start:" + textRange.start + "; end:" + textRange.end); 5145 return true; 5146 } 5147 if (menuItem.id.equals(TextMenuItemId.COPY)) { 5148 console.info("拦截 COPY start:" + textRange.start + "; end:" + textRange.end); 5149 return true; 5150 } 5151 if (menuItem.id.equals(TextMenuItemId.SELECT_ALL)) { 5152 console.info("不拦截 SELECT_ALL start:" + textRange.start + "; end:" + textRange.end); 5153 return false; 5154 } 5155 return false; 5156 } 5157 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5158 onPrepareMenu = (menuItems: Array<TextMenuItem>) => { 5159 let item1: TextMenuItem = { 5160 content: 'prepare1_' + this.endIndex, 5161 icon: $r('app.media.startIcon'), 5162 id: TextMenuItemId.of('prepare1'), 5163 }; 5164 menuItems.unshift(item1); 5165 return menuItems; 5166 } 5167 @State editMenuOptions: EditMenuOptions = { 5168 onCreateMenu: this.onCreateMenu, 5169 onMenuItemClick: this.onMenuItemClick, 5170 onPrepareMenu: this.onPrepareMenu 5171 }; 5172 5173 build() { 5174 Column() { 5175 RichEditor(this.options) 5176 .onReady(() => { 5177 this.controller.addTextSpan("RichEditor editMenuOptions") 5178 }) 5179 .editMenuOptions(this.editMenuOptions) 5180 .onSelectionChange((range: RichEditorRange) => { 5181 console.info("onSelectionChange, (" + range.start + "," + range.end + ")"); 5182 this.endIndex = range.end 5183 }) 5184 .height(50) 5185 .margin({ top: 100 }) 5186 .borderWidth(1) 5187 .borderColor(Color.Red) 5188 } 5189 .width("90%") 5190 .margin("5%") 5191 } 5192} 5193``` 5194 5195 5196 5197### 示例24(组件部分常用属性) 5198从API version 18开始,该示例通过[barState](#barstate13)属性设置组件滚动条的显示模式。通过[enableKeyboardOnFocus](#enablekeyboardonfocus12)属性设置组件通过点击以外的方式获焦时,是否主动拉起软键盘。通过[enableHapticFeedback](#enablehapticfeedback13)属性设置组件是否支持触感反馈。通过[getPreviewText](#getpreviewtext12)接口获取组件预上屏信息。通过[stopBackPress](#stopbackpress18)属性设置是否阻止返回键向其它组件或应用侧传递。 5199 5200```ts 5201// xxx.ets 5202import { JSON } from '@kit.ArkTS'; 5203 5204@Entry 5205@Component 5206struct RichEditor_example { 5207 controller: RichEditorController = new RichEditorController(); 5208 options: RichEditorOptions = { controller: this.controller }; 5209 5210 controller1: RichEditorController = new RichEditorController(); 5211 options1: RichEditorOptions = { controller: this.controller1 }; 5212 5213 @State e: boolean = true; 5214 @State bs_num: number = 0; 5215 @State bs: (BarState | undefined)[] = [BarState.Auto, BarState.On, BarState.Off, undefined]; 5216 @State bs_string: string[] = ["Auto", "On", "Off", "undefined"]; 5217 5218 build() { 5219 Column({space: 3}) { 5220 RichEditor(this.options) 5221 .onReady(() => { 5222 this.controller.addTextSpan('文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本', { 5223 style: { 5224 fontColor: Color.Black, 5225 fontSize: 15 5226 } 5227 }) 5228 }) 5229 .onDidIMEInput((value: TextRange) => { 5230 this.controller1.addTextSpan("\n" + "触发了onDidIMEInput回调,输入法本次输入内容范围为:(" + value.start + "," + value.end + ")", { 5231 style: { 5232 fontColor: Color.Gray, 5233 fontSize: 10 5234 } 5235 }) 5236 }) 5237 .onSelectionChange((value: RichEditorRange) => { 5238 this.controller1.addTextSpan("\n" + "触发了onSelectionChange回调,起始范围信息为:(" + value.start + "," + value.end + ")", { 5239 style: { 5240 fontColor: Color.Gray, 5241 fontSize: 10 5242 } 5243 }) 5244 }) 5245 .width(300) 5246 .height(100) 5247 .margin(20) 5248 .barState(this.bs[this.bs_num]) 5249 .enableKeyboardOnFocus(this.e) 5250 .enableHapticFeedback(true) 5251 .stopBackPress(false); 5252 5253 RichEditor(this.options1).width(300) 5254 5255 Button('设置barState为:' + this.bs_string[this.bs_num]) 5256 .height(30) 5257 .fontSize(13) 5258 .onClick(() => { 5259 this.bs_num++; 5260 if (this.bs_num > (this.bs.length - 1)) { 5261 this.bs_num = 0; 5262 } 5263 }) 5264 5265 Button('设置enableKeyboardOnFocus为:' + this.e) 5266 .height(30) 5267 .fontSize(13) 5268 .onClick(() => { 5269 this.e = !this.e; 5270 }) 5271 5272 Button('获取预上屏信息') 5273 .height(30) 5274 .fontSize(13) 5275 .onClick(() => { 5276 this.controller1.addTextSpan("\n获取预上屏信息:" + JSON.stringify(this.controller.getPreviewText())) 5277 }) 5278 } 5279 } 5280} 5281 5282``` 5283 5284 5285 5286### 示例25(获取光标相对组件位置的矩形) 5287从API version 18开始,该示例通过RichEditorBaseController的[getCaretRect](#getcaretrect18)方法来获取当前光标相对于组件位置的Rect。 5288 5289```ts 5290// xxx.ets 5291@Entry 5292@Component 5293struct Index { 5294 controller: RichEditorController = new RichEditorController(); 5295 options: RichEditorOptions = { controller: this.controller }; 5296 @State caretRect: string = "not found"; 5297 5298 build() { 5299 Column() { 5300 Button('get caret rect') 5301 .onClick(() => { 5302 let rectCaret = this.controller.getCaretRect(); 5303 if(rectCaret == undefined) { 5304 this.caretRect = 'undefined'; 5305 } else { 5306 this.caretRect = 'X: ' + rectCaret.x + '\nY: ' + rectCaret.y 5307 + '\nWidth: ' + rectCaret.width + '\nHeight: ' + rectCaret.height; 5308 } 5309 }) 5310 .fontSize(24) 5311 .width("60%") 5312 .height("10%") 5313 5314 Text(this.caretRect) 5315 .margin(12) 5316 .fontSize(24) 5317 5318 RichEditor(this.options) 5319 .onReady(() => { 5320 this.controller.addTextSpan('12345678901234567890', { 5321 style: 5322 { 5323 fontColor: Color.Orange, 5324 fontSize: 50 5325 } 5326 }) 5327 }) 5328 .borderWidth(1) 5329 .borderColor(Color.Red) 5330 .width("100%") 5331 .height("60%") 5332 } 5333 } 5334} 5335 5336``` 5337 5338 5339 5340### 示例26(设置最大行数和最大字符数) 5341从API version 18开始,该示例通过[maxLength](#maxlength18)设置可输入的最大字符数,通过[maxLines](#maxlines18)设置可输入的最大行数。 5342 5343```ts 5344@Entry 5345@Component 5346struct RichEditorExample { 5347 @State text: string = "As the sun begins to set, casting a warm golden hue across the sky," + 5348 "the world seems to slow down and breathe a sigh of relief. The sky is painted with hues of orange, " + 5349 " pink, and lavender, creating a breathtaking tapestry that stretches as far as the eye can see." + 5350 "The air is filled with the sweet scent of blooming flowers, mingling with the earthy aroma of freshly turned soil." + 5351 "it casts a warm," + 5352 "golden hue that spreads like liquid amber across the vast expanse of the sky." + 5353 "The once-blue heavens gradually transform, " + 5354 "now painted in a breathtaking palette of soft oranges, pinks, " + 5355 "and purples, each color blending seamlessly into the next. Wisps of clouds, tinged with fiery edges, " + 5356 "float lazily amidst this celestial canvas," + 5357 "creating a scene so serene and beautiful that it almost seems to pause time itself." + 5358 "As the sun begins to set, casting a warm golden hue across the sky," + 5359 "the world seems to slow down and breathe a sigh of relief. The sky is painted with hues of orange, " + 5360 " pink, and lavender, creating a breathtaking tapestry that stretches as far as the eye can see." + 5361 "The air is filled with the sweet scent of blooming flowers, mingling with the earthy aroma of freshly turned soil." + 5362 "it casts a warm," + 5363 "golden hue that spreads like liquid amber across the vast expanse of the sky." + 5364 "The once-blue heavens gradually transform, "; 5365 @State maxLineList: (number | undefined)[] = [2, 6, undefined]; 5366 @State maxLineIndex: number = 0; 5367 @State maxLineStringList: (string)[] = ["2", "6", "undefined"]; 5368 richEditorStyledString: MutableStyledString = new MutableStyledString(""); 5369 controller1: RichEditorController = new RichEditorController(); 5370 controller2: TextInputController = new TextInputController(); 5371 controller3: RichEditorController = new RichEditorController(); 5372 controller4: RichEditorStyledStringController = new RichEditorStyledStringController(); 5373 controller: RichEditorController = new RichEditorController(); 5374 option: RichEditorOptions = { controller: this.controller }; 5375 5376 build() { 5377 Column() { 5378 Text("当前的maxLength为7 ") 5379 .margin(10) 5380 .fontSize(25) 5381 Row() { 5382 Button("插入占1字符数的图片") 5383 .onClick(() => { 5384 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5385 this.controller1.addImageSpan($r('app.media.startIcon'), 5386 { 5387 imageStyle: 5388 { 5389 size: ["57px", "57px"] 5390 } 5391 }) 5392 }) 5393 Button("插入占2字符数图片") 5394 .onClick(() => { 5395 this.controller1.addSymbolSpan($r("sys.symbol.ohos_trash"), 5396 { 5397 style: 5398 { 5399 fontSize: 30 5400 } 5401 }) 5402 }) 5403 .margin({ left: 20 }) 5404 } 5405 5406 RichEditor({ controller: this.controller1 }) 5407 .width('95%') 5408 .margin(10) 5409 .height(60) 5410 .maxLength(7) 5411 .backgroundColor('rgb(240,250,255)') 5412 Text("当前的maxLine为 " + this.maxLineStringList[this.maxLineIndex]).margin(10) 5413 .fontSize(25) 5414 Button("更改maxLines").onClick(() => { 5415 this.maxLineIndex++; 5416 if (this.maxLineIndex > this.maxLineList.length - 1) { 5417 this.maxLineIndex = 0; 5418 } 5419 }) 5420 RichEditor({ controller: this.controller3 }) 5421 .onReady(() => { 5422 this.controller3.addTextSpan(this.text, 5423 { 5424 style: 5425 { 5426 fontColor: 'rgb(0,74,175)' 5427 } 5428 }) 5429 }) 5430 .margin(10) 5431 .width('95%') 5432 .maxLines(this.maxLineList[this.maxLineIndex]) 5433 .backgroundColor('rgb(240,250,255)') 5434 } 5435 } 5436} 5437``` 5438 5439 5440### 示例27(文本设置Url样式) 5441从API version 19开始,该示例通过在addTextSpan和UpdateSpanStyle接口中加入[UrlStyle](#richeditorurlstyle19),来实现文本点击时跳转到指定链接的功能。 5442 5443```ts 5444// xxx.ets 5445 5446@Entry 5447@Component 5448struct RichEditorExample { 5449 controller: RichEditorController = new RichEditorController(); 5450 options: RichEditorOptions = { controller: this.controller }; 5451 styledStringController: RichEditorStyledStringController = new RichEditorStyledStringController(); 5452 styledStringOptions: RichEditorStyledStringOptions = { controller: this.styledStringController }; 5453 5454 build() { 5455 Column() { 5456 Row() { 5457 Button("Add Example Url").onClick(() => { 5458 this.controller.addTextSpan("示例网址", { 5459 urlStyle: { url: "https://www.example.com" } 5460 }) 5461 }) 5462 Button("Clear Url").onClick(() => { 5463 this.controller.updateSpanStyle({ 5464 start: 0, 5465 textStyle: {}, 5466 urlStyle: { url: "" } 5467 }) 5468 }) 5469 } 5470 5471 Row() { 5472 RichEditor(this.options) 5473 .height('35%') 5474 .border({ width: 1, color: Color.Blue }) 5475 } 5476 5477 Row() { 5478 RichEditor(this.styledStringOptions) 5479 .height('35%') 5480 .border({ width: 1, color: Color.Red }) 5481 } 5482 } 5483 } 5484} 5485``` 5486 5487### 示例28(开启带样式的撤销还原能力) 5488从API version 20开始,该示例对于不使用属性字符串的富文本组件,可以通过配置[undoStyle](#undostyle20)属性为UndoStyle.KEEP_STYLE,以支持撤销还原时保留原内容的样式。 5489 5490```ts 5491// xxx.ets 5492 5493@Entry 5494@Component 5495struct StyledUndo { 5496 controller: RichEditorController = new RichEditorController(); 5497 options: RichEditorOptions = { controller: this.controller }; 5498 private start: number = 0; 5499 private end: number = 0; 5500 @State undoStyle: UndoStyle = UndoStyle.KEEP_STYLE; 5501 build() { 5502 Column() { 5503 Column() { 5504 Row({space:2}) { 5505 Button("插入文本").onClick(() => { 5506 this.controller.addTextSpan("插入文本", 5507 { 5508 style: 5509 { 5510 fontColor: Color.Orange, 5511 fontSize: 32 5512 } 5513 }) 5514 }) 5515 Button("插入图片").onClick(() => { 5516 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5517 this.controller.addImageSpan($r('app.media.startIcon'), 5518 { 5519 imageStyle: 5520 { 5521 size: ["100px", "100px"] 5522 } 5523 }); 5524 }) 5525 Button("插入Symbol").onClick(() => { 5526 this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"), 5527 { 5528 style: 5529 { 5530 fontSize: 32 5531 } 5532 }); 5533 }) 5534 } 5535 .borderWidth(1) 5536 .borderColor(Color.Red) 5537 .justifyContent(FlexAlign.Center) 5538 .width("100%") 5539 .height("10%") 5540 Row({space:2}) { 5541 Button("更新选中范围样式").onClick(() => { 5542 if (this.start < this.end) { 5543 this.controller.updateSpanStyle({ 5544 start: this.start, 5545 end: this.end, 5546 textStyle: 5547 { 5548 fontColor: Color.Red, 5549 fontWeight: FontWeight.Bolder 5550 } 5551 }); 5552 } 5553 }) 5554 Button("删除选中范围内容").onClick(() => { 5555 if (this.start < this.end) { 5556 this.controller.deleteSpans({ 5557 start: this.start, 5558 end: this.end 5559 }) 5560 } 5561 }) 5562 } 5563 .borderWidth(1) 5564 .borderColor(Color.Red) 5565 .justifyContent(FlexAlign.Center) 5566 .width("100%") 5567 .height("10%") 5568 Row({space:2}) { 5569 Button("撤销时不还原样式").onClick(() => { 5570 this.undoStyle = UndoStyle.CLEAR_STYLE; 5571 }) 5572 Button("撤销时还原样式").onClick(() => { 5573 this.undoStyle = UndoStyle.KEEP_STYLE; 5574 }) 5575 } 5576 .borderWidth(1) 5577 .borderColor(Color.Red) 5578 .justifyContent(FlexAlign.Center) 5579 .width("100%") 5580 .height("10%") 5581 } 5582 Column() { 5583 RichEditor(this.options) 5584 .onReady(()=>{ 5585 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5586 this.controller.addImageSpan($r('app.media.startIcon'), 5587 { 5588 imageStyle: 5589 { 5590 size: ["100px", "100px"] 5591 } 5592 }); 5593 this.controller.addTextSpan("初始化图文混排内容", 5594 { 5595 style: 5596 { 5597 fontColor: Color.Orange, 5598 fontSize: 32 5599 } 5600 }) 5601 this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"), 5602 { 5603 style: 5604 { 5605 fontSize: 32 5606 } 5607 }); 5608 }) 5609 .undoStyle(this.undoStyle) 5610 .onSelect((value: RichEditorSelection) => { 5611 this.start = value.selection[0]; 5612 this.end = value.selection[1]; 5613 }) 5614 .borderWidth(1) 5615 .borderColor(Color.Green) 5616 .width("100%") 5617 .height("50%") 5618 } 5619 } 5620 } 5621} 5622``` 5623 5624 5625### 示例29(文本设置预设段落样式) 5626从API version 20开始,该示例通过[setTypingParagraphStyle](#settypingparagraphstyle20)接口设置预设段落样式。 5627 5628```ts 5629@Entry 5630@Component 5631struct RichEditorExample { 5632 controller: RichEditorController = new RichEditorController() 5633 options: RichEditorOptions = { controller: this.controller } 5634 ssController: RichEditorStyledStringController = new RichEditorStyledStringController() 5635 ssOptions: RichEditorStyledStringOptions = { controller: this.ssController } 5636 contentChangedListener: StyledStringChangedListener = { 5637 onWillChange: (value: StyledStringChangeValue) => { 5638 let range = '[ ' + value.range.start + ' , ' + value.range.end + ' ]'; 5639 let replaceString = value.replacementString.getString(); 5640 console.info('styledString, onWillChange, range=' + range); 5641 console.info('styledString, onWillChange, replaceString=' + replaceString); 5642 let styles: Array<SpanStyle> = [] 5643 if (replaceString.length != 0) { 5644 styles = value.replacementString.getStyles(0, replaceString.length, StyledStringKey.PARAGRAPH_STYLE) 5645 } 5646 styles.forEach((style) => { 5647 let value = style.styledValue 5648 let paraStyle: ParagraphStyle = value as ParagraphStyle 5649 if (paraStyle != undefined) { 5650 console.info('styledString, onWillChange, textAlign=' + JSON.stringify(paraStyle.textAlign) 5651 + ', textIndent=' + JSON.stringify(paraStyle.textIndent) 5652 + ', maxLines=' + JSON.stringify(paraStyle.maxLines) 5653 + ', overflow=' + JSON.stringify(paraStyle.overflow) 5654 + ', wordBreak=' + JSON.stringify(paraStyle.wordBreak) 5655 + ', leadingMargin=' + JSON.stringify(paraStyle.leadingMargin) 5656 + ', paragraphSpacing=' + JSON.stringify(paraStyle.paragraphSpacing) 5657 ); 5658 } 5659 }) 5660 return true; 5661 } 5662 } 5663 5664 build() { 5665 Column() { 5666 Row() { 5667 Text('ParaStyle') 5668 // 设置预设段落样式为居中对齐 5669 Button('setStyle1').onClick(() => { 5670 let paragraphStyle: RichEditorParagraphStyle = { 5671 textAlign: TextAlign.Center 5672 } 5673 this.controller.setTypingParagraphStyle(paragraphStyle) 5674 this.ssController.setTypingParagraphStyle(paragraphStyle) 5675 }) 5676 // 设置预设段落样式为左对齐、带有缩进 5677 Button('setStyle2').onClick(() => { 5678 let paragraphStyle: RichEditorParagraphStyle = { 5679 textAlign: TextAlign.Start, 5680 leadingMargin: 80 5681 } 5682 this.controller.setTypingParagraphStyle(paragraphStyle) 5683 this.ssController.setTypingParagraphStyle(paragraphStyle) 5684 }) 5685 // 清除预设段落样式 5686 Button('clearParaStyle').onClick(() => { 5687 this.controller.setTypingParagraphStyle(undefined) 5688 this.ssController.setTypingParagraphStyle(undefined) 5689 }) 5690 } 5691 5692 Row() { 5693 Column() { 5694 RichEditor(this.options) 5695 .height('25%') 5696 .width('100%') 5697 .border({ width: 1, color: Color.Blue }) 5698 .onWillChange((value: RichEditorChangeValue) => { 5699 console.info('controller, onWillChange, rangeBefore=' + JSON.stringify(value.rangeBefore)) 5700 value.replacedSpans.forEach((item: RichEditorTextSpanResult) => { 5701 console.info('controller, onWillChange, replacedTextSpans=' + JSON.stringify(item)) 5702 }) 5703 return true 5704 }) 5705 RichEditor(this.ssOptions) 5706 .height('25%') 5707 .width('100%') 5708 .onReady(() => { 5709 this.ssController.onContentChanged(this.contentChangedListener); 5710 }) 5711 } 5712 } 5713 } 5714 } 5715} 5716``` 5717 5718### 示例30(设置装饰线粗细和多装饰线) 5719从API version 20开始,该示例通过[thicknessScale](ts-universal-styled-string.md#decorationstyle)设置装饰线粗细,通过[enableMultiType](ts-universal-styled-string.md#decorationoptions20)设置多装饰线。 5720 5721```ts 5722import { LengthMetrics } from '@kit.ArkUI'; 5723 5724@Entry 5725@Component 5726struct Index { 5727 private controller: RichEditorController = new RichEditorController(); 5728 private styledStringController: RichEditorStyledStringController = new RichEditorStyledStringController(); 5729 5730 build() { 5731 Column({ space: 20 }) { 5732 RichEditor({ controller: this.controller }) 5733 .onReady(() => { 5734 // 预置一段文本 5735 this.controller.addTextSpan('一段预置的文本', { 5736 style: { 5737 fontSize: 25, 5738 decoration: { 5739 type: TextDecorationType.LineThrough, 5740 // 设置装饰线粗细比例为2 5741 thicknessScale: 2 5742 } 5743 } 5744 }) 5745 }) 5746 5747 // 设置富文本多装饰线 5748 RichEditor({ controller: this.styledStringController }) 5749 5750 Button('追加粗细比例为8的文本') 5751 .fontSize(20) 5752 .onClick(() => { 5753 this.controller.addTextSpan('追加的文本', { 5754 style: { 5755 fontSize: 25, 5756 decoration: { 5757 type: TextDecorationType.LineThrough, 5758 // 设置装饰线粗细比例为8 5759 thicknessScale: 8 5760 } 5761 } 5762 }) 5763 }) 5764 5765 Button('修改全段文本的粗细比例为4') 5766 .fontSize(20) 5767 .onClick(() => { 5768 this.controller.updateSpanStyle({ 5769 start: 0, 5770 end: 1000, // 下标超过文本长度时,会更新整段文本 5771 textStyle: { 5772 decoration: { 5773 type: TextDecorationType.LineThrough, 5774 // 设置装饰线粗细比例为4 5775 thicknessScale: 4 5776 } 5777 } 5778 }) 5779 }) 5780 5781 Button('多装饰线文本') 5782 .fontSize(20) 5783 .onClick(() => { 5784 let mutString: MutableStyledString = new MutableStyledString('设置富文本多装饰线', [ 5785 { 5786 start: 0, 5787 length: 9, 5788 styledKey: StyledStringKey.FONT, 5789 styledValue: new TextStyle({ fontSize: LengthMetrics.vp(25) }) 5790 }, 5791 { 5792 start: 0, 5793 length: 5, 5794 styledKey: StyledStringKey.DECORATION, 5795 styledValue: new DecorationStyle( 5796 { 5797 type: TextDecorationType.Underline, 5798 }, 5799 { 5800 // 开启多装饰线 5801 enableMultiType: true 5802 } 5803 ) 5804 }, 5805 { 5806 start: 2, 5807 length: 4, 5808 styledKey: StyledStringKey.DECORATION, 5809 styledValue: new DecorationStyle( 5810 { 5811 type: TextDecorationType.LineThrough, 5812 }, 5813 { 5814 // 开启多装饰线 5815 enableMultiType: true 5816 } 5817 ) 5818 }, 5819 { 5820 start: 4, 5821 length: 5, 5822 styledKey: StyledStringKey.DECORATION, 5823 styledValue: new DecorationStyle( 5824 { 5825 type: TextDecorationType.Overline, 5826 }, 5827 { 5828 // 开启多装饰线 5829 enableMultiType: true 5830 } 5831 ) 5832 }, 5833 ]) 5834 this.styledStringController.setStyledString(mutString); 5835 }) 5836 } 5837 .height('100%') 5838 .width('100%') 5839 .justifyContent(FlexAlign.Center) 5840 .alignItems(HorizontalAlign.Center) 5841 } 5842} 5843``` 5844 5845 5846 5847### 示例31(设置开启中西文自动间距) 5848从API version 20开始,该示例通过[enableAutoSpacing](#enableautospacing20)属性设置中西文自动间距。 5849 5850```ts 5851@Entry 5852@Component 5853struct AutoSpacing { 5854 controller: RichEditorController = new RichEditorController(); 5855 options: RichEditorOptions = { controller: this.controller }; 5856 @State enableAutoSpace: boolean = false; 5857 5858 build() { 5859 Column() { 5860 Column() { 5861 Row({ space: 2 }) { 5862 Button("插入中西文内容").onClick(() => { 5863 this.controller.addTextSpan("Add文本Span", 5864 { 5865 style: 5866 { 5867 fontColor: Color.Orange, 5868 fontSize: 20 5869 } 5870 }) 5871 }) 5872 Button("插入图片").onClick(() => { 5873 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5874 this.controller.addImageSpan($r('app.media.startIcon'), 5875 { 5876 imageStyle: 5877 { 5878 size: ["100px", "100px"] 5879 } 5880 }); 5881 }) 5882 Button("插入Symbol").onClick(() => { 5883 this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"), 5884 { 5885 style: 5886 { 5887 fontSize: 32 5888 } 5889 }); 5890 }) 5891 } 5892 .borderWidth(1) 5893 .borderColor(Color.Red) 5894 .justifyContent(FlexAlign.Center) 5895 .width("100%") 5896 .height("10%") 5897 5898 Row({ space: 2 }) { 5899 Button("开启中西文自动间距").onClick(() => { 5900 this.enableAutoSpace = true; 5901 }) 5902 Button("关闭中西文自动间距").onClick(() => { 5903 this.enableAutoSpace = false; 5904 }) 5905 } 5906 .borderWidth(1) 5907 .borderColor(Color.Red) 5908 .justifyContent(FlexAlign.Center) 5909 .width("100%") 5910 .height("10%") 5911 } 5912 5913 Column() { 5914 RichEditor(this.options) 5915 .onReady(() => { 5916 // $r('app.media.startIcon')需要替换为开发者所需的图像资源文件。 5917 this.controller.addImageSpan($r('app.media.startIcon'), 5918 { 5919 imageStyle: 5920 { 5921 size: ["100px", "100px"] 5922 } 5923 }); 5924 this.controller.addTextSpan("中西文Auto Spacing自动间距", 5925 { 5926 style: 5927 { 5928 fontColor: Color.Orange, 5929 fontSize: 20 5930 } 5931 }) 5932 this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"), 5933 { 5934 style: 5935 { 5936 fontSize: 20 5937 } 5938 }); 5939 }) 5940 .enableAutoSpacing(this.enableAutoSpace) 5941 .borderWidth(1) 5942 .borderColor(Color.Green) 5943 .width("100%") 5944 .height("50%") 5945 } 5946 } 5947 } 5948} 5949``` 5950