1# RichEditor 2 3支持图文混排和文本交互式编辑的组件。 4 5> **说明:** 6> 7> 该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8 9 10## 子组件 11 12不包含子组件。 13 14 15## 接口 16 17RichEditor(value: RichEditorOptions) 18 19**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 20 21**系统能力:** SystemCapability.ArkUI.ArkUI.Full 22 23**参数:** 24 25| 参数名 | 类型 | 必填 | 说明 | 26| ----- | --------------------------------------- | ---- | ----------- | 27| value | [RichEditorOptions](#richeditoroptions) | 是 | 富文本组件初始化选项。 | 28 29RichEditor(options: RichEditorStyledStringOptions)<sup>12+</sup> 30 31 32**参数:** 33 34| 参数名 | 类型 | 必填 | 说明 | 35| ----- | --------------------------------------- | ---- | ----------- | 36| options | [RichEditorStyledStringOptions](#richeditorstyledstringoptions12) | 是 | 富文本组件初始化选项。 | 37 38## 属性 39 40除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性: 41 42> **说明:** 43> 44> align属性只支持上方、中间和下方位置的对齐方式。 45> 46> 不支持borderImage属性。 47 48### customKeyboard 49 50customKeyboard(value: CustomBuilder, options?: KeyboardOptions) 51 52设置自定义键盘。 53 54当设置自定义键盘时,输入框激活后不会打开系统输入法,而是加载指定的自定义组件。 55 56自定义键盘的高度可以通过自定义组件根节点的height属性设置,宽度不可设置,使用系统默认值。 57 58自定义键盘无法获取焦点,但是会拦截手势事件。 59 60默认在输入控件失去焦点时,关闭自定义键盘。 61 62如果设备支持拍摄输入,设置自定义键盘后,该输入框会不支持拍摄输入。 63 64**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 65 66**系统能力:** SystemCapability.ArkUI.ArkUI.Full 67 68**参数:** 69 70| 参数名 | 类型 | 必填 | 说明 | 71| --------------------- | ------------------------------------------- | ---- | -------------------------------- | 72| value | [CustomBuilder](ts-types.md#custombuilder8) | 是 | 自定义键盘。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 73| options<sup>12+</sup> | [KeyboardOptions](#keyboardoptions12) | 否 | 设置自定义键盘是否支持避让功能。 | 74 75### bindSelectionMenu 76 77bindSelectionMenu(spanType: RichEditorSpanType, content: CustomBuilder, responseType: ResponseType | RichEditorResponseType, 78 options?: SelectionMenuOptions) 79 80设置自定义选择菜单。自定义菜单超长时,建议内部嵌套[Scroll](./ts-container-scroll.md)组件使用,避免键盘被遮挡。 81 82**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 83 84**系统能力:** SystemCapability.ArkUI.ArkUI.Full 85 86**参数:** 87 88| 参数名 | 类型 | 必填 | 说明 | 89| ------------ | ------------------------------------------------------------ | ---- | --------------------------------------------------------- | 90| spanType | [RichEditorSpanType](#richeditorspantype) | 是 | 菜单的类型。<br/> 默认值:<br/>RichEditorSpanType.TEXT | 91| content | [CustomBuilder](ts-types.md#custombuilder8) | 是 | 菜单的内容。 | 92| responseType | [ResponseType](ts-appendix-enums.md#responsetype8) \| [RichEditorResponseType](#richeditorresponsetype11) | 是 | 菜单的响应类型。<br/> 默认值:<br/>ResponseType.LongPress | 93| options | [SelectionMenuOptions](#selectionmenuoptions10) | 否 | 菜单的选项。 | 94 95### copyOptions 96 97copyOptions(value: CopyOptions) 98 99设置组件是否支持文本内容可复制粘贴。 100 101copyOptions不为CopyOptions.None时,长按组件内容,会弹出文本选择弹框。如果通过bindSelectionMenu等方式自定义文本选择菜单,则会弹出自定义的菜单。 102 103设置copyOptions为CopyOptions.None,复制、剪切功能不生效。 104 105**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。 106 107**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 108 109**系统能力:** SystemCapability.ArkUI.ArkUI.Full 110 111**参数:** 112 113| 参数名 | 类型 | 必填 | 说明 | 114| ------ | ------------------------------------------------ | ---- | ------------------------------------------------------------ | 115| value | [CopyOptions](ts-appendix-enums.md#copyoptions9) | 是 | 组件支持文本内容是否可复制粘贴。<br />默认值:CopyOptions.LocalDevice <br />**卡片能力:** 从API version 10开始,该接口支持在ArkTS卡片中使用。|| 116 117### enableDataDetector<sup>11+</sup> 118 119enableDataDetector(enable: boolean) 120 121设置是否进行文本特殊实体识别。 122 123该接口依赖设备底层应具有文本识别能力,否则设置不会生效。 124 125当enableDataDetector设置为true,同时不设置dataDetectorConfig属性时,默认识别所有类型的实体,所识别实体的color和decoration会被更改为如下样式: 126 127```ts 128color: '#ff007dff' 129decoration:{ 130 type: TextDecorationType.Underline, 131 color: '#ff007dff', 132 style: TextDecorationStyle.SOLID 133} 134``` 135 136触摸点击和鼠标右键点击实体,会根据实体类型弹出对应的实体操作菜单,鼠标左键点击实体会直接响应菜单的第一个选项。 137 138对addBuilderSpan的节点文本,该功能不会生效。 139 140当copyOption设置为CopyOptions.None时,点击实体弹出的菜单没有选择文本和复制功能。 141 142**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 143 144**系统能力:** SystemCapability.ArkUI.ArkUI.Full 145 146**参数:** 147 148| 参数名 | 类型 | 必填 | 说明 | 149| ------ | ------- | ---- | --------------------------------- | 150| enable | boolean | 是 | 使能文本识别。<br/>默认值: false | 151 152### dataDetectorConfig<sup>11+</sup> 153 154dataDetectorConfig(config: TextDataDetectorConfig) 155 156设置文本识别配置。 157 158需配合[enableDataDetector](#enabledatadetector11)一起使用,设置enableDataDetector为true时,dataDetectorConfig的配置才能生效。 159 160当有两个实体A、B重叠时,按以下规则保留实体: 161 1621. 若A ⊂ B,则保留B,反之则保留A。 163 1642. 当A ⊄ B且B ⊄ A时,若A.start < B.start,则保留A,反之则保留B。 165 166**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 167 168**系统能力:** SystemCapability.ArkUI.ArkUI.Full 169 170**参数:** 171 172| 参数名 | 类型 | 必填 | 说明 | 173| ------ | ----------------------------------------------------------- | ---- | ------------------------------------------------------------ | 174| config | [TextDataDetectorConfig](ts-text-common.md#textdatadetectorconfig11对象说明) | 是 | 文本识别配置。| 175 176### enablePreviewText<sup>12+</sup> 177 178enablePreviewText(enable: boolean) 179 180设置是否开启预上屏功能。 181 182**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 183 184**系统能力:** SystemCapability.ArkUI.ArkUI.Full 185 186**参数:** 187 188| 参数名 | 类型 | 必填 | 说明 | 189| ------ | ------- | ---- | --------------------------------- | 190| enable | boolean | 是 | 使能预上屏功能。<br/>默认值: true | 191 192> **说明:** 193> 194> 该接口在CAPI场景使用时下,默认关闭。可以在工程的module.json5中配置[metadata](../../../../application-dev/quick-start/module-structure.md#metadata对象内部结构)字段控制是否启用预上屏,配置如下: 195> ```json 196> "metadata": [ 197> { 198> "name": "can_preview_text", 199> "value": "true", 200> } 201> ] 202> ``` 203 204### placeholder<sup>12+</sup> 205 206placeholder(value: ResourceStr, style?: PlaceholderStyle) 207 208设置无输入时的提示文本。 209 210**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 211 212**系统能力:** SystemCapability.ArkUI.ArkUI.Full 213 214**参数:** 215 216| 参数名 | 类型 | 必填 | 说明 | 217| ------ | --------------------------------------- | ---- | ------------------------------------------------------- | 218| value | [ResourceStr](ts-types.md#resourcestr) | 是 | 无输入时的提示文本。 | 219| style | [PlaceholderStyle](#placeholderstyle12) | 否 | 添加提示文本的字体样式。<br />style缺省时默认跟随主题。 | 220 221### caretColor<sup>12+</sup> 222 223caretColor(value: ResourceColor) 224 225设置输入框光标、手柄颜色。 226 227**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 228 229**系统能力:** SystemCapability.ArkUI.ArkUI.Full 230 231**参数:** 232 233| 参数名 | 类型 | 必填 | 说明 | 234| ------ | ------------------------------------------ | ---- | -------------------------------------- | 235| value | [ResourceColor](ts-types.md#resourcecolor) | 是 | 输入框光标、手柄颜色。<br/>默认值:'#007DFF' | 236 237### selectedBackgroundColor<sup>12+</sup> 238 239selectedBackgroundColor(value: ResourceColor) 240 241设置文本选中底板颜色。如果未设置不透明度,默认为20%不透明度。 242 243**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 244 245**系统能力:** SystemCapability.ArkUI.ArkUI.Full 246 247**参数:** 248 249| 参数名 | 类型 | 必填 | 说明 | 250| ------ | ------------------------------------------ | ---- | ------------------------------------------ | 251| value | [ResourceColor](ts-types.md#resourcecolor) | 是 | 文本选中底板颜色。<br/>默认为20%不透明度。 | 252 253### editMenuOptions<sup>12+</sup> 254 255editMenuOptions(editMenu: EditMenuOptions) 256 257设置自定义菜单扩展项,允许用户设置扩展项的文本内容、图标、回调方法。 258 259**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 260 261 262**元服务API:** 从API version 12开始,该接口支持在元服务中使用。 263 264**系统能力:** SystemCapability.ArkUI.ArkUI.Full 265 266**参数:** 267 268| 参数名 | 类型 | 必填 | 说明 | 269| ------ | --------------------------------------------- | ---- | --------------------------------------------- | 270| editMenu | [EditMenuOptions](ts-text-common.md#editmenuoptions对象说明) | 是 | 扩展菜单选项。 | 271 272### enterKeyType<sup>12+</sup> 273 274enterKeyType(value: EnterKeyType) 275 276设置软键盘输入法回车键类型。 277 278**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 279 280**系统能力:** SystemCapability.ArkUI.ArkUI.Full 281 282**参数:** 283 284| 参数名 | 类型 | 必填 | 说明 | 285| ------ | ------ | ---- | ----------------------------------- | 286| value | [EnterKeyType](ts-types.md#enterkeytype枚举说明) | 是 | 键盘输入法回车键类型。<br/>默认为EnterKeyType.NEW_LINE。 | 287 288### enableKeyboardOnFocus<sup>12+</sup> 289 290enableKeyboardOnFocus(isEnabled: boolean) 291 292设置RichEditor通过点击以外的方式获焦时,是否主动拉起软键盘。 293 294 295**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 296 297**系统能力:** SystemCapability.ArkUI.ArkUI.Full 298 299**参数:** 300 301| 参数名 | 类型 | 必填 | 说明 | 302| ------ | ------- | ---- | ----------------------------------------------------------- | 303| isEnabled | boolean | 是 | 通过点击以外的方式获焦时,是否主动拉起软键盘。<br/>默认值:true | 304 305### barState<sup>13+</sup> 306 307barState(state: BarState) 308 309设置RichEditor编辑态时滚动条的显示模式。 310 311**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 312 313**系统能力:** SystemCapability.ArkUI.ArkUI.Full 314 315**参数:** 316 317| 参数名 | 类型 | 必填 | 说明 | 318| ------ | ----------------------------------------- | ---- | ------------------------------------------------------ | 319| state | [BarState](ts-appendix-enums.md#barstate) | 是 | 输入框编辑态时滚动条的显示模式。<br/>默认值:BarState.Auto | 320 321### enableHapticFeedback<sup>13+</sup> 322 323enableHapticFeedback(isEnabled: boolean) 324 325设置RichEditor是否支持触控反馈。 326 327**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 328 329**系统能力:** SystemCapability.ArkUI.ArkUI.Full 330 331| 参数名 | 类型 | 必填 | 说明 | 332| ------ | --------------------------------------------- |-----|-------------------------------------------------------------------------------------| 333| isEnabled | boolean | 是 | 是否支持触控反馈。<br/>默认值:true,true表示开启触控反馈,false表示不开启触控反馈。<br/>设置为true后是否生效,还取决于系统的硬件是否支持。 | 334 335## 事件 336 337除支持[通用事件](ts-universal-events-click.md)外,还支持[OnDidChangeCallback](ts-text-common.md#ondidchangecallback12)、[StyledStringChangedListener](ts-text-common.md#styledstringchangedlistener12)、[StyledStringChangeValue](ts-text-common.md#styledstringchangevalue12)和以下事件: 338 339### onReady 340 341onReady(callback:Callback\<void\>) 342 343富文本组件初始化完成后,触发回调。 344 345**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 346 347**系统能力:** SystemCapability.ArkUI.ArkUI.Full 348 349**参数:** 350 351| 参数名 | 类型 | 必填 | 说明 | 352| ----- | --------------------------------------- | ---- | ----------- | 353| callback |Callback\<void\> | 是 | 订阅富文本组件初始化完成的回调。 | 354 355### onSelect 356 357onSelect(callback:Callback\<[RichEditorSelection](#richeditorselection)\>) 358 359鼠标左键双击选中内容时,会触发回调;松开鼠标左键后,会再次触发回调。 360 361手指长按选中内容时,会触发回调;松开手指后,会再次触发回调。 362 363使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 364 365**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 366 367**系统能力:** SystemCapability.ArkUI.ArkUI.Full 368 369**参数:** 370 371| 参数名 | 类型 | 必填 | 说明 | 372| ------ | ------------------------------------------- | ---- | -------------------- | 373| callback | Callback\<[RichEditorSelection](#richeditorselection)\> | 是 | [RichEditorSelection](#richeditorselection)为选中的所有span信息。<br/>选择时触发的回调。 | 374 375### aboutToIMEInput 376 377aboutToIMEInput(callback:Callback\<[RichEditorInsertValue](#richeditorinsertvalue), boolean\>) 378 379输入法输入内容前,触发回调。 380 381使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 382 383**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 384 385**系统能力:** SystemCapability.ArkUI.ArkUI.Full 386 387**参数:** 388 389| 参数名 | 类型 | 必填 | 说明 | 390| ------ | ------------------------------------------- | ---- | -------------------- | 391| callback | Callback\<[RichEditorInsertValue](#richeditorinsertvalue), boolean\> | 是 | [RichEditorInsertValue](#richeditorinsertvalue)为输入法将要输入内容信息。<br/>true:组件执行添加内容操作。<br/>false:组件不执行添加内容操作<br/>输入法输入内容前的回调。| 392 393### onDidIMEInput<sup>12+</sup> 394 395onDidIMEInput(callback:Callback\<TextRange>) 396 397输入法完成输入时,触发回调。 398 399使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 400 401**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 402 403**系统能力:** SystemCapability.ArkUI.ArkUI.Full 404 405**参数:** 406 407| 参数名 | 类型 | 必填 | 说明 | 408| ------ | ------------------------------------------- | ---- | -------------------- | 409| callback | Callback\<[TextRange](ts-text-common.md#textrange12)\> | 是 | TextRange为输入法本次输入内容的范围。<br/>输入法完成输入时的回调。| 410 411### onIMEInputComplete 412 413onIMEInputComplete(callback:Callback\<[RichEditorTextSpanResult](#richeditortextspanresult)\>) 414 415输入法完成输入后,触发回调。 416 417使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 418 419**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 420 421**系统能力:** SystemCapability.ArkUI.ArkUI.Full 422 423**参数:** 424 425| 参数名 | 类型 | 必填 | 说明 | 426| ------ | ------------------------------------------- | ---- | -------------------- | 427| callback | Callback\<[RichEditorTextSpanResult](#richeditortextspanresult)\> | 是 | [RichEditorTextSpanResult](#richeditortextspanresult)为输入法完成输入后的文本Span信息。<br/>输入法完成输入后的回调。| 428 429### aboutToDelete 430 431aboutToDelete(callback:Callback\<[RichEditorDeleteValue](#richeditordeletevalue), boolean\>) 432 433输入法删除内容前,触发回调。 434 435使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 436 437**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 438 439**系统能力:** SystemCapability.ArkUI.ArkUI.Full 440 441**参数:** 442 443| 参数名 | 类型 | 必填 | 说明 | 444| ------ | ------------------------------------------- | ---- | -------------------- | 445| callback | Callback\<[RichEditorDeleteValue](#richeditordeletevalue), boolean\> | 是 | [RichEditorDeleteValue](#richeditordeletevalue)为准备删除的内容所在的文本或者图片Span信息。<br/>true:组件执行删除操作。<br/>false:组件不执行删除操作。<br/>输入法删除内容前的回调,英文预上屏点击候选词时会执行该回调。| 446 447### onDeleteComplete 448 449onDeleteComplete(callback:Callback\<void\>) 450 451输入法完成删除后,触发回调。 452 453使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 454 455**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 456 457**系统能力:** SystemCapability.ArkUI.ArkUI.Full 458 459**参数:** 460 461| 参数名 | 类型 | 必填 | 说明 | 462| ----- | --------------------------------------- | ---- | ----------- | 463| callback |Callback\<void\> | 是 | 订阅输入法完成删除的回调。 | 464 465### onPaste<sup>11+</sup> 466 467onPaste(callback: [PasteEventCallback](#pasteeventcallback12) ) 468 469完成粘贴前,触发回调。开发者可以通过该方法,覆盖系统默认行为,实现图文的粘贴。 470 471**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 472 473**系统能力:** SystemCapability.ArkUI.ArkUI.Full 474 475**参数:** 476 477| 参数名 | 类型 | 必填 | 说明 | 478| ------ | ------- | ---- | ----------------------------- | 479| callback | [PasteEventCallback](#pasteeventcallback12) | 是 | 订阅完成粘贴前的回调。 | 480 481### onSelectionChange<sup>12+</sup> 482 483onSelectionChange(callback:Callback\<[RichEditorRange](#richeditorrange)\>) 484 485组件内所有内容选择区域发生变化或编辑状态下光标位置发生变化时触发该回调。光标位置发生变化回调时,选择区域的起始位置等于终止位置。 486 487**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 488 489**系统能力:** SystemCapability.ArkUI.ArkUI.Full 490 491**参数:** 492 493| 参数名 | 类型 | 必填 | 说明 | 494| ----- | --------------------------------------- | ---- | ----------- | 495| callback |Callback\<[RichEditorRange](#richeditorrange)\> | 是 | [RichEditorRange](#richeditorrange)为所有内容的选择区域起始和终止位置。<br/>订阅文本选择区域发生变化或编辑状态下光标位置发生变化时触发的回调| 496 497### onEditingChange<sup>12+</sup> 498 499onEditingChange(callback: Callback\<boolean\>) 500 501组件内所有内容的编辑状态发生改变时触发该回调函数。 502 503**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 504 505**系统能力:** SystemCapability.ArkUI.ArkUI.Full 506 507**参数:** 508 509| 参数名 | 类型 | 必填 | 说明 | 510| ----- | --------------------------------------- | ---- | ----------- | 511| callback | Callback\<boolean\> | 是 | true表示编辑态,false表示非编辑态。 | 512 513### onSubmit<sup>12+</sup> 514 515onSubmit(callback: SubmitCallback) 516 517按下软键盘输入法回车键触发该回调。 518 519**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 520 521**系统能力:** SystemCapability.ArkUI.ArkUI.Full 522 523**参数:** 524 525| 参数名 | 类型 | 必填 | 说明 | 526| ------ | ------- | ---- | ----------------------------- | 527| callback | [SubmitCallback](#submitcallback12) | 是 | 侦听事件的回调。 | 528 529### onWillChange<sup>12+</sup> 530 531onWillChange(callback: Callback\<RichEditorChangeValue, boolean\>) 532 533组件执行增删操作前,触发回调。 534 535使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 536 537**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 538 539**系统能力:** SystemCapability.ArkUI.ArkUI.Full 540 541**参数:** 542 543| 参数名 | 类型 | 必填 | 说明 | 544| -- | -- | -- | -- | 545| callback | Callback\<[RichEditorChangeValue](#richeditorchangevalue12) , boolean\> | 是 | [RichEditorChangeValue](#richeditorchangevalue12)为图文变化信息;boolean表示当前图文是否允许被更改,true:允许图文被更改。false:不允许图文被更改。 | 546 547### onDidChange<sup>12+</sup> 548 549onDidChange(callback: OnDidChangeCallback) 550 551组件执行增删操作后,触发回调。文本实际未发生增删时,不触发该回调。 552 553使用[RichEditorStyledStringOptions](#richeditorstyledstringoptions12)构建的RichEditor组件时不支持该回调。 554 555**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 556 557**系统能力:** SystemCapability.ArkUI.ArkUI.Full 558 559**参数:** 560 561| 参数名 | 类型 | 必填 | 说明 | 562| -- | -- | -- | -- | 563| callback | [OnDidChangeCallback](ts-text-common.md#ondidchangecallback12) | 是 | 图文变化前后的内容范围。 | 564 565### onCut<sup>12+</sup> 566 567onCut(callback: Callback\<CutEvent\>) 568 569完成剪切前,触发回调。系统的默认剪切行为,只支持纯文本的剪切。开发者可以通过该方法,覆盖系统默认行为,实现图文的剪切。 570 571**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 572 573**系统能力:** SystemCapability.ArkUI.ArkUI.Full 574 575**参数:** 576 577| 参数名 | 类型 | 必填 | 说明 | 578| ----- | --------------------------------------- | ---- | ----------- | 579| callback |Callback\<[CutEvent](#cutevent12)\> | 是 | 定义用户剪切事件。 | 580 581### onCopy<sup>12+</sup> 582 583onCopy(callback: Callback\<CopyEvent\>) 584 585完成复制前,触发回调。系统的默认复制行为,只支持纯文本的复制。开发者可以通过该方法,覆盖系统默认行为,实现图文的复制。 586 587**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 588 589**系统能力:** SystemCapability.ArkUI.ArkUI.Full 590 591**参数:** 592 593| 参数名 | 类型 | 必填 | 说明 | 594| ----- | --------------------------------------- | ---- | ----------- | 595| callback |Callback\<[CopyEvent](#copyevent12)\> | 是 | 定义用户复制事件。 | 596 597## RichEditorInsertValue 598 599插入文本信息。 600 601**系统能力:** SystemCapability.ArkUI.ArkUI.Full 602 603| 名称 | 类型 | 必填 | 说明 | 604| ------------ | ------ | ---- | ---------- | 605| insertOffset | number | 是 | 插入的文本偏移位置。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 606| insertValue | string | 是 | 插入的文本内容。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 607| previewText<sup>12+</sup> | string | 否 | 插入的预上屏文本内容。<br/> **原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 608 609 610## RichEditorDeleteValue 611 612删除操作的信息和被删除内容的信息。 613 614**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 615 616**系统能力:** SystemCapability.ArkUI.ArkUI.Full 617 618| 名称 | 类型 | 必填 | 说明 | 619| --------------------- | ---------------------------------------- | ---- | ------------------- | 620| offset | number | 是 | 删除内容的偏移位置。 | 621| direction | [RichEditorDeleteDirection](#richeditordeletedirection) | 是 | 删除操作的方向。 | 622| length | number | 是 | 删除内容长度。 | 623| richEditorDeleteSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult) \| [RichEditorImageSpanResult](#richeditorimagespanresult)> | 是 | 删除的文本或者图片Span的具体信息。 | 624 625 626## RichEditorDeleteDirection 627 628删除操作的方向。 629 630**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 631 632**系统能力:** SystemCapability.ArkUI.ArkUI.Full 633 634| 名称 | 说明 | 635| -------- | ---------- | 636| BACKWARD | 向后删除。 | 637| FORWARD | 向前删除。 | 638 639 640## RichEditorTextSpanResult 641 642文本Span信息。 643 644**系统能力:** SystemCapability.ArkUI.ArkUI.Full 645 646| 名称 | 类型 | 必填 | 说明 | 647| ----------------------------- | ---------------------------------------- | ---- | ---------------------- | 648| spanPosition | [RichEditorSpanPosition](#richeditorspanposition) | 是 | Span位置。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 649| value | string | 是 | 文本Span内容或Symbol的id。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 650| textStyle | [RichEditorTextStyleResult](#richeditortextstyleresult) | 是 | 文本Span样式信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 651| offsetInSpan | [number, number] | 是 | 文本Span内容里有效内容的起始和结束位置。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 652| valueResource<sup>11+</sup> | [Resource](ts-types.md#resource) | 否 | 组件SymbolSpan内容。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 653| symbolSpanStyle<sup>11+</sup> | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | 否 | 组件SymbolSpan样式信息。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 654| paragraphStyle<sup>12+</sup> | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 否 | 段落样式。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 655| previewText<sup>12+</sup> | string | 否 | 文本Span预上屏内容。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 656 657 658## RichEditorSpanPosition 659 660Span位置信息。 661 662**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 663 664**系统能力:** SystemCapability.ArkUI.ArkUI.Full 665 666| 名称 | 类型 | 必填 | 说明 | 667| --------- | ---------------- | ---- | --------------------------- | 668| spanIndex | number | 是 | Span索引值。 | 669| spanRange | [number, number] | 是 | Span内容在RichEditor内的起始和结束位置。 | 670 671## RichEditorSpanType 672 673Span类型信息。 674 675**系统能力:** SystemCapability.ArkUI.ArkUI.Full 676 677| 名称 | 值 | 说明 | 678| ----- | ---- | ------------ | 679| TEXT | 0 | Span为文字类型。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 680| IMAGE | 1 | Span为图像类型。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 681| MIXED | 2 | Span为图文混合类型。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 682| BUILDER<sup>12+</sup> | 3 | Span为BuilderSpan类型。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 683 684## RichEditorResponseType<sup>11+</sup> 685 686菜单的响应类型。 687 688**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 689 690**系统能力:** SystemCapability.ArkUI.ArkUI.Full 691 692| 名称 | 说明 | 693| ---------- | ------------- | 694| LONG_PRESS | 通过长按触发菜单弹出。 | 695| RIGHT_CLICK | 通过鼠标右键触发菜单弹出。 | 696| SELECT | 通过鼠标选中触发菜单弹出。 | 697 698## RichEditorTextStyleResult 699 700后端返回的文本样式信息。 701 702**系统能力:** SystemCapability.ArkUI.ArkUI.Full 703 704| 名称 | 类型 | 必填 | 说明 | 705| ---------- | ---------------------------------------- | ---- | ------------ | 706| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 是 | 文本颜色。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 707| fontSize | number | 是 | 字体大小,默认单位为fp。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 708| fontStyle | [FontStyle](ts-appendix-enums.md#fontstyle) | 是 | 字体样式。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 709| fontWeight | number | 是 | 字体粗细。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 710| fontFamily | string | 是 | 字体列表。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 711| decoration | [DecorationStyleResult](ts-text-common.md#decorationstyleresult12) | 是 | 文本装饰线样式信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 712| textShadow<sup>12+</sup> | Array<[ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions对象说明)> | 否 | 文字阴影效果。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 713| lineHeight<sup>12+</sup> | number | 否 | 文本行高,默认单位为fp。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 714| letterSpacing<sup>12+</sup>| number | 否 | 文本字符间距,默认单位为fp。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 715| fontFeature<sup>12+</sup> | string | 否 | 文字特性效果。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 716 717> **说明:** 718> 719> 在RichEditorTextStyle中,fontWeight是设置字体粗细的输入参数。 720> 而在RichEditorTextStyleResult中,会将之前设置的字体粗细转换为数字后返回。 721> 转换关系如下: 722> 723> | RichEditorTextStyle中的fontWeight | RichEditorTextStyleResult中的fontWeight | 724> | ---- | ----------------------------------- | 725> | 100 | 0 | 726> | 200 | 1 | 727> | 300 | 2 | 728> | 400 | 3 | 729> | 500 | 4 | 730> | 600 | 5 | 731> | 700 | 6 | 732> | 800 | 7 | 733> | 900 | 8 | 734> | Lighter | 12 | 735> | Normal | 10 | 736> | Regular | 14 | 737> | Medium | 13 | 738> | Bold | 9 | 739> | Bolder | 11 | 740> 741> RichEditorSymbolSpanStyle和RichEditorSymbolSpanStyleResult中fontWeight的转换关系, 742> 与RichEditorTextStyle和RichEditorTextStyleResult中fontWeight的转换关系一致。 743 744## RichEditorSymbolSpanStyleResult<sup>11+</sup> 745 746后端返回的SymbolSpan样式信息。 747 748**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 749 750**系统能力:** SystemCapability.ArkUI.ArkUI.Full 751 752| 名称 | 类型 | 必填 | 说明 | 753| ------ | -------- | ---- | -------------------------------------- | 754| fontColor | Array\<[ResourceColor](ts-types.md#resourcecolor)\> | 是 | SymbolSpan组件颜色。<br/> 默认值:不同渲染策略下默认值不同。 | 755| fontSize | number \| string \| [Resource](ts-types.md#resource) | 是 | SymbolSpan组件大小,默认单位为fp。<br/>默认值:跟随主题。| 756| 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。| 757| renderingStrategy | [SymbolRenderingStrategy](ts-basic-components-symbolGlyph.md#symbolrenderingstrategy11枚举说明) | 是 | SymbolSpan组件渲染策略。<br/>默认值:SymbolRenderingStrategy.SINGLE。| 758| effectStrategy | [SymbolEffectStrategy](ts-basic-components-symbolGlyph.md#symboleffectstrategy11枚举说明) | 是 | SymbolSpan组件动效策略。<br/>默认值:SymbolEffectStrategy.NONE。| 759 760## RichEditorImageSpanResult 761 762后端返回的图片信息。 763 764**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 765 766**系统能力:** SystemCapability.ArkUI.ArkUI.Full 767 768| 名称 | 类型 | 必填 | 说明 | 769|------------------|-------------------------------------------------------------------|-----|------------------| 770| spanPosition | [RichEditorSpanPosition](#richeditorspanposition) | 是 | Span位置。| 771| valuePixelMap | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7) | 否 | 图片内容。| 772| valueResourceStr | [ResourceStr](ts-types.md#resourcestr) | 否 | 图片资源id。| 773| imageStyle | [RichEditorImageSpanStyleResult](#richeditorimagespanstyleresult) | 是 | 图片样式。| 774| offsetInSpan | [number, number] | 是 | Span里图片的起始和结束位置。| 775 776## RichEditorImageSpanStyleResult 777 778后端返回的图片样式信息。 779 780**系统能力:** SystemCapability.ArkUI.ArkUI.Full 781 782| 名称 | 类型 | 必填 | 说明 | 783| ------------- | ---------------------------------------- | ---- | --------- | 784| size | [number, number] | 是 | 图片的宽度和高度,单位为px。默认值:size的默认值与objectFit的值有关,不同的objectFit值对应的size默认值也不同。objectFit的值为Cover时,图片高度为组件高度减去组件上下内边距,图片宽度为组件宽度减去组件左右内边距。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 785| verticalAlign | [ImageSpanAlignment](ts-basic-components-imagespan.md#imagespanalignment) | 是 | 图片垂直对齐方式。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 786| objectFit | [ImageFit](ts-appendix-enums.md#imagefit) | 是 | 图片缩放类型。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 787| layoutStyle<sup>12+</sup> | [RichEditorLayoutStyle](#richeditorlayoutstyle11) | 否 | 图片布局风格。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 || 788 789## RichEditorLayoutStyle<sup>11+</sup> 790 791**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 792 793**系统能力:** SystemCapability.ArkUI.ArkUI.Full 794 795|名称 |类型 |必填| 说明| 796| ------------- | ----------------------- | ---- | ------------------------------------------------------------ | 797|margin | [Dimension](ts-types.md#dimension10) \| [Margin](ts-types.md#margin) | 否 | 外边距类型,用于描述组件不同方向的外边距。<br/>参数为Dimension类型时,四个方向外边距同时生效。| 798|borderRadius | [Dimension](ts-types.md#dimension10) \| [BorderRadiuses](ts-types.md#borderradiuses9) | 否 | 圆角类型,用于描述组件边框圆角半径。<br/>参数为Dimension类型时,不支持以Percentage形式设置。| 799 800## RichEditorOptions 801 802RichEditor初始化参数。 803 804**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 805 806**系统能力:** SystemCapability.ArkUI.ArkUI.Full 807 808| 名称 | 类型 | 必填 | 说明 | 809| ---------- | ---------------------------------------- | ---- | ------- | 810| controller | [RichEditorController](#richeditorcontroller) | 是 | 富文本控制器。 | 811 812## RichEditorStyledStringOptions<sup>12+</sup> 813 814RichEditor初始化参数。 815 816**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 817 818**系统能力:** SystemCapability.ArkUI.ArkUI.Full 819 820| 名称 | 类型 | 必填 | 说明 | 821| ---------- | ---------------------------------------- | ---- | ------- | 822| controller | [RichEditorStyledStringController](#richeditorstyledstringcontroller12) | 是 | 富文本控制器。 | 823 824## RichEditorChangeValue<sup>12+</sup> 825 826**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 827 828**系统能力:** SystemCapability.ArkUI.ArkUI.Full 829 830| 名称 | 类型 | 必填 | 说明 | 831| --------------------- | ---------------------------------------- | ---- | ------------------- | 832| rangeBefore | [TextRange](ts-universal-attributes-text-style.md#textrange12) | 是 | 即将被替换内容的开始和结束索引。 | 833| replacedSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)> | 是 | 替换后文本Span的具体信息。 | 834| replacedImageSpans | Array<[RichEditorImageSpanResult](#richeditorimagespanresult)> | 是 | 替换后ImageSpan的具体信息。 | 835| replacedSymbolSpans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)> | 是 | 替换后SymbolSpan的具体信息。 | 836 837## RichEditorBaseController<sup>12+</sup> 838 839RichEditor组件控制器基类。 840 841### getCaretOffset<sup>10+</sup> 842 843getCaretOffset(): number 844 845返回当前光标所在位置。 846 847**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 848 849**系统能力:** SystemCapability.ArkUI.ArkUI.Full 850 851**返回值:** 852 853| 类型 | 说明 | 854| ------ | --------- | 855| number | 当前光标所在位置。 | 856 857### setCaretOffset<sup>10+</sup> 858 859setCaretOffset(offset: number): boolean 860 861设置光标位置。 862 863**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 864 865**系统能力:** SystemCapability.ArkUI.ArkUI.Full 866 867**参数:** 868 869| 参数名 | 类型 | 必填 | 说明 | 870| ------ | ------ | ---- | -------------------- | 871| offset | number | 是 | 光标偏移位置。超出所有内容范围时,设置失败。 | 872 873**返回值:** 874 875| 类型 | 说明 | 876| ------- | --------- | 877| boolean | 光标是否设置成功。 | 878 879### closeSelectionMenu<sup>10+</sup> 880 881closeSelectionMenu(): void 882 883关闭自定义选择菜单或系统默认选择菜单。 884 885**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 886 887**系统能力:** SystemCapability.ArkUI.ArkUI.Full 888 889### getTypingStyle<sup>11+</sup> 890 891getTypingStyle(): RichEditorTextStyle 892 893获得用户预设的样式。 894 895**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 896 897**系统能力:** SystemCapability.ArkUI.ArkUI.Full 898 899**返回值:** 900 901| 类型 | 说明 | 902| ---------------------------------------- | ------- | 903| [RichEditorTextStyle](#richeditortextstyle) | 用户预设样式。 | 904 905### setTypingStyle<sup>11+</sup> 906 907setTypingStyle(value: RichEditorTextStyle): void 908 909设置用户预设的样式。 910 911**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 912 913**系统能力:** SystemCapability.ArkUI.ArkUI.Full 914 915**参数:** 916 917| 参数名 | 类型 | 必填 | 说明 | 918| ----- | ---------------------------------------- | ---- | ----- | 919| value | [RichEditorTextStyle](#richeditortextstyle) | 是 | 预设样式。 | 920 921### setSelection<sup>11+</sup> 922 923setSelection(selectionStart: number, selectionEnd: number, options?: SelectionOptions): void 924 925支持设置组件内的内容选中,选中部分背板高亮。 926 927selectionStart和selectionEnd均为-1时表示全选。 928 929未获焦时调用该接口不产生选中效果。 930 931从API version 12开始,在2in1设备中,无论options取何值,调用setSelection接口都不会弹出菜单,此外,如果组件中已经存在菜单,调用setSelection接口会关闭菜单。 932 933在非2in1设备中,options取值为MenuPolicy.DEFAULT时,遵循以下规则: 934 9351. 组件内有手柄菜单时,接口调用后不关闭菜单,并且调整菜单位置。 936 9372. 组件内有不带手柄的菜单时,接口调用后不关闭菜单,并且菜单位置不变。 938 9393. 组件内无菜单时,接口调用后也无菜单显示。 940 941**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 942 943**系统能力:** SystemCapability.ArkUI.ArkUI.Full 944 945**参数:** 946 947| 参数名 | 类型 | 必填 | 说明 | 948| -------------- | ------ | ---- | ------- | 949| selectionStart | number | 是 | 选中开始位置。 | 950| selectionEnd | number | 是 | 选中结束位置。 | 951| options<sup>12+</sup> | [SelectionOptions](ts-types.md#selectionoptions12对象说明) | 否 | 选择项配置。 | 952 953### isEditing<sup>12+</sup> 954 955isEditing(): boolean 956 957获取当前富文本的编辑状态。 958 959**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 960 961**系统能力:** SystemCapability.ArkUI.ArkUI.Full 962 963**返回值:** 964 965| 类型 | 说明 | 966| ------- | ----------------------------- | 967| boolean | true为编辑态,false为非编辑态。 | 968 969### stopEditing<sup>12+</sup> 970 971stopEditing(): void 972 973退出编辑态。 974 975**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 976 977**系统能力:** SystemCapability.ArkUI.ArkUI.Full 978 979### getLayoutManager<sup>12+</sup> 980 981getLayoutManager(): LayoutManager 982 983获取布局管理器对象。 984 985**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 986 987**系统能力:** SystemCapability.ArkUI.ArkUI.Full 988 989**返回值:** 990 991| 类型 | 说明 | 992| ---------------------------------------- | ------- | 993| [LayoutManager](ts-text-common.md#LayoutManager12) | 布局管理器对象。 | 994 995### getPreviewText<sup>12+</sup> 996 997getPreviewText(): PreviewText 998 999获取预上屏信息。 1000 1001**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1002 1003**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1004 1005**返回值:** 1006 1007| 类型 | 说明 | 1008| ---------------------------------------- | ------- | 1009| [PreviewText](ts-text-common.md#previewtext12) | 预上屏信息。 | 1010 1011## RichEditorController 1012 1013RichEditor组件的控制器,继承自[RichEditorBaseController](#richeditorbasecontroller12)。 1014 1015### 导入对象 1016 1017``` 1018controller: RichEditorController = new RichEditorController() 1019``` 1020 1021### addTextSpan 1022 1023addTextSpan(value: string, options?: RichEditorTextSpanOptions): number 1024 1025添加文本内容,如果组件光标闪烁,插入后光标位置更新为新插入文本的后面。 1026 1027**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1028 1029**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1030 1031**参数:** 1032 1033| 参数名 | 类型 | 必填 | 说明 | 1034| ------- | ---------------------------------------- | ---- | ----- | 1035| value | string | 是 | 文本内容。 | 1036| options | [RichEditorTextSpanOptions](#richeditortextspanoptions) | 否 | 文本选项。 | 1037 1038**返回值:** 1039 1040| 类型 | 说明 | 1041| ------ | -------------------- | 1042| number | 添加完成的TextSpan所在的位置。 | 1043 1044### addImageSpan 1045 1046addImageSpan(value: PixelMap | ResourceStr, options?: RichEditorImageSpanOptions): number 1047 1048添加图片内容,如果组件光标闪烁,插入后光标位置更新为新插入图片的后面。 1049 1050不建议直接添加网络图片。 1051 1052**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1053 1054**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1055 1056**参数:** 1057 1058| 参数名 | 类型 | 必填 | 说明 | 1059| ------- | ---------------------------------------- | ---- | ----- | 1060| value | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7)\|[ResourceStr](ts-types.md#resourcestr) | 是 | 图片内容。 | 1061| options | [RichEditorImageSpanOptions](#richeditorimagespanoptions) | 否 | 图片选项。 | 1062 1063**返回值:** 1064 1065| 类型 | 说明 | 1066| ------ | -------------------- | 1067| number | 添加完成的ImageSpan所在的位置。 | 1068 1069### addBuilderSpan<sup>11+</sup> 1070 1071addBuilderSpan(value: CustomBuilder, options?: RichEditorBuilderSpanOptions): number 1072 1073添加用户自定义布局Span。 1074 1075> **说明:** 1076> 1077> - RichEditor组件添加占位Span,占位Span调用系统的measure方法计算真实的长宽和位置。 1078> - 可通过[RichEditorBuilderSpanOptions](#richeditorbuilderspanoptions11)设置此builder在RichEditor中的index(一个文字为一个单位)。 1079> - 此占位Span不可获焦,支持拖拽,支持部分通用属性,占位、删除等能力等同于ImageSpan,长度视为一个文字。 1080> - 不支持通过[bindSelectionMenu](#bindselectionmenu)设置自定义菜单。 1081> - 不支持通过[getSpans](#getspans),[getSelection](#getselection11),[onSelect](#onselect),[aboutToDelete](#abouttodelete)获取builderSpan信息。 1082> - 不支持通过[updateSpanStyle](#updatespanstyle),[updateParagraphStyle](#updateparagraphstyle11)等方式更新builder。 1083> - 对此builder节点进行复制或粘贴不生效。 1084> - builder的布局约束由RichEditor传入,如果builder里最外层组件不设置大小,则会用RichEditor的大小作为maxSize。 1085> - builder的手势相关事件机制与通用手势事件相同,如果builder中未设置透传,则仅有builder中的子组件响应。 1086> - 如果组件光标闪烁,插入后光标位置更新为新插入builder的后面。 1087 1088通用属性仅支持[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)、 1089[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#clip)、[mask](ts-universal-attributes-sharp-clipping.md#mask)、[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)。 1090 1091**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1092 1093**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1094 1095**参数:** 1096 1097| 参数名 | 类型 | 必填 | 说明 | 1098| ------- | ---------------------------------------- | ---- | ---------- | 1099| value | [CustomBuilder](ts-types.md#custombuilder8) | 是 | 自定义组件。 | 1100| options | [RichEditorBuilderSpanOptions](#richeditorbuilderspanoptions11) | 否 | builder选项。 | 1101 1102**返回值:** 1103 1104| 类型 | 说明 | 1105| ------ | ---------------------- | 1106| number | 添加完成的builderSpan所在的位置。 | 1107 1108### addSymbolSpan<sup>11+</sup> 1109 1110addSymbolSpan(value: Resource, options?: RichEditorSymbolSpanOptions ): number 1111 1112在Richeditor中添加SymbolSpan,如果组件光标闪烁,插入后光标位置更新为新插入Symbol的后面。 1113 1114暂不支持手势、复制、拖拽处理。 1115 1116**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1117 1118**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1119 1120**参数:** 1121 1122| 参数名 | 类型 | 必填 | 说明 | 1123| ------- | ---------------------------------------- | ---- | ----- | 1124| value | [Resource](ts-types.md#resource) | 是 | 组件内容。 | 1125| options | [RichEditorSymbolSpanOptions](#richeditorsymbolspanoptions11) | 否 | 组件选项。 | 1126 1127**返回值:** 1128 1129| 类型 | 说明 | 1130| ------ | --------------------- | 1131| number | 添加完成的SymbolSpan所在的位置。 | 1132 1133### updateSpanStyle 1134 1135updateSpanStyle(value: RichEditorUpdateTextSpanStyleOptions | RichEditorUpdateImageSpanStyleOptions | RichEditorUpdateSymbolSpanStyleOptions): void 1136 1137更新文本、图片或SymbolSpan样式。<br/>若只更新了一个Span的部分内容,则会根据更新部分、未更新部分将该Span拆分为多个Span。 1138 1139使用该接口更新文本、图片或SymbolSpan样式时默认不会关闭自定义文本选择菜单。 1140 1141**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1142 1143**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1144 1145**参数:** 1146 1147| 参数名 | 类型 | 必填 | 说明 | 1148| ------ | -------- | ---- | -------------------------------------- | 1149| value | [RichEditorUpdateTextSpanStyleOptions](#richeditorupdatetextspanstyleoptions) \| [RichEditorUpdateImageSpanStyleOptions](#richeditorupdateimagespanstyleoptions) \| [RichEditorUpdateSymbolSpanStyleOptions](#richeditorupdatesymbolspanstyleoptions11) | 是 | 文本、图片或SymbolSpan的样式选项信息。 | 1150 1151> **说明:** 1152> 1153> 当start大于end时为异常情况,此时start为0,end为无穷大。 1154 1155### updateParagraphStyle<sup>11+</sup> 1156 1157updateParagraphStyle(value: RichEditorParagraphStyleOptions): void 1158 1159更新段落的样式。 1160 1161**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1162 1163**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1164 1165**参数:** 1166 1167| 参数名 | 类型 | 必填 | 说明 | 1168| ----- | ---------------------------------------- | ---- | ---------- | 1169| value | [RichEditorParagraphStyleOptions](#richeditorparagraphstyleoptions11) | 是 | 段落的样式选项信息。 | 1170 1171### getSpans 1172 1173getSpans(value?: RichEditorRange): Array<RichEditorImageSpanResult| RichEditorTextSpanResult> 1174 1175获取span信息。 1176 1177**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1178 1179**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1180 1181**参数:** 1182 1183| 参数名 | 类型 | 必填 | 说明 | 1184| ----- | ----------------------------------- | ---- | ----------- | 1185| value | [RichEditorRange](#richeditorrange) | 否 | 需要获取span范围。 | 1186 1187**返回值:** 1188 1189| 类型 | 说明 | 1190| ---------------------------------------- | ------------ | 1191| Array<[RichEditorTextSpanResult](#richeditortextspanresult) \| [RichEditorImageSpanResult](#richeditorimagespanresult)> | 文本和图片Span信息。 | 1192 1193### deleteSpans 1194 1195deleteSpans(value?: RichEditorRange): void 1196 1197删除指定范围内的文本和图片。 1198 1199**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1200 1201**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1202 1203**参数:** 1204 1205| 参数名 | 类型 | 必填 | 说明 | 1206| ----- | ----------------------------------- | ---- | ------------------- | 1207| value | [RichEditorRange](#richeditorrange) | 否 | 删除范围。省略时,删除所有文本和图片。 | 1208 1209### getParagraphs<sup>11+</sup> 1210 1211getParagraphs(value?: RichEditorRange): Array\<RichEditorParagraphResult> 1212 1213获得指定返回的段落。 1214 1215**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1216 1217**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1218 1219**参数:** 1220 1221| 参数名 | 类型 | 必填 | 说明 | 1222| ----- | ----------------------------------- | ---- | ---------- | 1223| value | [RichEditorRange](#richeditorrange) | 否 | 需要获取段落的范围。 | 1224 1225**返回值:** 1226 1227| 类型 | 说明 | 1228| ---------------------------------------- | -------- | 1229| Array\<[RichEditorParagraphResult](#richeditorparagraphresult11)> | 选中段落的信息。 | 1230 1231### getSelection<sup>11+</sup> 1232 1233getSelection(): RichEditorSelection 1234 1235获取选中内容。如果未选中内容,返回光标所在span信息。 1236 1237**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1238 1239**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1240 1241**返回值:** 1242 1243| 类型 | 说明 | 1244| ---------------------------------------- | ------- | 1245| [RichEditorSelection](#richeditorselection) | 选中内容信息。 | 1246 1247### fromStyledString<sup>12+</sup> 1248 1249fromStyledString(value: StyledString): Array\<RichEditorSpan> 1250 1251将属性字符串转换成span信息。 1252 1253**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1254 1255**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1256 1257**参数:** 1258 1259| 参数名 | 类型 | 必填 | 说明 | 1260| ----- | ----------------------------------- | ---- | ---------- | 1261| value | [StyledString](ts-universal-styled-string.md#styledstring) | 是 | 转换前的属性字符串。 | 1262 1263**返回值:** 1264 1265| 类型 | 说明 | 1266| ---------------------------------------- | ------- | 1267| Array<[RichEditorSpan](#richeditorspan12)> | 文本和图片Span信息。 | 1268 1269**错误码:** 1270 1271以下错误码详细介绍请参考[通用错误码](../../errorcode-universal.md)。 1272 1273| 错误码ID | 错误信息 | 1274| -------- | ------------------------------ | 1275| 401 | The parameter check failed. | 1276 1277### toStyledString<sup>12+</sup> 1278 1279toStyledString(value: RichEditorRange): StyledString 1280 1281将给定范围的组件内容转换成属性字符串。 1282 1283**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1284 1285**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1286 1287**参数:** 1288 1289| 参数名 | 类型 | 必填 | 说明 | 1290| ----- | ----------------------------------- | ---- | ---------- | 1291| value | [RichEditorRange](#richeditorrange) | 是 | 需要获取的范围。 | 1292 1293**返回值:** 1294 1295| 类型 | 说明 | 1296| ---------------------------------------- | -------- | 1297| [StyledString](ts-universal-styled-string.md#styledstring) | 转换后的属性字符串 | 1298 1299**错误码:** 1300 1301以下错误码详细介绍请参考[通用错误码](../../errorcode-universal.md)。 1302 1303| 错误码ID | 错误信息 | 1304| -------- | ------------------------------ | 1305| 401 | The parameter check failed. | 1306 1307## RichEditorStyledStringController<sup>12+</sup> 1308 1309使用属性字符串构建的RichEditor组件的控制器,继承自[RichEditorBaseController](#richeditorbasecontroller12)。 1310 1311### 导入对象 1312 1313``` 1314controller: RichEditorStyledStringController = new RichEditorStyledStringController() 1315``` 1316 1317### getSelection<sup>12+</sup> 1318 1319getSelection(): RichEditorRange 1320 1321获取当前富文本当前的选中区域范围。 1322 1323**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1324 1325**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1326 1327**返回值:** 1328 1329| 类型 | 说明 | 1330| ---------------------------------------- | ------- | 1331| [RichEditorRange](#richeditorrange) | 选中区域范围。 | 1332 1333### setStyledString<sup>12+</sup> 1334 1335setStyledString(styledString: StyledString): void 1336 1337设置富文本组件显示的属性字符串。 1338 1339**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1340 1341**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1342 1343**参数:** 1344 1345| 参数名 | 类型 | 必填 | 说明 | 1346| ----- | ------ | ---- | ------------------- | 1347| styledString | [StyledString](ts-universal-styled-string.md#styledstring) | 是 | 属性字符串。<br/>**说明:** <br/>StyledString的子类[MutableStyledString](ts-universal-styled-string.md#mutablestyledstring)也可以作为入参值。 | 1348 1349### getStyledString<sup>12+</sup> 1350 1351getStyledString(): MutableStyledString; 1352 1353获取富文本组件显示的属性字符串。 1354 1355**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1356 1357**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1358 1359**返回值:** 1360 1361| 类型 | 说明 | 1362| ------- | ----------------------------- | 1363| [MutableStyledString](ts-universal-styled-string.md#mutablestyledstring) | 富文本组件显示的属性字符串 | 1364 1365### onContentChanged<sup>12+</sup> 1366 1367onContentChanged(listener: StyledStringChangedListener): void 1368 1369注册文本内容变化回调,该回调会在后端程序导致文本内容变更时触发 1370 1371**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1372 1373**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1374 1375**参数:** 1376 1377| 参数名 | 类型 | 必填 | 说明 | 1378| ----- | ------ | ---- | ------------------- | 1379| listener | [StyledStringChangedListener](ts-text-common.md#styledstringchangedlistener12) | 是 | 文本内容变化回调监听器。 | 1380 1381## RichEditorSelection 1382 1383选中内容信息。 1384 1385**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1386 1387**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1388 1389| 名称 | 类型 | 必填 | 说明 | 1390| --------- | ---------------------------------------- | ---- | ------- | 1391| selection | [number, number] | 是 | 选中范围。 | 1392| spans | Array<[RichEditorTextSpanResult](#richeditortextspanresult)\| [RichEditorImageSpanResult](#richeditorimagespanresult)> | 是 | span信息。 | 1393 1394## RichEditorRange 1395 1396定义RichEditor的范围。 1397 1398继承自[RichEditorRange](#richeditorrange)。 1399 1400**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1401 1402**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1403 1404| 名称 | 类型 | 必填 | 说明 | 1405| ----- | ------ | ---- | ------------------------------------------------------------ | 1406| start | number | 否 | 需要更新样式的文本起始位置,省略或者设置负值时表示从0开始。 | 1407| end | number | 否 | 需要更新样式的文本结束位置,省略或者超出文本范围时表示无穷大。 | 1408 1409 1410## RichEditorSpanStyleOptions 1411 1412文本样式选项。 1413 1414继承自[RichEditorRange](#richeditorrange)。 1415 1416**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1417 1418**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1419 1420## RichEditorUpdateTextSpanStyleOptions 1421 1422文本样式选项。 1423 1424继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1425 1426**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1427 1428**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1429 1430| 名称 | 类型 | 必填 | 说明 | 1431| --------- | ------------------------------------------- | ---- | ---------- | 1432| textStyle | [RichEditorTextStyle](#richeditortextstyle) | 是 | 文本样式。 | 1433 1434## RichEditorUpdateImageSpanStyleOptions 1435 1436图片样式选项。 1437 1438继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1439 1440**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1441 1442**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1443 1444| 名称 | 类型 | 必填 | 说明 | 1445| ---------- | ---------------------------------------- | ---- | ------------------------------- | 1446| imageStyle | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | 是 | 图片样式。 | 1447 1448## RichEditorUpdateSymbolSpanStyleOptions<sup>11+</sup> 1449 1450SymbolSpan样式选项。 1451 1452继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1453 1454**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1455 1456**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1457 1458| 名称 | 类型 | 必填 | 说明 | 1459| ----------- | --------------------------------------------------------- | ---- | ---------- | 1460| symbolStyle | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | 是 | 组件样式。 | 1461 1462## RichEditorParagraphStyleOptions<sup>11+</sup> 1463 1464段落样式选项。 1465 1466继承自[RichEditorSpanStyleOptions](#richeditorspanstyleoptions)。 1467 1468**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1469 1470**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1471 1472| 名称 | 类型 | 必填 | 说明 | 1473| ----- | ---------------------------------------- | ---- | ---------------------------------- | 1474| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 是 | 段落样式。 | 1475 1476> **说明:** 1477> 1478> 接口作用的范围:设定的区间所涉及的段落。 1479 1480## RichEditorParagraphStyle<sup>11+</sup> 1481 1482段落样式。 1483 1484**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1485 1486**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1487 1488| 名称 | 类型 | 必填 | 说明 | 1489| ------------- | ---------------------------------------- | ---- | ------------------ | 1490| textAlign | [TextAlign](ts-appendix-enums.md#textalign) | 否 | 设置文本段落在水平方向的对齐方式。默认值:TextAlign.START <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1491| leadingMargin | [Dimension](ts-types.md#dimension10) \| [LeadingMarginPlaceholder](#leadingmarginplaceholder11) | 否 | 设置文本段落缩进,当段落仅存在ImageSpan或BuilderSpan时,此属性值不生效。参数为Dimension类型时,不支持以Percentage形式设置。默认值:{"size":["0.00px","0.00px"]} <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1492| wordBreak<sup>12+</sup> | [WordBreak](ts-appendix-enums.md#wordbreak11) | 否 | 设置断行规则。 <br />默认值:WordBreak.BREAK_WORD | 1493| lineBreakStrategy<sup>12+</sup> | [LineBreakStrategy](ts-appendix-enums.md#linebreakstrategy12) | 否 | 设置折行规则。 <br />默认值:LineBreakStrategy.GREEDY<br />在wordBreak不等于breakAll的时候生效,不支持连字符。 | 1494 1495## LeadingMarginPlaceholder<sup>11+</sup> 1496 1497前导边距占位符,用于表示文本段落左侧与组件边缘之间的距离。 1498 1499**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1500 1501| 名称 | 类型 | 必填 | 说明 | 1502| -------- | ---------------------------------------- | ---- | -------------- | 1503| pixelMap | [PixelMap](../../apis-image-kit/js-apis-image.md#pixelmap7) | 是 | 图片内容。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1504| size | \[[Dimension](ts-types.md#dimension10), [Dimension](ts-types.md#dimension10)\] | 是 | 图片大小,不支持设置百分比。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 1505 1506## RichEditorParagraphResult<sup>11+</sup> 1507 1508后端返回的段落信息。 1509 1510**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1511 1512**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1513 1514| 名称 | 类型 | 必填 | 说明 | 1515| ----- | ---------------------------------------- | ---- | ------- | 1516| style | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 是 | 段落样式。 | 1517| range | \[number, number\] | 是 | 段落起始和结束位置。 | 1518 1519## RichEditorTextSpanOptions 1520 1521添加文本的偏移位置和文本样式信息。 1522 1523**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1524 1525| 名称 | 类型 | 必填 | 说明 | 1526| ---------------------------- | ---------------------------------------- | ---- | -------------------------- | 1527| offset | number | 否 | 添加文本的位置。省略时,添加到所有内容的最后。<br/>当值小于0时,放在所有内容最前面;当值大于所有内容长度时,放在所有内容最后面。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1528| style | [RichEditorTextStyle](#richeditortextstyle) | 否 | 文本样式信息。省略时,使用系统默认文本信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1529| paragraphStyle<sup>11+</sup> | [RichEditorParagraphStyle](#richeditorparagraphstyle11) | 否 | 段落样式。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 1530| gesture<sup>11+</sup> | [RichEditorGesture](#richeditorgesture11) | 否 | 行为触发回调。省略时,仅使用系统默认行为。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1531 1532## RichEditorTextStyle 1533 1534文本样式信息。 1535 1536**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1537 1538| 名称 | 类型 | 必填 | 说明 | 1539| ------------------------ | ---------------------------------------- | ---- | ---------------------------------------- | 1540| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 文本颜色。<br/> 默认值:$r('sys.color.font_primary')。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1541| fontSize | [Length](ts-types.md#length) \| number | 否 | 设置字体大小,Length为number类型时,使用fp单位。字体默认大小16。不支持设置百分比字符串。字体大小设置为0时,显示默认字体大小。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1542| fontStyle | [FontStyle](ts-appendix-enums.md#fontstyle) | 否 | 字体样式。<br/>默认值:FontStyle.Normal。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1543| 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开始,该接口支持在原子化服务中使用。| 1544| fontFamily | [ResourceStr](ts-types.md#resourcestr) | 否 | 设置字体列表。默认字体'HarmonyOS Sans',当前支持'HarmonyOS Sans'字体和[注册自定义字体](../js-apis-font.md)。 <br/>默认字体:'HarmonyOS Sans'。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1545| decoration | [DecorationStyleInterface](ts-universal-styled-string.md#decorationstyleinterface对象说明) | 否 | 设置文本装饰线样式及其颜色。<br/>type默认值:TextDecorationType.None。<br/>color默认值:跟随字体颜色。<br/>style默认值:TextDecorationStyle.SOLID。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1546| 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开始,该接口支持在原子化服务中使用。| 1547| lineHeight<sup>12+</sup> | number \| string \| [Resource](ts-types.md#resource) | 否 |设置文本的文本行高,设置值不大于0时,不限制文本行高,自适应字体大小,number类型时单位为fp,不支持设置百分比字符串。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1548| letterSpacing<sup>12+</sup> | number \| string | 否 | 设置文本字符间距,当取值为负值时,文字会发生压缩,负值过小时会将组件内容区大小压缩为0,导致无内容显示,number类型时单位为fp, 不支持设置百分比字符串。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1549| 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开始,该接口支持在原子化服务中使用。| 1550 1551## PlaceholderStyle<sup>12+</sup> 1552 1553添加提示文本的字体样式。 1554 1555**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1556 1557**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1558 1559| 名称 | 类型 | 必填 | 说明 | 1560| ---------------------------- | ---------------------------------------- | ---- | -------------------------- | 1561| font | [Font](ts-types.md#font) | 否 | 设置placeholder文本样式。<br/>默认值跟随主题。| 1562| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置placeholder文本颜色。<br/>默认值跟随主题。| 1563 1564## RichEditorImageSpanOptions 1565 1566添加图片的偏移位置和图片样式信息。 1567 1568**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1569 1570| 名称 | 类型 | 必填 | 说明 | 1571| --------------------- | ---------------------------------------- | ---- | -------------------------- | 1572| offset | number | 否 | 添加图片的位置。省略时,添加到所有内容的最后。<br/>当值小于0时,放在所有内容最前面;当值大于所有内容长度时,放在所有内容最后面。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1573| imageStyle | [RichEditorImageSpanStyle](#richeditorimagespanstyle) | 否 | 图片样式信息。省略时,使用系统默认图片信息。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1574| gesture<sup>11+</sup> | [RichEditorGesture](#richeditorgesture11) | 否 | 行为触发回调。省略时,仅使用系统默认行为。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。| 1575 1576## RichEditorImageSpanStyle 1577 1578图片样式。 1579 1580**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1581 1582| 名称 | 类型 | 必填 | 说明 | 1583| ------------------------- | ---------------------------------------- | ---- | ---------------------------------------- | 1584| size | [[Dimension](ts-types.md#dimension10), [Dimension](ts-types.md#dimension10)] | 否 | 图片宽度和高度。默认值:size的默认值与objectFit的值有关,不同的objectFit值对应的size默认值也不同。objectFit的值为Cover时,图片高度为组件高度减去组件上下内边距,图片宽度为组件宽度减去组件左右内边距。不支持以Percentage形式设置。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1585| verticalAlign | [ImageSpanAlignment](ts-basic-components-imagespan.md#imagespanalignment) | 否 | 图片垂直对齐方式。<br/>默认值:ImageSpanAlignment.BOTTOM <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。| 1586| objectFit | [ImageFit](ts-appendix-enums.md#imagefit) | 否 | 图片缩放类型。<br/> 默认值:ImageFit.Cover。 <br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1587| layoutStyle<sup>11+</sup> | [RichEditorLayoutStyle](#richeditorlayoutstyle11) | 否 | 图片布局风格。默认值:{"borderRadius":"","margin":""}<br/> <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 1588 1589## RichEditorSymbolSpanOptions<sup>11+</sup> 1590 1591添加SymbolSpan组件的偏移位置和SymbolSpan组件样式信息。 1592 1593**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1594 1595**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1596 1597| 名称 | 类型 | 必填 | 说明 | 1598| ------ | ---------------------------------------- | ---- | -------------------------- | 1599| offset | number | 否 | 添加组件的位置。省略时,添加到所有内容的最后。<br/>当值小于0时,放在所有内容最前面;当值大于所有内容长度时,放在所有内容最后面。 | 1600| style | [RichEditorSymbolSpanStyle](#richeditorsymbolspanstyle11) | 否 | 组件样式信息。省略时,使用系统默认样式信息。 | 1601 1602## RichEditorSymbolSpanStyle<sup>11+</sup> 1603 1604组件SymbolSpan样式信息。 1605 1606**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1607 1608**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1609 1610| 名称 | 类型 | 必填 | 说明 | 1611| ------ | -------- | ---- | -------------------------------------- | 1612| fontColor | Array\<[ResourceColor](ts-types.md#resourcecolor)\> | 否 | 设置SymbolSpan组件颜色。<br/> 默认值:不同渲染策略下默认值不同。 | 1613| fontSize | number \| string \| [Resource](ts-types.md#resource) | 否 | 设置SymbolSpan组件大小,默认单位为fp。<br/>默认值:跟随主题。 | 1614| 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。 | 1615| renderingStrategy | [SymbolRenderingStrategy](ts-basic-components-symbolGlyph.md#symbolrenderingstrategy11枚举说明) | 否 | 设置SymbolSpan组件渲染策略。<br/>默认值:SymbolRenderingStrategy.SINGLE。 | 1616| effectStrategy | [SymbolEffectStrategy](ts-basic-components-symbolGlyph.md#symboleffectstrategy11枚举说明) | 否 | 设置SymbolSpan组件动效策略。<br/>默认值:SymbolEffectStrategy.NONE。 | 1617 1618## RichEditorBuilderSpanOptions<sup>11+</sup> 1619 1620添加图片的偏移位置和图片样式信息。 1621 1622**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1623 1624**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1625 1626| 名称 | 类型 | 必填 | 说明 | 1627| ------ | ------ | ---- | ------------------------------------- | 1628| offset | number | 否 | 添加builder的位置。省略或者为异常值时,添加到所有内容的最后。 | 1629 1630## RichEditorSpan<sup>12+</sup> 1631 1632type RichEditorSpan = RichEditorImageSpanResult | RichEditorTextSpanResult 1633 1634RichEditor span信息。 1635 1636**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1637 1638**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1639 1640| 类型 | 说明 | 1641| ------ | ---------- | 1642| [RichEditorImageSpanResult](#richeditorimagespanresult) | 后端返回的图片信息。 | 1643| [RichEditorTextSpanResult](#richeditortextspanresult) | 后端返回的文本样式信息。 | 1644 1645## SelectionMenuOptions<sup>10+</sup> 1646 1647菜单的选项。 1648 1649**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1650 1651| 名称 | 类型 | 必填 | 说明 | 1652| ----------- | ---------- | ---- | ------------- | 1653| onAppear | [MenuOnAppearCallback](#menuonappearcallback12) | 否 | 自定义选择菜单弹出时回调。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1654| onDisappear | Callback\<void\> | 否 | 自定义选择菜单关闭时回调。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 | 1655| menuType<sup>13+</sup> | [MenuType](ts-text-common.md#menutype13枚举说明) | 否 | 自定义选择菜单类型。<br/>**原子化服务API:** 从API version 13开始,该接口支持在原子化服务中使用。 | 1656 1657## PasteEvent<sup>11+</sup> 1658 1659定义用户粘贴事件。 1660 1661**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 1662 1663**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1664 1665| 名称 | 类型 | 必填 | 说明 | 1666| -------------- | ----------- | ---- | ----------------------------- | 1667| preventDefault | Callback\<void\> | 否 | 阻止系统默认粘贴事件。 | 1668 1669## CutEvent<sup>12+</sup> 1670 1671定义用户剪切事件。 1672 1673**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1674 1675**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1676 1677| 名称 | 类型 | 必填 | 说明 | 1678| -------------- | ----------- | ---- | ----------------------------- | 1679| preventDefault | Callback\<void\> | 否 | 阻止系统默认剪切事件。 | 1680 1681## CopyEvent<sup>12+</sup> 1682 1683定义用户拷贝事件。 1684 1685**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1686 1687**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1688 1689| 名称 | 类型 | 必填 | 说明 | 1690| -------------- | ----------- | ---- | ----------------------------- | 1691| preventDefault | Callback\<void\> | 否 | 阻止系统默认拷贝事件。 | 1692 1693## RichEditorGesture<sup>11+</sup> 1694 1695用户行为回调。 1696 1697**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1698 1699**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1700 1701| 名称 | 类型 | 必填 | 说明 | 1702| ----------- | ---------- | ---- | ------------- | 1703| onClick | Callback\<[ClickEvent](ts-universal-events-click.md#clickevent对象说明)\> | 否 | [ClickEvent](ts-universal-events-click.md#clickevent对象说明)为用户点击事件。<br/>点击完成时回调事件。<br/>双击时,第一次点击触发回调事件。| 1704| onLongPress | Callback\<[GestureEvent](ts-gesture-settings.md#gestureevent对象说明)\> | 否 | [GestureEvent](ts-gesture-settings.md#gestureevent对象说明)为用户长按事件。<br/>长按完成时回调事件。 | 1705 1706## KeyboardOptions<sup>12+</sup> 1707 1708设置自定义键盘是否支持避让功能。 1709 1710**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1711 1712**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1713 1714| 名称 | 类型 | 必填 | 说明 | 1715| --------------- | --------------- |---- | ------------------------------------ | 1716| supportAvoidance | boolean | 否 | 设置自定义键盘是否支持避让功能;默认值为false不支持避让,true为支持避让。 | 1717 1718## SubmitCallback<sup>12+</sup> 1719 1720type SubmitCallback = (enterKey: EnterKeyType, event: SubmitEvent) => void 1721 1722软键盘按下回车键时的回调事件。 1723 1724**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1725 1726**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1727 1728**参数:** 1729 1730| 参数名 | 类型 | 必填 | 说明 | 1731| -------- | ------------------------------------------------------------ | ---- | -------------------------------------------------------- | 1732| enterKey | [EnterKeyType](ts-types.md#enterkeytype枚举说明) | 是 | 软键盘输入法回车键类型。具体类型见EnterKeyType枚举说明。 | 1733| event | [SubmitEvent](ts-basic-components-textinput.md#submitevent11对象说明) | 是 | 当提交的时候,提供保持RichEditor编辑状态的方法。 | 1734 1735## MenuOnAppearCallback<sup>12+</sup> 1736 1737type MenuOnAppearCallback = (start: number, end: number) => void 1738 1739自定义选择菜单弹出时触发的回调事件。 1740 1741**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1742 1743**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1744 1745**参数:** 1746 1747| 参数名 | 类型 | 必填 | 说明 | 1748| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- | 1749| start | number | 是 | 选中内容的起始位置。 | 1750| end | number | 是 | 选中内容的终止位置。 | 1751 1752## PasteEventCallback<sup>12+</sup> 1753 1754type PasteEventCallback = (event?: PasteEvent) => void 1755 1756完成粘贴前,触发回调。 1757 1758**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 1759 1760type PasteEventCallback = (event?: PasteEvent) => void 1761 1762**系统能力:** SystemCapability.ArkUI.ArkUI.Full 1763 1764**参数:** 1765 1766| 参数名 | 类型 | 必填 | 说明 | 1767| -------- | ------------------------------------------------ | ---- | -------------------------------------------------------- | 1768| event | [PasteEvent](#pasteevent11) | 否 | 定义用户粘贴事件。 | 1769 1770## 示例 1771 1772### 示例1 1773 1774```ts 1775// xxx.ets 1776@Entry 1777@Component 1778struct Index { 1779 controller: RichEditorController = new RichEditorController(); 1780 options: RichEditorOptions = { controller: this.controller }; 1781 private start: number = -1; 1782 private end: number = -1; 1783 @State message: string = "[-1, -1]" 1784 @State content: string = "" 1785 1786 build() { 1787 Column() { 1788 Column() { 1789 Text("selection range:").width("100%") 1790 Text() { 1791 Span(this.message) 1792 }.width("100%") 1793 Text("selection content:").width("100%") 1794 Text() { 1795 Span(this.content) 1796 }.width("100%") 1797 } 1798 .borderWidth(1) 1799 .borderColor(Color.Red) 1800 .width("100%") 1801 .height("20%") 1802 1803 Row() { 1804 Button("更新样式:加粗").onClick(() => { 1805 this.controller.updateSpanStyle({ 1806 start: this.start, 1807 end: this.end, 1808 textStyle: 1809 { 1810 fontWeight: FontWeight.Bolder 1811 } 1812 }) 1813 }) 1814 Button("获取选择内容").onClick(() => { 1815 this.content = ""; 1816 this.controller.getSpans({ 1817 start: this.start, 1818 end: this.end 1819 }).forEach(item => { 1820 if(typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined'){ 1821 this.content += (item as RichEditorImageSpanResult).valueResourceStr; 1822 this.content += "\n" 1823 } else { 1824 if(typeof(item as RichEditorTextSpanResult)['symbolSpanStyle'] != 'undefined') { 1825 this.content += (item as RichEditorTextSpanResult).symbolSpanStyle?.fontSize; 1826 this.content += "\n" 1827 }else { 1828 this.content += (item as RichEditorTextSpanResult).value; 1829 this.content += "\n" 1830 } 1831 } 1832 }) 1833 }) 1834 Button("删除选择内容").onClick(() => { 1835 this.controller.deleteSpans({ 1836 start: this.start, 1837 end: this.end 1838 }) 1839 this.start = -1; 1840 this.end = -1; 1841 this.message = "[" + this.start + ", " + this.end + "]" 1842 }) 1843 } 1844 .borderWidth(1) 1845 .borderColor(Color.Red) 1846 .width("100%") 1847 .height("10%") 1848 1849 Column() { 1850 RichEditor(this.options) 1851 .onReady(() => { 1852 this.controller.addTextSpan("012345", 1853 { 1854 style: 1855 { 1856 fontColor: Color.Orange, 1857 fontSize: 30 1858 } 1859 }) 1860 this.controller.addSymbolSpan($r("sys.symbol.ohos_trash"), 1861 { 1862 style: 1863 { 1864 fontSize: 30 1865 } 1866 }) 1867 this.controller.addImageSpan($r("app.media.icon"), 1868 { 1869 imageStyle: 1870 { 1871 size: ["57px", "57px"] 1872 } 1873 }) 1874 this.controller.addTextSpan("56789", 1875 { 1876 style: 1877 { 1878 fontColor: Color.Black, 1879 fontSize: 30 1880 } 1881 }) 1882 }) 1883 .onSelect((value: RichEditorSelection) => { 1884 this.start = value.selection[0]; 1885 this.end = value.selection[1]; 1886 this.message = "[" + this.start + ", " + this.end + "]" 1887 }) 1888 .aboutToIMEInput((value: RichEditorInsertValue) => { 1889 console.log("---------------------- aboutToIMEInput ----------------------") 1890 console.log("insertOffset:" + value.insertOffset) 1891 console.log("insertValue:" + value.insertValue) 1892 return true; 1893 }) 1894 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 1895 console.log("---------------------- onIMEInputComplete ---------------------") 1896 console.log("spanIndex:" + value.spanPosition.spanIndex) 1897 console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]") 1898 console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]") 1899 console.log("value:" + value.value) 1900 }) 1901 .aboutToDelete((value: RichEditorDeleteValue) => { 1902 console.log("---------------------- aboutToDelete --------------------------") 1903 console.log("offset:" + value.offset) 1904 console.log("direction:" + value.direction) 1905 console.log("length:" + value.length) 1906 value.richEditorDeleteSpans.forEach(item => { 1907 console.log("---------------------- item --------------------------") 1908 console.log("spanIndex:" + item.spanPosition.spanIndex) 1909 console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]") 1910 console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]") 1911 if (typeof(item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 1912 console.log("image:" + (item as RichEditorImageSpanResult).valueResourceStr) 1913 } else { 1914 console.log("text:" + (item as RichEditorTextSpanResult).value) 1915 } 1916 }) 1917 return true; 1918 }) 1919 .onDeleteComplete(() => { 1920 console.log("---------------------- onDeleteComplete ------------------------") 1921 }) 1922 .placeholder("input...", { 1923 fontColor: Color.Gray, 1924 font: { 1925 size: 16, 1926 weight: FontWeight.Normal, 1927 family: "HarmonyOS Sans", 1928 style: FontStyle.Normal 1929 } 1930 }) 1931 .borderWidth(1) 1932 .borderColor(Color.Green) 1933 .width("100%") 1934 .height("30%") 1935 } 1936 .borderWidth(1) 1937 .borderColor(Color.Red) 1938 .width("100%") 1939 .height("70%") 1940 } 1941 } 1942} 1943``` 1944 1945 1946### 示例2 1947 1948```ts 1949// xxx.ets 1950@Entry 1951@Component 1952struct RichEditorExample { 1953 controller: RichEditorController = new RichEditorController() 1954 1955 // 自定义键盘组件 1956 @Builder CustomKeyboardBuilder() { 1957 Column() { 1958 Grid() { 1959 ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => { 1960 GridItem() { 1961 Button(item + "") 1962 .width(110).onClick(() => { 1963 this.controller.addTextSpan(item + '', { 1964 offset: this.controller.getCaretOffset(), 1965 style: 1966 { 1967 fontColor: Color.Orange, 1968 fontSize: 30 1969 } 1970 }) 1971 this.controller.setCaretOffset(this.controller.getCaretOffset() + item.toString().length) 1972 }) 1973 } 1974 }) 1975 }.maxCount(3).columnsGap(10).rowsGap(10).padding(5) 1976 }.backgroundColor(Color.Gray) 1977 } 1978 1979 build() { 1980 Column() { 1981 RichEditor({ controller: this.controller }) 1982 // 绑定自定义键盘 1983 .customKeyboard(this.CustomKeyboardBuilder()).margin(10).border({ width: 1 }) 1984 .height(200) 1985 .borderWidth(1) 1986 .borderColor(Color.Red) 1987 .width("100%") 1988 } 1989 } 1990} 1991``` 1992 1993 1994 1995### 示例3 1996 1997```ts 1998// xxx.ets 1999import { BusinessError, pasteboard } from '@kit.BasicServicesKit'; 2000 2001export interface SelectionMenuTheme { 2002 imageSize: number; 2003 buttonSize: number; 2004 menuSpacing: number; 2005 editorOptionMargin: number; 2006 expandedOptionPadding: number; 2007 defaultMenuWidth: number; 2008 imageFillColor: Resource; 2009 backGroundColor: Resource; 2010 iconBorderRadius: Resource; 2011 containerBorderRadius: Resource; 2012 cutIcon: Resource; 2013 copyIcon: Resource; 2014 pasteIcon: Resource; 2015 selectAllIcon: Resource; 2016 shareIcon: Resource; 2017 translateIcon: Resource; 2018 searchIcon: Resource; 2019 arrowDownIcon: Resource; 2020 iconPanelShadowStyle: ShadowStyle; 2021 iconFocusBorderColor: Resource; 2022} 2023 2024export const defaultTheme: SelectionMenuTheme = { 2025 imageSize: 24, 2026 buttonSize: 48, 2027 menuSpacing: 8, 2028 editorOptionMargin: 1, 2029 expandedOptionPadding: 3, 2030 defaultMenuWidth: 256, 2031 imageFillColor: $r('sys.color.ohos_id_color_primary'), 2032 backGroundColor: $r('sys.color.ohos_id_color_dialog_bg'), 2033 iconBorderRadius: $r('sys.float.ohos_id_corner_radius_default_m'), 2034 containerBorderRadius: $r('sys.float.ohos_id_corner_radius_card'), 2035 cutIcon: $r("sys.media.ohos_ic_public_cut"), 2036 copyIcon: $r("sys.media.ohos_ic_public_copy"), 2037 pasteIcon: $r("sys.media.ohos_ic_public_paste"), 2038 selectAllIcon: $r("sys.media.ohos_ic_public_select_all"), 2039 shareIcon: $r("sys.media.ohos_ic_public_share"), 2040 translateIcon: $r("sys.media.ohos_ic_public_translate_c2e"), 2041 searchIcon: $r("sys.media.ohos_ic_public_search_filled"), 2042 arrowDownIcon: $r("sys.media.ohos_ic_public_arrow_down"), 2043 iconPanelShadowStyle: ShadowStyle.OUTER_DEFAULT_MD, 2044 iconFocusBorderColor: $r('sys.color.ohos_id_color_focused_outline'), 2045} 2046 2047@Entry 2048@Component 2049struct SelectionMenu { 2050 @State message: string = 'Hello World' 2051 @State textSize: number = 40 2052 @State sliderShow: boolean = false 2053 @State start: number = -1 2054 @State end: number = -1 2055 @State colorTransparent: Color = Color.Transparent 2056 controller: RichEditorController = new RichEditorController(); 2057 options: RichEditorOptions = { controller: this.controller } 2058 private iconArr: Array<Resource> = 2059 [$r('app.media.icon'), $r("app.media.icon"), $r('app.media.icon'), 2060 $r("app.media.icon"), $r('app.media.icon')] 2061 @State iconBgColor: ResourceColor[] = new Array(this.iconArr.length).fill(this.colorTransparent) 2062 @State pasteEnable: boolean = false 2063 @State visibilityValue: Visibility = Visibility.Visible 2064 @State textStyle: RichEditorTextStyle = {} 2065 private fontWeightTable: string[] = ["100", "200", "300", "400", "500", "600", "700", "800", "900", "bold", "normal", "bolder", "lighter", "medium", "regular"] 2066 private theme: SelectionMenuTheme = defaultTheme; 2067 2068 aboutToAppear() { 2069 if (this.controller) { 2070 let richEditorSelection = this.controller.getSelection() 2071 if (richEditorSelection) { 2072 let start = richEditorSelection.selection[0] 2073 let end = richEditorSelection.selection[1] 2074 if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) { 2075 this.visibilityValue = Visibility.None 2076 } else { 2077 this.visibilityValue = Visibility.Visible 2078 } 2079 } 2080 } 2081 let sysBoard = pasteboard.getSystemPasteboard() 2082 if (sysBoard && sysBoard.hasDataSync()) { 2083 this.pasteEnable = true 2084 } else { 2085 this.pasteEnable = false 2086 } 2087 } 2088 2089 build() { 2090 Column() { 2091 Column() { 2092 RichEditor(this.options) 2093 .onReady(() => { 2094 this.controller.addTextSpan(this.message, { style: { fontColor: Color.Orange, fontSize: 30 } }) 2095 }) 2096 .onSelect((value: RichEditorSelection) => { 2097 if (value.selection[0] == -1 && value.selection[1] == -1) { 2098 return 2099 } 2100 this.start = value.selection[0] 2101 this.end = value.selection[1] 2102 }) 2103 .bindSelectionMenu(RichEditorSpanType.TEXT, this.panel, ResponseType.LongPress, { onDisappear: () => { 2104 this.sliderShow = false 2105 }}) 2106 .bindSelectionMenu(RichEditorSpanType.TEXT, this.panel, ResponseType.RightClick, { onDisappear: () => { 2107 this.sliderShow = false 2108 }}) 2109 .borderWidth(1) 2110 .borderColor(Color.Red) 2111 .width(200) 2112 .height(200) 2113 }.width('100%').backgroundColor(Color.White) 2114 }.height('100%') 2115 } 2116 2117 PushDataToPasteboard(richEditorSelection: RichEditorSelection) { 2118 let sysBoard = pasteboard.getSystemPasteboard() 2119 let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, '') 2120 if (richEditorSelection.spans && richEditorSelection.spans.length > 0) { 2121 let count = richEditorSelection.spans.length 2122 for (let i = count - 1; i >= 0; i--) { 2123 let item = richEditorSelection.spans[i] 2124 if ((item as RichEditorTextSpanResult)?.textStyle) { 2125 let span = item as RichEditorTextSpanResult 2126 let style = span.textStyle 2127 let data = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_PLAIN, span.value.substring(span.offsetInSpan[0], span.offsetInSpan[1])) 2128 let prop = pasteData.getProperty() 2129 let temp: Record<string, Object> = { 2130 'color': style.fontColor, 2131 'size': style.fontSize, 2132 'style': style.fontStyle, 2133 'weight': this.fontWeightTable[style.fontWeight], 2134 'fontFamily': style.fontFamily, 2135 'decorationType': style.decoration.type, 2136 'decorationColor': style.decoration.color 2137 } 2138 prop.additions[i] = temp; 2139 pasteData.addRecord(data) 2140 pasteData.setProperty(prop) 2141 } 2142 } 2143 } 2144 sysBoard.clearData() 2145 sysBoard.setData(pasteData).then(() => { 2146 console.info('SelectionMenu copy option, Succeeded in setting PasteData.'); 2147 this.pasteEnable = true; 2148 }).catch((err: BusinessError) => { 2149 console.error('SelectionMenu copy option, Failed to set PasteData. Cause:' + err.message); 2150 }) 2151 } 2152 2153 PopDataFromPasteboard(richEditorSelection: RichEditorSelection) { 2154 let start = richEditorSelection.selection[0] 2155 let end = richEditorSelection.selection[1] 2156 if (start == end && this.controller) { 2157 start = this.controller.getCaretOffset() 2158 end = this.controller.getCaretOffset() 2159 } 2160 let moveOffset = 0 2161 let sysBoard = pasteboard.getSystemPasteboard() 2162 sysBoard.getData((err, data) => { 2163 if (err) { 2164 return 2165 } 2166 let count = data.getRecordCount() 2167 for (let i = 0; i < count; i++) { 2168 const element = data.getRecord(i); 2169 let tex: RichEditorTextStyle = { 2170 fontSize: 16, 2171 fontColor: Color.Black, 2172 fontWeight: FontWeight.Normal, 2173 fontFamily: "HarmonyOS Sans", 2174 fontStyle: FontStyle.Normal, 2175 decoration: { type: TextDecorationType.None, color: "#FF000000", style: TextDecorationStyle.SOLID } 2176 } 2177 if (data.getProperty() && data.getProperty().additions[i]) { 2178 const tmp = data.getProperty().additions[i] as Record<string, Object | undefined>; 2179 if (tmp.color) { 2180 tex.fontColor = tmp.color as ResourceColor; 2181 } 2182 if (tmp.size) { 2183 tex.fontSize = tmp.size as Length | number; 2184 } 2185 if (tmp.style) { 2186 tex.fontStyle = tmp.style as FontStyle; 2187 } 2188 if (tmp.weight) { 2189 tex.fontWeight = tmp.weight as number | FontWeight | string; 2190 } 2191 if (tmp.fontFamily) { 2192 tex.fontFamily = tmp.fontFamily as ResourceStr; 2193 } 2194 if (tmp.decorationType && tex.decoration) { 2195 tex.decoration.type = tmp.decorationType as TextDecorationType; 2196 } 2197 if (tmp.decorationColor && tex.decoration) { 2198 tex.decoration.color = tmp.decorationColor as ResourceColor; 2199 } 2200 if (tex.decoration) { 2201 tex.decoration = { type: tex.decoration.type, color: tex.decoration.color } 2202 } 2203 } 2204 if (element && element.plainText && element.mimeType === pasteboard.MIMETYPE_TEXT_PLAIN && this.controller) { 2205 this.controller.addTextSpan(element.plainText, 2206 { 2207 style: tex, 2208 offset: start + moveOffset 2209 } 2210 ) 2211 moveOffset += element.plainText.length 2212 } 2213 } 2214 if (this.controller) { 2215 this.controller.setCaretOffset(start + moveOffset) 2216 this.controller.closeSelectionMenu() 2217 } 2218 if (start != end && this.controller) { 2219 this.controller.deleteSpans({ start: start + moveOffset, end: end + moveOffset }) 2220 } 2221 }) 2222 } 2223 2224 @Builder 2225 panel() { 2226 Column() { 2227 this.iconPanel() 2228 if (!this.sliderShow) { 2229 this.SystemMenu() 2230 } else { 2231 this.sliderPanel() 2232 } 2233 }.width(256) 2234 } 2235 2236 @Builder iconPanel() { 2237 Column() { 2238 Row({ space: 2 }) { 2239 ForEach(this.iconArr, (item:Resource, index ?: number) => { 2240 Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 2241 Image(item).fillColor(this.theme.imageFillColor).width(24).height(24).focusable(true).draggable(false) 2242 } 2243 .borderRadius(this.theme.iconBorderRadius) 2244 .width(this.theme.buttonSize) 2245 .height(this.theme.buttonSize) 2246 .onClick(() => { 2247 if (index as number == 0) { 2248 this.sliderShow = false 2249 if (this.controller) { 2250 let selection = this.controller.getSelection(); 2251 let spans = selection.spans 2252 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2253 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2254 let span = item as RichEditorTextSpanResult 2255 this.textStyle = span.textStyle 2256 let start = span.offsetInSpan[0] 2257 let end = span.offsetInSpan[1] 2258 let offset = span.spanPosition.spanRange[0] 2259 if (this.textStyle.fontWeight != 11) { 2260 this.textStyle.fontWeight = FontWeight.Bolder 2261 } else { 2262 this.textStyle.fontWeight = FontWeight.Normal 2263 } 2264 this.controller.updateSpanStyle({ 2265 start: offset + start, 2266 end: offset + end, 2267 textStyle: this.textStyle 2268 }) 2269 } 2270 }) 2271 } 2272 } else if (index as number == 1) { 2273 this.sliderShow = false 2274 if (this.controller) { 2275 let selection = this.controller.getSelection(); 2276 let spans = selection.spans 2277 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2278 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2279 let span = item as RichEditorTextSpanResult 2280 this.textStyle = span.textStyle 2281 let start = span.offsetInSpan[0] 2282 let end = span.offsetInSpan[1] 2283 let offset = span.spanPosition.spanRange[0] 2284 if (this.textStyle.fontStyle == FontStyle.Italic) { 2285 this.textStyle.fontStyle = FontStyle.Normal 2286 } else { 2287 this.textStyle.fontStyle = FontStyle.Italic 2288 } 2289 this.controller.updateSpanStyle({ 2290 start: offset + start, 2291 end: offset + end, 2292 textStyle: this.textStyle 2293 }) 2294 } 2295 }) 2296 } 2297 } else if (index as number == 2) { 2298 this.sliderShow = false 2299 if (this.controller) { 2300 let selection = this.controller.getSelection(); 2301 let spans = selection.spans 2302 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2303 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2304 let span = item as RichEditorTextSpanResult 2305 this.textStyle = span.textStyle 2306 let start = span.offsetInSpan[0] 2307 let end = span.offsetInSpan[1] 2308 let offset = span.spanPosition.spanRange[0] 2309 if (this.textStyle.decoration) { 2310 if (this.textStyle.decoration.type == TextDecorationType.Underline) { 2311 this.textStyle.decoration.type = TextDecorationType.None 2312 } else { 2313 this.textStyle.decoration.type = TextDecorationType.Underline 2314 } 2315 } else { 2316 this.textStyle.decoration = { type: TextDecorationType.Underline, color: Color.Black, style: TextDecorationStyle.SOLID } 2317 } 2318 this.controller.updateSpanStyle({ 2319 start: offset + start, 2320 end: offset + end, 2321 textStyle: this.textStyle 2322 }) 2323 } 2324 }) 2325 } 2326 } else if (index as number == 3) { 2327 this.sliderShow = !this.sliderShow 2328 } else if (index as number == 4) { 2329 this.sliderShow = false 2330 if (this.controller) { 2331 let selection = this.controller.getSelection(); 2332 let spans = selection.spans 2333 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2334 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2335 let span = item as RichEditorTextSpanResult 2336 this.textStyle = span.textStyle 2337 let start = span.offsetInSpan[0] 2338 let end = span.offsetInSpan[1] 2339 let offset = span.spanPosition.spanRange[0] 2340 if (this.textStyle.fontColor == Color.Orange || this.textStyle.fontColor == '#FFFFA500') { 2341 this.textStyle.fontColor = Color.Black 2342 } else { 2343 this.textStyle.fontColor = Color.Orange 2344 } 2345 this.controller.updateSpanStyle({ 2346 start: offset + start, 2347 end: offset + end, 2348 textStyle: this.textStyle 2349 }) 2350 } 2351 }) 2352 } 2353 } 2354 }) 2355 .onTouch((event?: TouchEvent | undefined) => { 2356 if(event != undefined){ 2357 if (event.type === TouchType.Down) { 2358 this.iconBgColor[index as number] = $r('sys.color.ohos_id_color_click_effect') 2359 } 2360 if (event.type === TouchType.Up) { 2361 this.iconBgColor[index as number] = this.colorTransparent 2362 } 2363 } 2364 }) 2365 .onHover((isHover?: boolean, event?: HoverEvent) => { 2366 this.iconBgColor.forEach((icon:ResourceColor, index1) => { 2367 this.iconBgColor[index1] = this.colorTransparent 2368 }) 2369 if(isHover != undefined) { 2370 this.iconBgColor[index as number] = $r('sys.color.ohos_id_color_hover') 2371 } 2372 }) 2373 .backgroundColor(this.iconBgColor[index as number]) 2374 }) 2375 } 2376 } 2377 .clip(true) 2378 .width(this.theme.defaultMenuWidth) 2379 .padding(this.theme.expandedOptionPadding) 2380 .borderRadius(this.theme.containerBorderRadius) 2381 .margin({ bottom: this.theme.menuSpacing }) 2382 .backgroundColor(this.theme.backGroundColor) 2383 .shadow(this.theme.iconPanelShadowStyle) 2384 } 2385 2386 @Builder 2387 SystemMenu() { 2388 Column() { 2389 Menu() { 2390 if (this.controller) { 2391 MenuItemGroup() { 2392 MenuItem({ startIcon: this.theme.cutIcon, content: "剪切", labelInfo: "Ctrl+X" }) 2393 .onClick(() => { 2394 if (!this.controller) { 2395 return 2396 } 2397 let richEditorSelection = this.controller.getSelection() 2398 this.PushDataToPasteboard(richEditorSelection); 2399 this.controller.deleteSpans({ 2400 start: richEditorSelection.selection[0], 2401 end: richEditorSelection.selection[1] 2402 }) 2403 }) 2404 MenuItem({ startIcon: this.theme.copyIcon, content: "复制", labelInfo: "Ctrl+C" }) 2405 .onClick(() => { 2406 if (!this.controller) { 2407 return 2408 } 2409 let richEditorSelection = this.controller.getSelection() 2410 this.PushDataToPasteboard(richEditorSelection); 2411 this.controller.closeSelectionMenu() 2412 }) 2413 MenuItem({ startIcon: this.theme.pasteIcon, content: "粘贴", labelInfo: "Ctrl+V" }) 2414 .enabled(this.pasteEnable) 2415 .onClick(() => { 2416 if (!this.controller) { 2417 return 2418 } 2419 let richEditorSelection = this.controller.getSelection() 2420 this.PopDataFromPasteboard(richEditorSelection) 2421 }) 2422 MenuItem({ startIcon: this.theme.selectAllIcon, content: "全选", labelInfo: "Ctrl+A" }) 2423 .visibility(this.visibilityValue) 2424 .onClick(() => { 2425 if (!this.controller) { 2426 return 2427 } 2428 this.controller.setSelection(-1, -1) 2429 this.visibilityValue = Visibility.None 2430 }) 2431 MenuItem({ startIcon: this.theme.shareIcon, content: "分享", labelInfo: "" }) 2432 .enabled(false) 2433 MenuItem({ startIcon: this.theme.translateIcon, content: "翻译", labelInfo: "" }) 2434 .enabled(false) 2435 MenuItem({ startIcon: this.theme.searchIcon, content: "搜索", labelInfo: "" }) 2436 .enabled(false) 2437 } 2438 } 2439 } 2440 .onVisibleAreaChange([0.0, 1.0], () => { 2441 if (!this.controller) { 2442 return 2443 } 2444 let richEditorSelection = this.controller.getSelection() 2445 let start = richEditorSelection.selection[0] 2446 let end = richEditorSelection.selection[1] 2447 if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) { 2448 this.visibilityValue = Visibility.None 2449 } else { 2450 this.visibilityValue = Visibility.Visible 2451 } 2452 }) 2453 .radius(this.theme.containerBorderRadius) 2454 .clip(true) 2455 .backgroundColor(Color.White) 2456 .width(this.theme.defaultMenuWidth) 2457 } 2458 .width(this.theme.defaultMenuWidth) 2459 } 2460 2461 @Builder sliderPanel() { 2462 Column() { 2463 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 2464 Text('A').fontSize(15) 2465 Slider({ value: this.textSize, step: 10, style: SliderStyle.InSet }) 2466 .width(210) 2467 .onChange((value: number, mode: SliderChangeMode) => { 2468 if (this.controller) { 2469 let selection = this.controller.getSelection(); 2470 if (mode == SliderChangeMode.End) { 2471 if (this.textSize == undefined) { 2472 this.textSize = 0 2473 } 2474 let spans = selection.spans 2475 spans.forEach((item: RichEditorTextSpanResult | RichEditorImageSpanResult, index) => { 2476 if (typeof (item as RichEditorTextSpanResult)['textStyle'] != 'undefined') { 2477 this.textSize = Math.max(this.textSize, (item as RichEditorTextSpanResult).textStyle.fontSize) 2478 } 2479 }) 2480 } 2481 if (mode == SliderChangeMode.Moving || mode == SliderChangeMode.Click) { 2482 this.start = selection.selection[0] 2483 this.end = selection.selection[1] 2484 this.textSize = value 2485 this.controller.updateSpanStyle({ 2486 start: this.start, 2487 end: this.end, 2488 textStyle: { fontSize: this.textSize } 2489 }) 2490 } 2491 } 2492 }) 2493 Text('A').fontSize(20).fontWeight(FontWeight.Medium) 2494 }.borderRadius(this.theme.containerBorderRadius) 2495 } 2496 .shadow(ShadowStyle.OUTER_DEFAULT_MD) 2497 .backgroundColor(Color.White) 2498 .borderRadius(this.theme.containerBorderRadius) 2499 .padding(15) 2500 .height(48) 2501 } 2502} 2503``` 2504> **说明:** 2505> 2506> 系统暂未预置加粗、斜体等图标,示例代码使用系统默认图标,开发者使用时需自行替换iconArr中的资源。 2507 2508 2509 2510### 示例4 2511 2512```ts 2513// xxx.ets 2514@Entry 2515@Component 2516struct Index { 2517 controller: RichEditorController = new RichEditorController(); 2518 options: RichEditorOptions = { controller: this.controller }; 2519 private start: number = -1; 2520 private end: number = -1; 2521 @State message: string = "[-1, -1]" 2522 @State content: string = "" 2523 @State paddingVal: number = 5 2524 @State borderRad: number = 4 2525 2526 build() { 2527 Column() { 2528 Column() { 2529 Text("selection range:").width("100%") 2530 Text() { 2531 Span(this.message) 2532 }.width("100%") 2533 Text("selection content:").width("100%") 2534 Text() { 2535 Span(this.content) 2536 }.width("100%") 2537 } 2538 .borderWidth(1) 2539 .borderColor(Color.Red) 2540 .width("100%") 2541 .height("20%") 2542 2543 Row() { 2544 Button("updateSpanStyle1") 2545 .fontSize(12) 2546 .onClick(() => { 2547 this.controller.updateSpanStyle({ 2548 start: this.start, 2549 textStyle: 2550 { 2551 fontWeight: FontWeight.Bolder 2552 }, 2553 imageStyle: { 2554 size: ["80px", "80px"], 2555 layoutStyle: { 2556 borderRadius: undefined, 2557 margin: undefined 2558 } 2559 } 2560 }) 2561 }) 2562 2563 Button("updateSpanStyle2") 2564 .fontSize(12) 2565 .onClick(() => { 2566 this.controller.updateSpanStyle({ 2567 start: this.start, 2568 textStyle: 2569 { 2570 fontWeight: FontWeight.Bolder 2571 }, 2572 imageStyle: { 2573 size: ["70px", "70px"], 2574 layoutStyle: { 2575 borderRadius: { topLeft: '100px', topRight: '20px', bottomLeft: '100px', bottomRight: '20px' }, 2576 margin: { left: '30px', top: '20px', right: '20px', bottom: '20px' } 2577 } 2578 } 2579 }) 2580 }) 2581 2582 Button("updateSpanStyle3") 2583 .fontSize(12) 2584 .onClick(() => { 2585 this.controller.updateSpanStyle({ 2586 start: this.start, 2587 textStyle: 2588 { 2589 fontWeight: FontWeight.Bolder 2590 }, 2591 imageStyle: { 2592 size: ["60px", "60px"], 2593 layoutStyle: { 2594 borderRadius: '-10px', 2595 margin: '-10px' 2596 } 2597 } 2598 }) 2599 }) 2600 } 2601 .borderWidth(1) 2602 .borderColor(Color.Red) 2603 .width("100%") 2604 .height("10%") 2605 2606 Row() { 2607 Button('addImageSpan1') 2608 .fontSize(12) 2609 .onClick(() => { 2610 this.controller.addImageSpan($r('app.media.app_icon'), { 2611 imageStyle: { 2612 size: ["80px", "80px"], 2613 layoutStyle: { 2614 borderRadius: '50px', 2615 margin: '40px' 2616 } 2617 } 2618 }) 2619 }) 2620 2621 Button('addImageSpan2') 2622 .fontSize(12) 2623 .onClick(() => { 2624 this.controller.addImageSpan($r('app.media.app_icon'), { 2625 imageStyle: { 2626 size: ["100px", "100px"], 2627 verticalAlign: ImageSpanAlignment.BOTTOM, 2628 layoutStyle: { 2629 borderRadius: undefined, 2630 margin: undefined 2631 } 2632 } 2633 }) 2634 }) 2635 2636 Button('addImageSpan3') 2637 .fontSize(12) 2638 .onClick(() => { 2639 this.controller.addImageSpan($r('app.media.app_icon'), { 2640 imageStyle: { 2641 size: ["60px", "60px"], 2642 verticalAlign: ImageSpanAlignment.BOTTOM, 2643 layoutStyle: { 2644 borderRadius: { topLeft: '10px', topRight: '20px', bottomLeft: '30px', bottomRight: '40px' }, 2645 margin: { left: '10px', top: '20px', right: '30px', bottom: '40px' } 2646 } 2647 } 2648 }) 2649 }) 2650 } 2651 .borderWidth(1) 2652 .borderColor(Color.Red) 2653 .width("100%") 2654 .height("10%") 2655 2656 Column() { 2657 RichEditor(this.options) 2658 .onReady(() => { 2659 this.controller.addTextSpan("0123456789", 2660 { 2661 style: 2662 { 2663 fontColor: Color.Orange, 2664 fontSize: 30 2665 } 2666 }) 2667 2668 this.controller.addImageSpan($r("app.media.app_icon"), 2669 { 2670 imageStyle: 2671 { 2672 size: ["60px", "60px"], 2673 verticalAlign: ImageSpanAlignment.BOTTOM, 2674 layoutStyle: { 2675 borderRadius: { topLeft: '10px', topRight: '20px', bottomLeft: '30px', bottomRight: '40px' }, 2676 margin: { left: '10px', top: '20px', right: '30px', bottom: '40px' } 2677 } 2678 } 2679 }) 2680 2681 this.controller.addTextSpan("0123456789", 2682 { 2683 style: 2684 { 2685 fontColor: Color.Black, 2686 fontSize: 30 2687 } 2688 }) 2689 }) 2690 .onSelect((value: RichEditorSelection) => { 2691 this.start = value.selection[0]; 2692 this.end = value.selection[1]; 2693 this.message = "[" + this.start + ", " + this.end + "]" 2694 }) 2695 .aboutToIMEInput((value: RichEditorInsertValue) => { 2696 console.log("---------------------- aboutToIMEInput ----------------------") 2697 console.log("insertOffset:" + value.insertOffset) 2698 console.log("insertValue:" + value.insertValue) 2699 return true; 2700 }) 2701 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 2702 console.log("---------------------- onIMEInputComplete ---------------------") 2703 console.log("spanIndex:" + value.spanPosition.spanIndex) 2704 console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]") 2705 console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]") 2706 console.log("value:" + value.value) 2707 }) 2708 .aboutToDelete((value: RichEditorDeleteValue) => { 2709 console.log("---------------------- aboutToDelete --------------------------") 2710 console.log("offset:" + value.offset) 2711 console.log("direction:" + value.direction) 2712 console.log("length:" + value.length) 2713 value.richEditorDeleteSpans.forEach(item => { 2714 console.log("---------------------- item --------------------------") 2715 console.log("spanIndex:" + item.spanPosition.spanIndex) 2716 console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]") 2717 console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]") 2718 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 2719 console.log("image:" + (item as RichEditorImageSpanResult).valueResourceStr) 2720 } else { 2721 console.log("text:" + (item as RichEditorTextSpanResult).value) 2722 } 2723 }) 2724 return true; 2725 }) 2726 .onDeleteComplete(() => { 2727 console.log("---------------------- onDeleteComplete ------------------------") 2728 }) 2729 .borderWidth(1) 2730 .borderColor(Color.Green) 2731 .width("100%") 2732 .height('80.00%') 2733 } 2734 .borderWidth(1) 2735 .borderColor(Color.Red) 2736 .width("100%") 2737 .height("70%") 2738 } 2739 } 2740} 2741``` 2742 2743 2744### 示例5 2745 2746```ts 2747// xxx.ets 2748@Entry 2749@Component 2750struct Index { 2751 controller: RichEditorController = new RichEditorController() 2752 options: RichEditorOptions = { controller: this.controller }; 2753 @State textFlag: string = "TextFlag"; 2754 2755 build() { 2756 Column() { 2757 Column() { 2758 Text(this.textFlag) 2759 .copyOption(CopyOptions.InApp) 2760 .fontSize(50) 2761 } 2762 Divider() 2763 Column() { 2764 RichEditor(this.options) 2765 .onReady(() => { 2766 this.controller.addTextSpan('Area1\n', { 2767 style: 2768 { 2769 fontColor: Color.Orange, 2770 fontSize: 50 2771 }, 2772 gesture: 2773 { 2774 onClick: () => { 2775 this.textFlag = "Area1 is onClick." 2776 }, 2777 onLongPress: () => { 2778 this.textFlag = "Area1 is onLongPress." 2779 } 2780 } 2781 }) 2782 2783 this.controller.addTextSpan('Area2\n', { 2784 style: 2785 { 2786 fontColor: Color.Blue, 2787 fontSize: 50 2788 }, 2789 gesture: 2790 { 2791 onClick: () => { 2792 this.textFlag = "Area2 is onClick." 2793 }, 2794 onLongPress: () => { 2795 this.textFlag = "Area2 is onLongPress." 2796 } 2797 } 2798 }) 2799 2800 this.controller.addImageSpan($r("app.media.icon"), 2801 { 2802 imageStyle: 2803 { 2804 size: ["100px", "100px"], 2805 layoutStyle: { 2806 margin: 5, 2807 borderRadius: 15 2808 } 2809 }, 2810 gesture: 2811 { 2812 onClick: () => { 2813 this.textFlag = "ImageSpan is onClick." 2814 }, 2815 onLongPress: () => { 2816 this.textFlag = "ImageSpan is onLongPress." 2817 } 2818 } 2819 }) 2820 }) 2821 } 2822 .borderWidth(1) 2823 .borderColor(Color.Red) 2824 .width("100%") 2825 .height("70%") 2826 } 2827 } 2828} 2829``` 2830 2831 2832### 示例6 2833 2834```ts 2835// xxx.ets 2836@Entry 2837@Component 2838struct Index { 2839 controller: RichEditorController = new RichEditorController(); 2840 private spanParagraphs: RichEditorParagraphResult[] = []; 2841 2842 build() { 2843 Column() { 2844 RichEditor({ controller: this.controller }) 2845 .onReady(() => { 2846 this.controller.addTextSpan("0123456789\n", { 2847 style: { 2848 fontColor: Color.Pink, 2849 fontSize: "32", 2850 }, 2851 paragraphStyle: { 2852 textAlign: TextAlign.Start, 2853 leadingMargin: 16 2854 } 2855 }) 2856 this.controller.addTextSpan("0123456789") 2857 }) 2858 .width("80%") 2859 .height("30%") 2860 .border({ width: 1, radius: 5 }) 2861 .draggable(false) 2862 2863 Column({ space: 5 }) { 2864 Button("段落左对齐").onClick(() => { 2865 this.controller.updateParagraphStyle({ start: -1, end: -1, 2866 style: { 2867 textAlign: TextAlign.Start, 2868 } 2869 }) 2870 }) 2871 2872 Button("段落右对齐").onClick(() => { 2873 this.controller.updateParagraphStyle({ start: -1, end: -1, 2874 style: { 2875 textAlign: TextAlign.End, 2876 } 2877 }) 2878 }) 2879 2880 Button("段落居中").onClick(() => { 2881 this.controller.updateParagraphStyle({ start: -1, end: -1, 2882 style: { 2883 textAlign: TextAlign.Center, 2884 } 2885 }) 2886 }) 2887 Divider() 2888 Button("getParagraphs").onClick(() => { 2889 this.spanParagraphs = this.controller.getParagraphs({ start: -1, end: -1 }) 2890 console.log("RichEditor getParagraphs:" + JSON.stringify(this.spanParagraphs)) 2891 }) 2892 2893 Button("UpdateSpanStyle1").onClick(() => { 2894 this.controller.updateSpanStyle({ start: -1, end: -1, 2895 textStyle: { 2896 fontColor: Color.Brown, 2897 fontSize: 20 2898 } 2899 }) 2900 }) 2901 2902 Button("UpdateSpanStyle2").onClick(() => { 2903 this.controller.updateSpanStyle({ start: -1, end: -1, 2904 textStyle: { 2905 fontColor: Color.Green, 2906 fontSize: 30 2907 } 2908 }) 2909 }) 2910 } 2911 } 2912 } 2913} 2914``` 2915 2916 2917### 示例7 2918 2919```ts 2920// xxx.ets 2921import { font } from '@kit.ArkUI' 2922 2923const canvasWidth = 1000 2924const canvasHeight = 100 2925const Indentation = 40 2926class LeadingMarginCreator { 2927 private settings: RenderingContextSettings = new RenderingContextSettings(true) 2928 private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(canvasWidth, canvasHeight) 2929 private offContext: OffscreenCanvasRenderingContext2D = this.offscreenCanvas.getContext("2d", this.settings) 2930 public static instance: LeadingMarginCreator = new LeadingMarginCreator() 2931 2932 // 获得字体字号级别,分别是从0到4级 2933 public getFontSizeLevel(fontSize: number) { 2934 const fontScaled: number = Number(fontSize) / 16 2935 2936 enum FontSizeScaleThreshold { 2937 SMALL = 0.9, 2938 NORMAL = 1.1, 2939 LEVEL_1_LARGE = 1.2, 2940 LEVEL_2_LARGE = 1.4, 2941 LEVEL_3_LARGE = 1.5 2942 } 2943 2944 let fontSizeLevel: number = 1 2945 2946 if (fontScaled < FontSizeScaleThreshold.SMALL) { 2947 fontSizeLevel = 0 2948 } else if (fontScaled < FontSizeScaleThreshold.NORMAL) { 2949 fontSizeLevel = 1 2950 } else if (fontScaled < FontSizeScaleThreshold.LEVEL_1_LARGE) { 2951 fontSizeLevel = 2 2952 } else if (fontScaled < FontSizeScaleThreshold.LEVEL_2_LARGE) { 2953 fontSizeLevel = 3 2954 } else if (fontScaled < FontSizeScaleThreshold.LEVEL_3_LARGE) { 2955 fontSizeLevel = 4 2956 } else { 2957 fontSizeLevel = 1 2958 } 2959 2960 return fontSizeLevel 2961 } 2962 // 获得字体字号级别,分别是从0到4级 2963 public getmarginLevel(Width: number) { 2964 let marginlevel: number = 1 2965 if (Width == 40) { 2966 marginlevel = 2.0 2967 } else if (Width == 80) { 2968 marginlevel = 1.0 2969 } else if (Width == 120) { 2970 marginlevel = 2/3 2971 } else if (Width == 160) { 2972 marginlevel = 0.5 2973 } else if (Width == 200) { 2974 marginlevel = 0.4 2975 } 2976 return marginlevel 2977 } 2978 2979 public genStrMark(fontSize: number, str: string): PixelMap { 2980 this.offContext = this.offscreenCanvas.getContext("2d", this.settings) 2981 this.clearCanvas() 2982 this.offContext.font = fontSize + 'vp sans-serif' 2983 this.offContext.fillText(str + '.', 0, fontSize * 0.9) 2984 return this.offContext.getPixelMap(0, 0, fontSize * (str.length + 1) / 1.75, fontSize) 2985 } 2986 2987 public genSquareMark(fontSize: number): PixelMap { 2988 this.offContext = this.offscreenCanvas.getContext("2d", this.settings) 2989 this.clearCanvas() 2990 const coordinate = fontSize * (1 - 1 / 1.5) / 2 2991 const sideLength = fontSize / 1.5 2992 this.offContext.fillRect(coordinate, coordinate, sideLength, sideLength) 2993 return this.offContext.getPixelMap(0, 0, fontSize, fontSize) 2994 } 2995 2996 // 生成圆圈符号 2997 public genCircleMark(fontSize: number, width: number, level?: number ): PixelMap { 2998 const indentLevel = level ?? 1 2999 const offsetLevel = [22, 28, 32, 34, 38] 3000 const fontSizeLevel = this.getFontSizeLevel(fontSize) 3001 const marginlevel = this.getmarginLevel(width) 3002 const newCanvas = new OffscreenCanvas(canvasWidth, canvasHeight) 3003 const newOffContext: OffscreenCanvasRenderingContext2D = newCanvas.getContext("2d", this.settings) 3004 const centerCoordinate = 50 3005 const radius = 10 3006 this.clearCanvas() 3007 newOffContext.ellipse(100 * (indentLevel + 1) - centerCoordinate * marginlevel, offsetLevel[fontSizeLevel], radius * marginlevel, radius, 0, 0, 2 * Math.PI) 3008 newOffContext.fillStyle = '66FF0000' 3009 newOffContext.fill() 3010 return newOffContext.getPixelMap(0, 0, 100 + 100 * indentLevel, 100) 3011 } 3012 3013 private clearCanvas() { 3014 this.offContext.clearRect(0, 0, canvasWidth, canvasHeight) 3015 } 3016} 3017 3018@Entry 3019@Component 3020struct Index { 3021 controller: RichEditorController = new RichEditorController() 3022 options: RichEditorOptions = { controller: this.controller } 3023 private leadingMarkCreatorInstance = LeadingMarginCreator.instance 3024 private fontNameRawFile: string = 'MiSans-Bold' 3025 @State fs: number = 30 3026 @State cl: number = Color.Black 3027 private leftMargin: Dimension = 0 3028 private richEditorTextStyle: RichEditorTextStyle = {} 3029 3030 aboutToAppear() { 3031 font.registerFont({ 3032 familyName: 'MiSans-Bold', 3033 familySrc: '/font/MiSans-Bold.ttf' 3034 }) 3035 } 3036 3037 build() { 3038 Scroll() { 3039 Column() { 3040 RichEditor(this.options) 3041 .onReady(() => { 3042 this.controller.addTextSpan("0123456789\n", 3043 { 3044 style: 3045 { 3046 fontWeight: 'medium', 3047 fontFamily: this.fontNameRawFile, 3048 fontColor: Color.Red, 3049 fontSize: 50, 3050 fontStyle: FontStyle.Italic, 3051 decoration: { type: TextDecorationType.Underline, color: Color.Green } 3052 } 3053 }) 3054 3055 this.controller.addTextSpan("abcdefg", 3056 { 3057 style: 3058 { 3059 fontWeight: FontWeight.Lighter, 3060 fontFamily: 'HarmonyOS Sans', 3061 fontColor: 'rgba(0,128,0,0.5)', 3062 fontSize: 30, 3063 fontStyle: FontStyle.Normal, 3064 decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' } 3065 } 3066 }) 3067 }) 3068 .borderWidth(1) 3069 .borderColor(Color.Green) 3070 .width("100%") 3071 .height("50%") 3072 3073 Row({ space: 5 }) { 3074 Button('setTypingStyle1') 3075 .fontSize(10) 3076 .onClick(() => { 3077 this.controller.setTypingStyle( 3078 { 3079 fontWeight: 'medium', 3080 fontFamily: this.fontNameRawFile, 3081 fontColor: Color.Blue, 3082 fontSize: 50, 3083 fontStyle: FontStyle.Italic, 3084 decoration: { type: TextDecorationType.Underline, color: Color.Green } 3085 }) 3086 }) 3087 3088 Button('setTypingStyle2') 3089 .fontSize(10) 3090 .onClick(() => { 3091 this.controller.setTypingStyle( 3092 { 3093 fontWeight: FontWeight.Lighter, 3094 fontFamily: 'HarmonyOS Sans', 3095 fontColor: Color.Green, 3096 fontSize: '30', 3097 fontStyle: FontStyle.Normal, 3098 decoration: { type: TextDecorationType.Overline, color: 'rgba(169, 26, 246, 0.50)' } 3099 }) 3100 }) 3101 } 3102 Divider() 3103 Button("getTypingStyle").onClick(() => { 3104 this.richEditorTextStyle = this.controller.getTypingStyle() 3105 console.log("RichEditor getTypingStyle:" + JSON.stringify(this.richEditorTextStyle)) 3106 }) 3107 Divider() 3108 Row({ space: 5 }) { 3109 Button("向右列表缩进").onClick(() => { 3110 let margin = Number(this.leftMargin) 3111 if (margin < 200) { 3112 margin += Indentation 3113 this.leftMargin = margin 3114 } 3115 this.controller.updateParagraphStyle({ 3116 start: -10, 3117 end: -10, 3118 style: { 3119 leadingMargin : { 3120 pixelMap : this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1), 3121 size: [margin, 40] 3122 } 3123 } 3124 }) 3125 }) 3126 3127 Button("向左列表缩进").onClick(() => { 3128 let margin = Number(this.leftMargin) 3129 if (margin > 0) { 3130 margin -= Indentation 3131 this.leftMargin = margin 3132 } 3133 this.controller.updateParagraphStyle({ 3134 start: -10, 3135 end: -10, 3136 style: { 3137 leadingMargin : { 3138 pixelMap : this.leadingMarkCreatorInstance.genCircleMark(100, margin, 1), 3139 size: [margin, 40] 3140 } 3141 } 3142 }) 3143 }) 3144 } 3145 Divider() 3146 Row({ space: 5 }) { 3147 Button("向右空白缩进").onClick(() => { 3148 let margin = Number(this.leftMargin) 3149 if (margin < 200) { 3150 margin += Indentation 3151 this.leftMargin = margin 3152 } 3153 this.controller.updateParagraphStyle({ 3154 start: -10, 3155 end: -10, 3156 style: { 3157 leadingMargin: margin 3158 } 3159 }) 3160 }) 3161 3162 Button("向左空白缩进").onClick(() => { 3163 let margin = Number(this.leftMargin) 3164 if (margin > 0) { 3165 margin -= Indentation 3166 this.leftMargin = margin 3167 } 3168 this.controller.updateParagraphStyle({ 3169 start: -10, 3170 end: -10, 3171 style: { 3172 leadingMargin: margin 3173 } 3174 }) 3175 }) 3176 } 3177 }.borderWidth(1).borderColor(Color.Red) 3178 } 3179 } 3180} 3181``` 3182 3183 3184### 示例8 3185``` ts 3186@Entry 3187@Component 3188struct Index { 3189 controller: RichEditorController = new RichEditorController(); 3190 options: RichEditorOptions = { controller: this.controller }; 3191 private start: number = -1; 3192 private end: number = -1; 3193 @State message: string = "[-1, -1]" 3194 @State content: string = "" 3195 @State visable :number = 0; 3196 @State index:number = 0; 3197 @State offsetx: number = 0; 3198 @State textShadows : (ShadowOptions | Array<ShadowOptions> ) = 3199 [{ radius: 10, color: Color.Red, offsetX: 10, offsetY: 0 },{ radius: 10, color: Color.Black, offsetX: 20, offsetY: 0 }, 3200 { radius: 10, color: Color.Brown, offsetX: 30, offsetY: 0 },{ radius: 10, color: Color.Green, offsetX: 40, offsetY: 0 }, 3201 { radius: 10, color: Color.Yellow, offsetX: 100, offsetY: 0 }] 3202 @State textshadowOf : ShadowOptions[] = [] 3203 build() { 3204 Column() { 3205 Column() { 3206 Text("selection range:").width("100%") 3207 Text() { 3208 Span(this.message) 3209 }.width("100%") 3210 Text("selection content:").width("100%") 3211 Text() { 3212 Span(this.content) 3213 }.width("100%") 3214 } 3215 .borderWidth(1) 3216 .borderColor(Color.Red) 3217 .width("100%") 3218 .height("20%") 3219 Row() { 3220 Button("更新样式: 加粗 & 文本阴影").onClick(() => { 3221 this.controller.updateSpanStyle({ 3222 start: this.start, 3223 end: this.end, 3224 textStyle: 3225 { 3226 fontWeight: FontWeight.Bolder, 3227 textShadow: this.textShadows 3228 } 3229 }) 3230 }) 3231 } 3232 .borderWidth(1) 3233 .borderColor(Color.Red) 3234 .width("100%") 3235 .height("10%") 3236 Column() { 3237 RichEditor(this.options) 3238 .onReady(() => { 3239 this.controller.addTextSpan("0123456789", 3240 { 3241 style: 3242 { 3243 fontColor: Color.Orange, 3244 fontSize: 30, 3245 textShadow: { radius: 10, color: Color.Blue, offsetX: 10, offsetY: 0 } 3246 } 3247 }) 3248 }) 3249 .borderWidth(1) 3250 .borderColor(Color.Green) 3251 .width("100%") 3252 .height("30%") 3253 } 3254 .borderWidth(1) 3255 .borderColor(Color.Red) 3256 .width("100%") 3257 .height("70%") 3258 } 3259 } 3260} 3261``` 3262 3263 3264 3265### 示例9 3266``` ts 3267@Builder 3268function placeholderBuilder2() { 3269 Row({ space: 2 }) { 3270 Image($r("app.media.icon")).width(24).height(24).margin({ left: -5 }) 3271 Text('okokokok').fontSize(10) 3272 }.width('20%').height(50).padding(10).backgroundColor(Color.Red) 3273} 3274 3275// xxx.ets 3276@Entry 3277@Component 3278struct Index { 3279 controller: RichEditorController = new RichEditorController(); 3280 option: RichEditorOptions = { controller: this.controller }; 3281 private start: number = 2; 3282 private end: number = 4; 3283 @State message: string = "[-1, -1]" 3284 @State content: string = "" 3285 private my_offset: number | undefined = undefined 3286 private my_builder: CustomBuilder = undefined 3287 @BuilderParam my_builder2:() => void = placeholderBuilder2; 3288 3289 @Builder 3290 placeholderBuilder() { 3291 Row({ space: 2 }) { 3292 Image($r("app.media.icon")).width(24).height(24).margin({ left: -5 }) 3293 Text('Custom Popup').fontSize(10) 3294 }.width(100).height(50).padding(5) 3295 } 3296 3297 @Builder 3298 placeholderBuilder3() { 3299 Text("hello").padding('20').borderWidth(1).width('100%') 3300 } 3301 3302 @Builder 3303 placeholderBuilder4() { 3304 Column() { 3305 Column({ space: 5 }) { 3306 Text('direction:Row').fontSize(9).fontColor(0xCCCCCC).width('90%') 3307 Flex({ direction: FlexDirection.Row }) { // 子组件在容器主抽上行布局 3308 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3309 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3310 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3311 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3312 } 3313 .height(70) 3314 .width('90%') 3315 .padding(10) 3316 .backgroundColor(0xAFEEEE) 3317 3318 Text('direction:RowReverse').fontSize(9).fontColor(0xCCCCCC).width('90%') 3319 Flex({ direction: FlexDirection.RowReverse }) { // 子组件在容器主抽上反向行布局 3320 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3321 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3322 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 3323 Text('1').width('20%').height(50).backgroundColor(0xD2B48C) 3324 } 3325 .height(70) 3326 .width('90%') 3327 .padding(10) 3328 .backgroundColor(0xAFEEEE) 3329 3330 Text('direction:Column').fontSize(9).fontColor(0xCCCCCC).width('90%') 3331 Flex({ direction: FlexDirection.Column }) { // 子组件在容器主抽上列布局 3332 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3333 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3334 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3335 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3336 } 3337 .height(160) 3338 .width('90%') 3339 .padding(10) 3340 .backgroundColor(0xAFEEEE) 3341 3342 Text('direction:ColumnReverse').fontSize(9).fontColor(0xCCCCCC).width('90%') 3343 Flex({ direction: FlexDirection.ColumnReverse }) { // 子组件在容器主抽上反向列布局 3344 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3345 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3346 Text('1').width('20%').height(40).backgroundColor(0xF5DEB3) 3347 Text('1').width('20%').height(40).backgroundColor(0xD2B48C) 3348 } 3349 .height(160) 3350 .width('90%') 3351 .padding(10) 3352 .backgroundColor(0xAFEEEE) 3353 }.width('100%').margin({ top: 5 }) 3354 }.width('100%') 3355 } 3356 3357 @Builder 3358 MyMenu() { 3359 Menu() { 3360 MenuItem({ startIcon: $r("app.media.icon"), content: "菜单选项1" }) 3361 MenuItem({ startIcon: $r("app.media.icon"), content: "菜单选项2" }) 3362 .enabled(false) 3363 } 3364 } 3365 3366 build() { 3367 Column() { 3368 Column() { 3369 Text("selection range:").width("100%") 3370 Text() { 3371 Span(this.message) 3372 }.width("100%") 3373 3374 Text("selection content:").width("100%") 3375 Text() { 3376 Span(this.content) 3377 }.width("100%") 3378 } 3379 .borderWidth(1) 3380 .borderColor(Color.Red) 3381 .width("100%") 3382 .height("20%") 3383 3384 Row() { 3385 Button("获取选择内容 getSpans").onClick(() => { 3386 console.info('getSpans='+JSON.stringify(this.controller.getSpans({ start:1, end:5 }))) 3387 console.info('getParagraphs='+JSON.stringify(this.controller.getParagraphs({ start:1, end:5 }))) 3388 this.content = "" 3389 this.controller.getSpans({ 3390 start: this.start, 3391 end: this.end 3392 }).forEach(item => { 3393 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3394 if ((item as RichEditorImageSpanResult).valueResourceStr == "") { 3395 console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + 3396 (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1]) 3397 } else { 3398 console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " + 3399 (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + 3400 (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1]) 3401 } 3402 } else { 3403 this.content += (item as RichEditorTextSpanResult).value; 3404 this.content += "\n" 3405 console.info("text span: " + (item as RichEditorTextSpanResult).value) 3406 } 3407 }) 3408 }) 3409 Button("获取选择内容 getSelection").onClick(() => { 3410 this.content = ""; 3411 let select = this.controller.getSelection() 3412 console.info("selection start " + select.selection[0] + " end " + select.selection[1]) 3413 select.spans.forEach(item => { 3414 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3415 if ((item as RichEditorImageSpanResult).valueResourceStr == "") { 3416 console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + 3417 (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1]) 3418 } else { 3419 console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " + 3420 (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + 3421 (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1]) 3422 } 3423 } else { 3424 this.content += (item as RichEditorTextSpanResult).value; 3425 this.content += "\n" 3426 console.info("text span: " + (item as RichEditorTextSpanResult).value) 3427 } 3428 }) 3429 }) 3430 Button("删除选择内容").onClick(() => { 3431 this.controller.deleteSpans({ 3432 start: this.start, 3433 end: this.end 3434 }) 3435 }) 3436 } 3437 .borderWidth(1) 3438 .borderColor(Color.Red) 3439 .width("100%") 3440 .height("10%") 3441 3442 Column() { 3443 RichEditor(this.option) 3444 .onReady(() => { 3445 this.controller.addTextSpan("0123456789", 3446 { 3447 style: 3448 { 3449 fontColor: Color.Orange, 3450 fontSize: 30 3451 } 3452 }) 3453 this.controller.addImageSpan($r("app.media.icon"), 3454 { 3455 imageStyle: 3456 { 3457 size: ["57px", "57px"] 3458 } 3459 }) 3460 }) 3461 .onSelect((value: RichEditorSelection) => { 3462 this.start = value.selection[0]; 3463 this.end = value.selection[1]; 3464 this.message = "[" + this.start + ", " + this.end + "]" 3465 console.info("onSelect="+JSON.stringify(value)) 3466 }) 3467 .aboutToIMEInput((value: RichEditorInsertValue) => { 3468 console.log("---------------------- aboutToIMEInput --------------------") 3469 console.info("aboutToIMEInput="+JSON.stringify(value)) 3470 console.log("insertOffset:" + value.insertOffset) 3471 console.log("insertValue:" + value.insertValue) 3472 return true; 3473 }) 3474 .onIMEInputComplete((value: RichEditorTextSpanResult) => { 3475 console.log("---------------------- onIMEInputComplete --------------------") 3476 console.info("onIMEInputComplete="+JSON.stringify(value)) 3477 console.log("spanIndex:" + value.spanPosition.spanIndex) 3478 console.log("spanRange:[" + value.spanPosition.spanRange[0] + "," + value.spanPosition.spanRange[1] + "]") 3479 console.log("offsetInSpan:[" + value.offsetInSpan[0] + "," + value.offsetInSpan[1] + "]") 3480 console.log("value:" + value.value) 3481 }) 3482 .aboutToDelete((value: RichEditorDeleteValue) => { 3483 value.richEditorDeleteSpans.forEach(item => { 3484 console.log("---------------------- item --------------------") 3485 console.info("spanIndex=" + item.spanPosition.spanIndex) 3486 console.log("spanRange:[" + item.spanPosition.spanRange[0] + "," + item.spanPosition.spanRange[1] + "]") 3487 console.log("offsetInSpan:[" + item.offsetInSpan[0] + "," + item.offsetInSpan[1] + "]") 3488 if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') { 3489 if ((item as RichEditorImageSpanResult).valueResourceStr == "") { 3490 console.info("builder span index " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range : " + (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + 3491 (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + (item as RichEditorImageSpanResult).imageStyle[0] + ", " + (item as RichEditorImageSpanResult).imageStyle[1]) 3492 } else { 3493 console.info("image span " + (item as RichEditorImageSpanResult).valueResourceStr + ", index : " + (item as RichEditorImageSpanResult).spanPosition.spanIndex + ", range: " + 3494 (item as RichEditorImageSpanResult).offsetInSpan[0] + ", " + (item as RichEditorImageSpanResult).offsetInSpan[1] + ", size : " + 3495 (item as RichEditorImageSpanResult).imageStyle.size[0] + ", " + (item as RichEditorImageSpanResult).imageStyle.size[1]) 3496 } 3497 } else { 3498 console.info("delete text: " + (item as RichEditorTextSpanResult).value) 3499 } 3500 }) 3501 return true; 3502 }) 3503 .borderWidth(1) 3504 .borderColor(Color.Green) 3505 .width("100%") 3506 .height("30%") 3507 3508 Button("add span") 3509 .onClick(() => { 3510 let num = this.controller.addBuilderSpan(this.my_builder, { offset: this.my_offset }) 3511 console.info('addBuilderSpan return ' + num) 3512 }) 3513 Button("add image") 3514 .onClick(() => { 3515 let num = this.controller.addImageSpan($r("app.media.icon"), { 3516 imageStyle: { 3517 size: ["50px", "50px"], 3518 verticalAlign: ImageSpanAlignment.BOTTOM, 3519 layoutStyle: { 3520 borderRadius: undefined, 3521 margin: undefined 3522 } 3523 } 3524 }) 3525 console.info('addImageSpan return' + num) 3526 }) 3527 Row() { 3528 Button('builder1').onClick(() => { 3529 this.my_builder = () => { 3530 this.placeholderBuilder() 3531 } 3532 }) 3533 Button('builder2').onClick(() => { 3534 this.my_builder = () => { 3535 this.my_builder2() 3536 } 3537 }) 3538 Button('builder3').onClick(() => { 3539 this.my_builder = () => { 3540 this.placeholderBuilder3() 3541 } 3542 }) 3543 Button('builder4').onClick(() => { 3544 this.my_builder = () => { 3545 this.placeholderBuilder4() 3546 } 3547 }) 3548 } 3549 } 3550 .borderWidth(1) 3551 .borderColor(Color.Red) 3552 .width("100%") 3553 .height("70%") 3554 } 3555 } 3556} 3557``` 3558 3559 3560### 示例10 3561enableDataDetector和dataDetectorConfig使用示例 3562 3563```ts 3564@Entry 3565@Component 3566struct TextExample7 { 3567 controller: RichEditorController = new RichEditorController(); 3568 options: RichEditorOptions = { controller: this.controller }; 3569 @State phoneNumber: string = '(86) (755) ********'; 3570 @State url: string = 'www.********.com'; 3571 @State email: string = '***@example.com'; 3572 @State address: string = 'XX省XX市XX区XXXX'; 3573 @State enableDataDetector: boolean = true; 3574 @State enablePreviewText: boolean = false; 3575 @State types: TextDataDetectorType[] = []; 3576 3577 build() { 3578 Row() { 3579 Column() { 3580 RichEditor(this.options) 3581 .onReady(() => { 3582 this.controller.addTextSpan('电话号码:' + this.phoneNumber + '\n', 3583 { 3584 style: 3585 { 3586 fontSize: 30 3587 } 3588 }) 3589 this.controller.addTextSpan('链接:' + this.url + '\n', 3590 { 3591 style: 3592 { 3593 fontSize: 30 3594 } 3595 }) 3596 this.controller.addTextSpan('邮箱:' + this.email + '\n', 3597 { 3598 style: 3599 { 3600 fontSize: 30 3601 } 3602 }) 3603 this.controller.addTextSpan('地址:' + this.address, 3604 { 3605 style: 3606 { 3607 fontSize: 30 3608 } 3609 }) 3610 }) 3611 .copyOptions(CopyOptions.InApp) 3612 .enableDataDetector(this.enableDataDetector) 3613 .dataDetectorConfig({types : this.types, onDetectResultUpdate: (result: string)=>{}}) 3614 .enablePreviewText(this.enablePreviewText) 3615 .borderWidth(1) 3616 .padding(10) 3617 .width('100%') 3618 } 3619 .width('100%') 3620 } 3621 } 3622} 3623``` 3624### 示例11 3625caretColor和selectedBackgroundColor使用示例 3626``` ts 3627@Entry 3628@Component 3629struct RichEditorDemo { 3630 @State color: Color|string = "" 3631 controller: RichEditorController = new RichEditorController(); 3632 build() { 3633 Column() { 3634 Row(){ 3635 Button("改为红色").onClick(() => { 3636 this.color = Color.Red 3637 }) 3638 }.margin({top:50}) 3639 RichEditor({ controller: this.controller }) 3640 .onReady(()=>{ 3641 this.controller.addTextSpan('测试文字测试文字测试文字测试文字测试文字测试文字') 3642 }) 3643 .width("100%") 3644 .border({ width: 1, radius: 5 }) 3645 .key('RichEditor') 3646 .caretColor(this.color) //光标颜色 3647 .selectedBackgroundColor(this.color) //选中背景色 3648 .margin({top:50}) 3649 } 3650 .width('100%') 3651 } 3652} 3653``` 3654 3655 3656### 示例12 3657lineHeight和letterSpacing使用示例 3658```ts 3659@Entry 3660@Component 3661struct RichEditorDemo03 { 3662 controller: RichEditorController = new RichEditorController(); 3663 options: RichEditorOptions = { controller: this.controller }; 3664 @State start: number = -1; 3665 @State end: number = -1; 3666 @State LH:number = 50 3667 @State LS:number = 20 3668 3669 build() { 3670 Column() { 3671 Scroll(){ 3672 Column(){ 3673 Row() { 3674 Button("行高++").onClick(()=>{ 3675 this.LH = this.LH + 5 3676 this.controller.updateSpanStyle({ 3677 start: this.start, 3678 end: this.end, 3679 textStyle: 3680 { 3681 lineHeight: this.LH 3682 } 3683 }) 3684 }) 3685 Button("行高--").onClick(()=>{ 3686 this.LH = this.LH - 5 3687 this.controller.updateSpanStyle({ 3688 start: this.start, 3689 end: this.end, 3690 textStyle: 3691 { 3692 lineHeight: this.LH 3693 } 3694 }) 3695 }) 3696 Button("字符间距++").onClick(()=>{ 3697 this.LS = this.LS + 5 3698 this.controller.updateSpanStyle({ 3699 start: this.start, 3700 end: this.end, 3701 textStyle: 3702 { 3703 letterSpacing: this.LS 3704 } 3705 }) 3706 }) 3707 Button("字符间距--").onClick(()=>{ 3708 this.LS = this.LS - 5 3709 this.controller.updateSpanStyle({ 3710 start: this.start, 3711 end: this.end, 3712 textStyle: 3713 { 3714 letterSpacing: this.LS 3715 } 3716 }) 3717 }) 3718 } 3719 } 3720 }.borderWidth(1) 3721 .borderColor(Color.Red) 3722 .width("100%") 3723 .height("20%") 3724 .margin({top: 20}) 3725 3726 Scroll(){ 3727 Column() { 3728 Text("LineHeight:" + this.LH).width("100%") 3729 Text("LetterSpacing:" + this.LS).width("100%") 3730 } 3731 } 3732 .borderWidth(1) 3733 .borderColor(Color.Red) 3734 .width("100%") 3735 .height("20%") 3736 .margin({bottom: 20}) 3737 3738 Column() { 3739 RichEditor(this.options).clip(true).padding(10) 3740 .onReady(() => { 3741 this.controller.addTextSpan("012345", 3742 { 3743 style: 3744 { 3745 fontColor: Color.Orange, 3746 fontSize: 30, 3747 lineHeight: this.LH, 3748 letterSpacing: this.LS 3749 } 3750 }) 3751 this.controller.addTextSpan("6789", 3752 { 3753 style: 3754 { 3755 fontColor: Color.Black, 3756 fontSize: 30, 3757 lineHeight: this.LH, 3758 letterSpacing: this.LS 3759 } 3760 }) 3761 }) 3762 .borderWidth(1) 3763 .borderColor(Color.Green) 3764 .width(400) 3765 .height(400) 3766 } 3767 .borderWidth(1) 3768 .borderColor(Color.Red) 3769 .width("100%") 3770 .height("60%") 3771 } 3772 } 3773} 3774``` 3775 3776 3777### 示例13 3778preventDefault使用示例 3779```ts 3780@Entry 3781@Component 3782struct RichEditorDemo { 3783 controller: RichEditorController = new RichEditorController(); 3784 options: RichEditorOptions = { controller: this.controller }; 3785 3786 build() { 3787 Column({ space: 2 }) { 3788 RichEditor(this.options) 3789 .onReady(() => { 3790 this.controller.addTextSpan('RichEditor preventDefault') 3791 }) 3792 .onPaste((event?: PasteEvent) => { 3793 if (event != undefined && event.preventDefault) { 3794 event.preventDefault(); 3795 } 3796 }) 3797 .borderWidth(1) 3798 .borderColor(Color.Green) 3799 .width('100%') 3800 .height('40%') 3801 } 3802 } 3803} 3804``` 3805 3806 3807### 示例14 3808 3809当添加“ss01”特性的FontFeature属性时,数字“0”由原来的椭圆形改变为带有倒圆角形。 3810 3811```ts 3812@Entry 3813@Component 3814struct RichEditorExample { 3815 controller: RichEditorController = new RichEditorController(); 3816 options: RichEditorOptions = { controller: this.controller }; 3817 @State enableDataDetector: boolean = true; 3818 @State types: TextDataDetectorType[] = []; 3819 build() { 3820 Row() { 3821 Column() { 3822 RichEditor(this.options) 3823 .onReady(() => { 3824 this.controller.addTextSpan('This is ss01 off :' + '0000' + '\n', 3825 { 3826 style: 3827 { 3828 fontSize: 30 3829 } 3830 }) 3831 this.controller.addTextSpan('This is ss01 on :' + '0000' + '\n', 3832 { 3833 style: 3834 { 3835 fontSize: 30, 3836 fontFeature: "\"ss01\" 1" 3837 } 3838 }) 3839 }) 3840 .copyOptions(CopyOptions.InApp) 3841 .enableDataDetector(this.enableDataDetector) 3842 .dataDetectorConfig({types : this.types, onDetectResultUpdate: (result: string)=>{}}) 3843 .borderWidth(1) 3844 .padding(10) 3845 .width('100%') 3846 } 3847 .width('100%') 3848 .margin({top:150}) 3849 } 3850 } 3851} 3852``` 3853 3854 3855### 示例15 3856 3857自定义键盘弹出发生避让示例。 3858 3859```ts 3860@Entry 3861@Component 3862struct RichEditorExample { 3863 controller: RichEditorController = new RichEditorController() 3864 @State height1:string|number = '80%' 3865 @State height2:number = 100 3866 @State supportAvoidance:boolean = true; 3867 3868 // 自定义键盘组件 3869 @Builder CustomKeyboardBuilder() { 3870 Column() { 3871 Row(){ 3872 Button('增加特表情包').onClick(() => { 3873 this.controller.addTextSpan("\uD83D\uDE0A", 3874 { 3875 style: 3876 { 3877 fontColor: Color.Orange, 3878 } 3879 }) 3880 }) 3881 } 3882 Grid() { 3883 ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '#'], (item: number | string) => { 3884 GridItem() { 3885 Button(item + "") 3886 .width(110).onClick(() => { 3887 this.controller.addTextSpan(item + '', { 3888 offset: this.controller.getCaretOffset(), 3889 style: 3890 { 3891 fontColor: Color.Orange, 3892 fontSize: 30 3893 } 3894 }) 3895 this.controller.setCaretOffset(this.controller.getCaretOffset() + item.toString().length) 3896 }) 3897 } 3898 }) 3899 }.maxCount(3).columnsGap(10).rowsGap(10).padding(5) 3900 }.backgroundColor(Color.Gray) 3901 } 3902 3903 build() { 3904 Column() { 3905 Row(){ 3906 Button("20%") 3907 .fontSize(24) 3908 .onClick(()=>{ 3909 this.height1 = "20%" 3910 }) 3911 Button("80%") 3912 .fontSize(24) 3913 .margin({left:20}) 3914 .onClick(()=>{ 3915 this.height1 = "80%" 3916 }) 3917 } 3918 .justifyContent(FlexAlign.Center) 3919 .alignItems(VerticalAlign.Bottom) 3920 .height(this.height1) 3921 .width("100%") 3922 .padding({bottom:50}) 3923 RichEditor({ controller: this.controller }) 3924 // 绑定自定义键盘 3925 .customKeyboard(this.CustomKeyboardBuilder(),{ supportAvoidance: this.supportAvoidance }).margin(10).border({ width: 1 }) 3926 .borderWidth(1) 3927 .borderColor(Color.Red) 3928 .width("100%") 3929 } 3930 } 3931} 3932``` 3933 3934 3935### 示例16 3936 3937onEditingChange,isEditing使用示例。 3938 3939```ts 3940@Entry 3941@Component 3942struct RichEditor_onEditingChange { 3943 controller: RichEditorController = new RichEditorController() 3944 @State controllerIsEditing: boolean = false 3945 @Builder 3946 3947 build() { 3948 Column() { 3949 Row() { 3950 Button("点击查看编辑状态isEditing():").onClick(() => { 3951 this.controllerIsEditing = this.controller.isEditing() 3952 }) 3953 .padding(5) 3954 Text('' + this.controllerIsEditing) 3955 .width('100%') 3956 .padding(5) 3957 .fontColor(Color.Orange) 3958 .fontSize(20) 3959 } 3960 RichEditor({ controller: this.controller }) 3961 .onEditingChange((isEditing: boolean) => { 3962 console.log("Current Editing Status:" + isEditing) 3963 }) 3964 .height(400) 3965 .borderWidth(1) 3966 .borderColor(Color.Red) 3967 .width("100%") 3968 } 3969 } 3970} 3971``` 3972 3973 3974 3975### 示例17 3976 3977onWillChange,onDidChange,onCut,onCopy使用示例。 3978 3979```ts 3980@Entry 3981@Component 3982struct RichEditorExample { 3983 controller: RichEditorController = new RichEditorController() 3984 build() { 3985 Column() { 3986 RichEditor({ controller: this.controller }) 3987 .height(200) 3988 .borderWidth(1) 3989 .borderColor(Color.Red) 3990 .width("100%") 3991 .onReady(() => { 3992 this.controller.addTextSpan('测试文字TestWord', { style: { fontColor: Color.Orange, fontSize: 30 } }) 3993 this.controller.updateSpanStyle({ 3994 start: -1, 3995 end: -1, 3996 textStyle: 3997 { 3998 fontWeight: FontWeight.Bolder 3999 } 4000 }) 4001 }) 4002 .onWillChange((value: RichEditorChangeValue) => { 4003 console.log('测试log: onWillChange') 4004 console.log('rangeBefore: ' + JSON.stringify(value.rangeBefore)) 4005 console.log('print replacedSpans') 4006 value.replacedSpans.forEach((item: RichEditorTextSpanResult) => { 4007 console.log('spanPosition:' + JSON.stringify(item.spanPosition)) 4008 console.log('value:' + item.value) 4009 console.log('textStyle:' + JSON.stringify(item.textStyle)) 4010 console.log('offsetInSpan:' + item.offsetInSpan) 4011 console.log('valueResource:' + item.valueResource) 4012 console.log('paragraphStyle:' + JSON.stringify(item.paragraphStyle)) 4013 }) 4014 console.log('print replacedImageSpans') 4015 value.replacedImageSpans.forEach((item: RichEditorImageSpanResult) => { 4016 console.log('spanPosition:' + JSON.stringify(item.spanPosition)) 4017 console.log('valuePixelMap:' + JSON.stringify(item.valuePixelMap)) 4018 console.log('valueResourceStr:' + item.valueResourceStr) 4019 console.log('imageStyle:' + JSON.stringify(item.imageStyle)) 4020 console.log('offsetInSpan:' + item.offsetInSpan) 4021 }) 4022 console.log('print replacedSymbolSpans') 4023 value.replacedSymbolSpans.forEach((item: RichEditorTextSpanResult) => { 4024 console.log('spanPosition:' + JSON.stringify(item.spanPosition)) 4025 console.log('value:' + item.value) 4026 console.log('offsetInSpan:' + item.offsetInSpan) 4027 console.log('symbolSpanStyle:' + JSON.stringify(item.symbolSpanStyle)) 4028 console.log('valueResource:' + item.valueResource) 4029 console.log('paragraphStyle:' + JSON.stringify(item.paragraphStyle)) 4030 }) 4031 return true 4032 }) 4033 .onDidChange((rangeBefore: TextRange, rangeAfter: TextRange) => { 4034 console.log('测试log: onDidChange') 4035 console.log('rangeBefore:' + JSON.stringify(rangeBefore)) 4036 console.log('rangeAfter:' + JSON.stringify(rangeAfter)) 4037 }) 4038 .onCut((event:CutEvent) => { 4039 event.preventDefault!() 4040 console.log('测试log:onCut') 4041 }) 4042 .onCopy((event:CopyEvent) => { 4043 event.preventDefault!() 4044 console.log('测试log:onCopy') 4045 }) 4046 .onPaste(()=>{ 4047 console.log('测试log:onPaste') 4048 }) 4049 Text('测试文字去Hellow') 4050 .lineHeight(50) 4051 .fontSize(24) 4052 .draggable(true) 4053 .onDragStart(()=>{}) 4054 TextInput({text:'测试文字NiHao'}) 4055 .draggable(true) 4056 .margin(20) 4057 } 4058 } 4059} 4060``` 4061### 示例18 4062 4063enterKeyType,onSubmit,stopEditing使用示例。 4064 4065```ts 4066@Entry 4067@Component 4068struct SoftKeyboardEnterTypeExample { 4069 controller: RichEditorController = new RichEditorController() 4070 4071 build() { 4072 Column() { 4073 Button("停止编辑").onClick(()=>{ 4074 this.controller.stopEditing() 4075 }) 4076 RichEditor({ controller: this.controller }) 4077 .margin(10) 4078 .border({ width: 1 }) 4079 .height(200) 4080 .borderWidth(1) 4081 .borderColor(Color.Red) 4082 .width("100%") 4083 .enterKeyType(EnterKeyType.Search) 4084 .onSubmit((enterKey: EnterKeyType, event: SubmitEvent) => { 4085 console.log("trigger richeditor onsubmit" + enterKey); 4086 this.controller.addTextSpan(" type["+ enterKey +"] triggerred") 4087 event.keepEditableState(); 4088 }) 4089 }.height("100%").justifyContent(FlexAlign.Center) 4090 } 4091} 4092``` 4093 4094 4095 4096### 示例19 4097lineBreakStrategy属性值设置、更新、查询使用示例。 4098 4099```ts 4100@Entry 4101@Component 4102struct LineBreakStrategyExample { 4103 controller: RichEditorController = new RichEditorController(); 4104 private spanParagraphs: RichEditorParagraphResult[] = []; 4105 @State lineBreakOptionStr: string[] = ['GREEDY', 'HIGH_QUALITY', 'BALANCED'] 4106 @State attributeValue: string = "" 4107 @State testStr: string = "0123456789,0123456789,0123456789,0123456789,0123456789." 4108 build() { 4109 Column() { 4110 RichEditor({ controller: this.controller }) 4111 .onReady(() => { 4112 this.controller.addTextSpan(this.testStr, { 4113 style: { 4114 fontColor: Color.Black, 4115 fontSize: "32", 4116 }, 4117 paragraphStyle: { 4118 textAlign: TextAlign.Start, 4119 lineBreakStrategy: LineBreakStrategy.GREEDY 4120 } 4121 }) 4122 }) 4123 .width(400) 4124 .height(300) 4125 .margin({bottom:20}) 4126 .draggable(false) 4127 Column(){ 4128 Text('linebreak属性值为:' + this.attributeValue).fontSize(20).fontColor(Color.Black) 4129 }.margin({bottom: 10}) 4130 Column({ space: 10 }) { 4131 Button("设置折行类型GREEDY").onClick(() => { 4132 this.controller.updateParagraphStyle({ start: -1, end: -1, 4133 style: { 4134 lineBreakStrategy: LineBreakStrategy.GREEDY, 4135 } 4136 }) 4137 }) 4138 Button("设置折行类型HIGH_QUALITY").onClick(() => { 4139 this.controller.updateParagraphStyle({ start: -1, end: -1, 4140 style: { 4141 lineBreakStrategy: LineBreakStrategy.HIGH_QUALITY, 4142 } 4143 }) 4144 }) 4145 Button("设置折行类型BALANCED").onClick(() => { 4146 this.controller.updateParagraphStyle({ start: -1, end: -1, 4147 style: { 4148 lineBreakStrategy: LineBreakStrategy.BALANCED, 4149 } 4150 }) 4151 }) 4152 Divider() 4153 Row(){ 4154 Button("获取linebreak属性值").onClick(() => { 4155 this.spanParagraphs = this.controller.getParagraphs({ start: -1, end: -1 }) 4156 console.log("RichEditor getParagraphs:" + JSON.stringify(this.spanParagraphs)) 4157 this.spanParagraphs.forEach(item => { 4158 if(typeof(item as RichEditorParagraphResult)['style'] != 'undefined'){ 4159 this.attributeValue = "" 4160 console.info('lineBreakStrategy:'+ JSON.stringify((item as RichEditorParagraphResult)['style'])) 4161 this.attributeValue += this.lineBreakOptionStr[Number((item as RichEditorParagraphResult)['style'].lineBreakStrategy)]; 4162 } 4163 }) 4164 }) 4165 } 4166 } 4167 } 4168 } 4169} 4170``` 4171 4172 4173 4174### 示例20 4175属性字符串使用示例。 4176 4177```ts 4178import {LengthMetrics} from '@kit.ArkUI' 4179import {image} from '@kit.ImageKit' 4180 4181@Entry 4182@Component 4183struct Index { 4184 stringLength: number = 0; 4185 imagePixelMap: image.PixelMap | undefined = undefined; 4186 @State selection: string = ""; 4187 @State content: string = ""; 4188 @State range: string = ""; 4189 @State replaceString: string = ""; 4190 @State rangeBefore: string = ""; 4191 @State rangeAfter: string = ""; 4192 richEditorStyledString: MutableStyledString = new MutableStyledString(""); 4193 textStyle: TextStyle = new TextStyle({ 4194 fontWeight: FontWeight.Lighter, 4195 fontFamily: 'HarmonyOS Sans', 4196 fontColor: Color.Green, 4197 fontSize: LengthMetrics.vp(30), 4198 fontStyle: FontStyle.Normal 4199 }) 4200 fontStyle1: TextStyle = new TextStyle({ 4201 fontColor: Color.Blue 4202 }); 4203 fontStyle2: TextStyle = new TextStyle({ 4204 fontWeight: FontWeight.Bolder, 4205 fontFamily: 'Arial', 4206 fontColor: Color.Orange, 4207 fontSize: LengthMetrics.vp(30), 4208 fontStyle: FontStyle.Italic 4209 }) 4210 4211 controller1: RichEditorController = new RichEditorController() 4212 options1: RichEditorOptions = { 4213 controller: this.controller1 4214 }; 4215 // 创建属性字符串对象 4216 mutableStyledString: MutableStyledString = new MutableStyledString("初始属性字符串", 4217 [{ 4218 start: 0, 4219 length: 5, 4220 styledKey: StyledStringKey.FONT, 4221 styledValue: this.fontStyle1 4222 }]); 4223 styledString: StyledString = new StyledString("插入属性字符串", 4224 [{ 4225 start: 2, 4226 length: 4, 4227 styledKey: StyledStringKey.FONT, 4228 styledValue: this.fontStyle2 4229 }]); 4230 controller: RichEditorStyledStringController = new RichEditorStyledStringController(); 4231 options: RichEditorStyledStringOptions = { 4232 controller: this.controller 4233 }; 4234 // 文本内容变化回调 4235 contentChangedListener: StyledStringChangedListener = { 4236 onWillChange: (value: StyledStringChangeValue) => { 4237 this.range = '[ ' + value.range.start + ' , ' + value.range.end + ' ]'; 4238 this.replaceString = value.replacementString.getString(); 4239 return true; 4240 }, 4241 onDidChange: (rangeBefore, rangeAfter) => { 4242 this.rangeBefore = '[ ' + rangeBefore.start + ' , ' + rangeBefore.end + ' ]'; 4243 this.rangeAfter = '[ ' + rangeAfter.start + ' , ' + rangeAfter.end + ' ]'; 4244 } 4245 } 4246 4247 async aboutToAppear() { 4248 console.info("aboutToAppear initial imagePixelMap"); 4249 this.imagePixelMap = await this.getPixmapFromMedia($r('app.media.app_icon')); 4250 } 4251 4252 private async getPixmapFromMedia(resource: Resource) { 4253 let unit8Array = await getContext(this)?.resourceManager?.getMediaContent({ 4254 bundleName: resource.bundleName, 4255 moduleName: resource.moduleName, 4256 id: resource.id 4257 }) 4258 let imageSource = image.createImageSource(unit8Array.buffer.slice(0, unit8Array.buffer.byteLength)) 4259 let createPixelMap: image.PixelMap = await imageSource.createPixelMap({ 4260 desiredPixelFormat: image.PixelMapFormat.RGBA_8888 4261 }) 4262 await imageSource.release() 4263 return createPixelMap 4264 } 4265 4266 build() { 4267 Column({space: 6}) { 4268 Column() { 4269 Text("选中区信息") 4270 .fontSize(20) 4271 .width("100%") 4272 Text("selection range: " + this.selection).width("100%") 4273 Text("selection content: " + this.content).width("100%") 4274 } 4275 .width("100%") 4276 .height("10%") 4277 4278 Column() { 4279 Text("onWillChange回调信息") 4280 .fontSize(20) 4281 .width("100%") 4282 Text("range: " + this.range).width("100%") 4283 Text("replacementString: " + this.replaceString).width("100%") 4284 Text("onWillChange回调信息") 4285 .fontSize(20) 4286 .width("100%") 4287 Text("rangeBefore: " + this.rangeBefore).width("100%") 4288 Text("rangeAfter: " + this.rangeAfter).width("100%") 4289 } 4290 .borderWidth(1) 4291 .borderColor(Color.Black) 4292 .width("100%") 4293 .height("20%") 4294 4295 RichEditor(this.options) 4296 .onReady(() => { 4297 // 注册文本变化回调 4298 this.controller.onContentChanged(this.contentChangedListener); 4299 // 设定组件展示的属性字符串 4300 this.controller.setStyledString(this.mutableStyledString); 4301 }) 4302 .height("20%") 4303 .width("100%") 4304 4305 RichEditor(this.options1) 4306 .onReady(() => { 4307 this.controller1.addTextSpan("把这些文字转换成属性字符串"); 4308 }) 4309 .height("10%") 4310 .width("100%") 4311 .borderWidth(1) 4312 .borderColor(Color.Black) 4313 4314 Row({space: 2}) { 4315 Button("插入图片") 4316 .stateEffect(true) 4317 .onClick(() => { 4318 if (this.imagePixelMap !== undefined) { 4319 let imageStyledString = new MutableStyledString(new ImageAttachment({ 4320 value: this.imagePixelMap, 4321 size: { 4322 width: 50, 4323 height: 50 4324 }, 4325 layoutStyle: { 4326 borderRadius: LengthMetrics.vp(10) 4327 }, 4328 verticalAlign: ImageSpanAlignment.BASELINE, 4329 objectFit: ImageFit.Contain 4330 })) 4331 // 获取组件展示的属性字符串 4332 this.richEditorStyledString = this.controller.getStyledString(); 4333 this.richEditorStyledString.appendStyledString(imageStyledString); 4334 // 使插入图片后的属性字符串展示在组件上 4335 this.controller.setStyledString(this.richEditorStyledString); 4336 this.controller.setCaretOffset(this.richEditorStyledString.length); 4337 } 4338 }) 4339 Button("插入文本").onClick(() => { 4340 // 获取组件展示的属性字符串 4341 this.richEditorStyledString = this.controller.getStyledString(); 4342 this.richEditorStyledString.appendStyledString(this.styledString); 4343 // 使插入文本后的属性字符串展示在组件上 4344 this.controller.setStyledString(this.richEditorStyledString); 4345 this.controller.setCaretOffset(this.richEditorStyledString.length); 4346 }) 4347 Button("删除选中内容").onClick(() => { 4348 // 获取选中范围 4349 let richEditorSelection = this.controller.getSelection(); 4350 let start = richEditorSelection.start ? richEditorSelection.start : 0; 4351 let end = richEditorSelection.end ? richEditorSelection.end : 0; 4352 // 获取组件展示的属性字符串 4353 this.richEditorStyledString = this.controller.getStyledString(); 4354 this.richEditorStyledString.removeString(start, end - start); 4355 // 使删除内容后的属性字符串展示在组件上 4356 this.controller.setStyledString(this.richEditorStyledString); 4357 }) 4358 } 4359 Row({space: 2}) { 4360 Button("获取选中内容").onClick(() => { 4361 // 获取选中范围 4362 let richEditorSelection = this.controller.getSelection(); 4363 let start = richEditorSelection.start ? richEditorSelection.start : 0; 4364 let end = richEditorSelection.end ? richEditorSelection.end : 0; 4365 // 获取组件展示的属性字符串 4366 this.richEditorStyledString = this.controller.getStyledString(); 4367 this.selection = '[ ' + start + ' , ' + end + ' ]'; 4368 if (start == end) { 4369 this.content = ""; 4370 } else { 4371 this.content = this.richEditorStyledString.subStyledString(start, end - start).getString(); 4372 } 4373 }) 4374 Button("更新选中样式").onClick(() => { 4375 // 获取选中范围 4376 let richEditorSelection = this.controller.getSelection(); 4377 let start = richEditorSelection.start ? richEditorSelection.start : 0; 4378 let end = richEditorSelection.end ? richEditorSelection.end : 0; 4379 // 获取组件展示的属性字符串 4380 this.richEditorStyledString = this.controller.getStyledString(); 4381 this.richEditorStyledString.setStyle({ 4382 start: start, 4383 length: end - start, 4384 styledKey: StyledStringKey.FONT, 4385 styledValue: this.textStyle 4386 }) 4387 // 使变更样式后的属性字符串展示在组件上 4388 this.controller.setStyledString(this.richEditorStyledString); 4389 }) 4390 } 4391 Row({space: 2}) { 4392 //将属性字符串转换成span信息 4393 Button("调用fromStyledString").onClick(() => { 4394 this.controller1.addTextSpan("调用fromStyledString:" + JSON.stringify(this.controller1.fromStyledString(this.mutableStyledString))) 4395 }) 4396 //将给定范围的组件内容转换成属性字符串 4397 Button("调用toStyledString").onClick(() => { 4398 this.controller.setStyledString(this.controller1.toStyledString({ 4399 start: 0, 4400 end: 13 4401 })) 4402 }) 4403 } 4404 } 4405 } 4406} 4407 4408``` 4409 4410.gif) 4411 4412### 示例21 4413LayoutManager使用示例。 4414 4415```ts 4416@Entry 4417@Component 4418export struct Index { 4419 @State lineCount: string = "" 4420 @State glyphPositionAtCoordinate: string = "" 4421 @State lineMetrics: string = "" 4422 controller: RichEditorController = new RichEditorController(); 4423 @State textStr: string = 4424 'Hello World! 你好,世界!' 4425 4426 build() { 4427 Scroll() { 4428 Column() { 4429 Text('RichEditor组件getLayoutManager接口获取相对于组件的布局信息') 4430 .fontSize(9) 4431 .fontColor(0xCCCCCC) 4432 .width('90%') 4433 .padding(10) 4434 RichEditor({ controller: this.controller }) 4435 .borderColor(Color.Red) 4436 .borderWidth(1) 4437 .onReady(() => { 4438 this.controller.addTextSpan(this.textStr) 4439 }) 4440 .onAreaChange(() => { 4441 let layoutManager = this.controller.getLayoutManager(); 4442 this.lineCount = "LineCount: " + layoutManager.getLineCount() 4443 }) 4444 4445 Text('LineCount').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10) 4446 Text(this.lineCount) 4447 4448 Text('GlyphPositionAtCoordinate').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10) 4449 Button("相对组件坐标[150,50]字形信息") 4450 .onClick(() => { 4451 let layoutManager: LayoutManager = this.controller.getLayoutManager() 4452 let position = layoutManager.getGlyphPositionAtCoordinate(150, 50) 4453 this.glyphPositionAtCoordinate = 4454 "相对组件坐标[150,50] glyphPositionAtCoordinate position: " + position.position + " affinity: " + 4455 position.affinity 4456 }) 4457 .margin({ bottom: 20, top: 10 }) 4458 Text(this.glyphPositionAtCoordinate) 4459 4460 Text('LineMetrics').fontSize(9).fontColor(0xCCCCCC).width('90%').padding(10) 4461 Button("首行行信息、文本样式信息、以及字体属性信息") 4462 .onClick(() => { 4463 let layoutManager: LayoutManager = this.controller.getLayoutManager() 4464 let lineMetrics = layoutManager.getLineMetrics(0) 4465 this.lineMetrics = "lineMetrics is " + JSON.stringify(lineMetrics) + '\n\n' 4466 let runMetrics = lineMetrics.runMetrics 4467 runMetrics.forEach((value, key) => { 4468 this.lineMetrics += "runMetrics key is " + key + " " + JSON.stringify(value) + "\n\n" 4469 }); 4470 }) 4471 .margin({ bottom: 20, top: 10 }) 4472 Text(this.lineMetrics) 4473 } 4474 .margin({ top: 100, left: 8, right: 8 }) 4475 } 4476 } 4477} 4478``` 4479 4480 4481 4482### 示例22 4483 4484editMenuOptions 使用示例,展示设置自定义菜单扩展项的文本内容、图标、回调方法。 4485 4486```ts 4487// xxx.ets 4488@Entry 4489@Component 4490struct RichEditorExample { 4491 controller: RichEditorController = new RichEditorController(); 4492 options: RichEditorOptions = { controller: this.controller } 4493 4494 onCreateMenu(menuItems: Array<TextMenuItem>) { 4495 console.log('menuItems size=' + menuItems.length); 4496 menuItems.forEach((value, index) => { 4497 console.log('menuItem' + index + ', id=' + JSON.stringify(value)); 4498 }) 4499 let extensionMenuItems: Array<TextMenuItem> = [ 4500 { 4501 content: 'RichEditor扩展1', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension1') 4502 }, 4503 { 4504 content: 'RichEditor扩展2', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension2') 4505 }, 4506 { 4507 content: 'RichEditor扩展3', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension3') 4508 }, 4509 { 4510 content: 'RichEditor扩展4', icon: $r('app.media.startIcon'), id: TextMenuItemId.of('extension4') 4511 } 4512 ] 4513 return menuItems.concat(extensionMenuItems) 4514 } 4515 onMenuItemClicked(menuItem: TextMenuItem, textRange: TextRange) { 4516 if (menuItem.id.equals(TextMenuItemId.of('extension1'))) { 4517 console.log('click' + menuItem.content + ', textRange=' + JSON.stringify(textRange)) 4518 return true; 4519 } 4520 return false; 4521 } 4522 4523 build() { 4524 Row() { 4525 RichEditor(this.options) 4526 .onReady(() => { 4527 this.controller.addTextSpan("RichEditor扩展") 4528 }) 4529 .editMenuOptions({ 4530 onCreateMenu: (menuItems: Array<TextMenuItem>) => { 4531 return this.onCreateMenu(menuItems) 4532 }, 4533 onMenuItemClick: (menuItem: TextMenuItem, textRange: TextRange) => { 4534 return this.onMenuItemClicked(menuItem, textRange) 4535 } 4536 }) 4537 .height(200) 4538 .borderWidth(1) 4539 .borderColor(Color.Red) 4540 } 4541 } 4542} 4543``` 4544 4545 4546 4547### 示例23 4548 4549barState、enableKeyboardOnFocus、getPreviewText使用示例。 4550 4551```ts 4552// xxx.ets 4553import { JSON } from '@kit.ArkTS'; 4554 4555@Entry 4556@Component 4557struct RichEditor_example { 4558 controller: RichEditorController = new RichEditorController() 4559 options: RichEditorOptions = { controller: this.controller }; 4560 4561 controller1: RichEditorController = new RichEditorController() 4562 options1: RichEditorOptions = { controller: this.controller1 }; 4563 4564 @State e: boolean = true 4565 @State bs_num: number = 0 4566 @State bs: (BarState | undefined)[] = [BarState.Auto, BarState.On, BarState.Off, undefined] 4567 @State bs_string: (String)[] = ["Auto", "On", "Off", "undefined"] 4568 4569 build() { 4570 Column({space: 3}) { 4571 RichEditor(this.options) 4572 .onReady(() => { 4573 this.controller.addTextSpan('文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本', { 4574 style: { 4575 fontColor: Color.Black, 4576 fontSize: 15 4577 } 4578 }) 4579 }) 4580 .onDidIMEInput((value: TextRange) => { 4581 this.controller1.addTextSpan("\n" + "触发了onDidIMEInput回调,输入法本次输入内容范围为:(" + value.start + "," + value.end + ")", { 4582 style: { 4583 fontColor: Color.Gray, 4584 fontSize: 10 4585 } 4586 }) 4587 }) 4588 .onSelectionChange((value: RichEditorRange) => { 4589 this.controller1.addTextSpan("\n" + "触发了onSelectionChange回调,起始范围信息为:(" + value.start + "," + value.end + ")", { 4590 style: { 4591 fontColor: Color.Gray, 4592 fontSize: 10 4593 } 4594 }) 4595 }) 4596 .width(300) 4597 .height(100) 4598 .margin(20) 4599 .barState(this.bs[this.bs_num]) 4600 .enableKeyboardOnFocus(this.e) 4601 .enableHapticFeedback(true) 4602 4603 RichEditor(this.options1).width(300) 4604 4605 Button('设置barState为:' + this.bs_string[this.bs_num]) 4606 .height(30) 4607 .fontSize(13) 4608 .onClick(() => { 4609 this.bs_num++ 4610 if (this.bs_num > (this.bs.length - 1)) { 4611 this.bs_num = 0 4612 } 4613 }) 4614 4615 Button('设置enableKeyboardOnFocus为:' + this.e) 4616 .height(30) 4617 .fontSize(13) 4618 .onClick(() => { 4619 this.e = !this.e 4620 }) 4621 4622 Button('获取预上屏信息') 4623 .height(30) 4624 .fontSize(13) 4625 .onClick(() => { 4626 this.controller1.addTextSpan("\n获取预上屏信息:" + JSON.stringify(this.controller.getPreviewText())) 4627 }) 4628 } 4629 } 4630} 4631 4632``` 4633 4634