如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!点击下方名片关注公众号。
RichEditor是支持图文混排和文本交互式编辑的组件,通常用于响应用户的对于图文混合内容的输入操作,例如可以输入图片的评论区。下面针对RichEditor的基本使用做一个讨论。
👉🏻 创建一个RichEditor组件
创建一个RichEditor组件的方式有两种:a)不使用属性字符串构建RichEditor组件;b)使用属性字符串构建RichEditor。
⭐️ 不使用属性字符串构建方式接口定义如下:
RichEditor(value: RichEditorOptions)RichEditorOptions的类图一览如下:
其中RichEditorOptions是富文本组件初始化选项。示例代码如下:
controller: RichEditorController = new RichEditorController();options: RichEditorOptions = { controller: this.controller };RichEditor(this.options).onReady(() => {this.controller.addTextSpan('创建不使用属性字符串构建的RichEditor组件。', {style: {fontColor: Color.Black,fontSize: 15}})})
示例代码对应的效果如下:
⭐️ 使用属性字符串构建方式接口定义如下:
RichEditor(options: RichEditorStyledStringOptions)RichEditorStyledStringOptions的类图一览如下:
其中RichEditorStyledStringOptions是富文本组件初始化选项。示例代码如下:
mutableStyledString: MutableStyledString = new MutableStyledString("创建使用属性字符串构建的RichEditor组件。",[{start: 0,length: 5,styledKey: StyledStringKey.FONT,styledValue: this.fontStyle}]);controller: RichEditorStyledStringController = new RichEditorStyledStringController();options: RichEditorStyledStringOptions = {controller: this.controller};RichEditor(this.options).onReady(() => {this.controller.setStyledString(this.mutableStyledString);})
实例代码对应的效果如下:
👉🏻 为RichEditor设置属性
⭐️ 设置自定义选择菜单
bindSelectionMenu(spanType: RichEditorSpanType,content: CustomBuilder,responseType: ResponseType | RichEditorResponseType,options?: SelectionMenuOptions)// 涉及到的核心数据结构如下enum RichEditorSpanType {TEXT = 0, // Span为文字类型。IMAGE = 1, // Span为图像类型。MIXED = 2, // Span为图文混合类型。BUILDER = 3, // Span为BuilderSpan类型。}enum RichEditorResponseType{LONG_PRESS // 通过长按触发菜单弹出。RIGHT_CLICK // 通过鼠标右键触发菜单弹出。SELECT // 通过鼠标选中触发菜单弹出。}interface SelectionMenuOptions {onAppear: MenuOnAppearCallback //自定义选择菜单弹出时回调。onDisappear: Callback<void> //自定义选择菜单关闭时回调。}type MenuOnAppearCallback = (start: number, end: number) => void
其中:
spanType是菜单的类型,默认值为文字类型;
content是菜单的内容;
responseType是菜单的响应类型,默认类型为长按;
options是菜单的选项,可设置自定义选择菜单弹出或关闭时的回调。
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('组件设置了自定义菜单,长按可触发。', {style: {fontColor: Color.Black,fontSize: 18}})}).bindSelectionMenu(RichEditorSpanType.TEXT, this.SystemMenu, ResponseType.LongPress, {onDisappear: () => {this.sliderShow = false}}).width(300).height(300)SystemMenu() {Column() {Menu() {if (this.controller) {MenuItemGroup() {MenuItem({startIcon: this.theme.cutIcon,content: "剪切",labelInfo: "Ctrl+X",})MenuItem({startIcon: this.theme.copyIcon,content: "复制",labelInfo: "Ctrl+C"})MenuItem({startIcon: this.theme.pasteIcon,content: "粘贴",labelInfo: "Ctrl+V"})}}}.radius(this.theme.containerBorderRadius).clip(true).backgroundColor(Color.White).width(this.theme.defaultMenuWidth)}.width(this.theme.defaultMenuWidth)}
效果如下
⭐️ 设置光标和手柄颜色
addTextSpan(value: string, options?: RichEditorTextSpanOptions): number// options涉及的接口定义如下:interface RichEditorTextSpanOptions {offset: number //添加文本的位置。省略时,添加到所有内容的最后。当值小于0时,放在所有内容最前面;当值大于所有内容长度时,放在所有内容最后面。style: RichEditorTextStyle // 文本样式信息。省略时,使用系统默认文本信息。paragraphStyle: RichEditorParagraphStyle //段落样式。gesture: RichEditorGesture // 行为触发回调。省略时,仅使用系统默认行为。}
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('组件设置了光标手柄颜色。', {style: {fontColor: Color.Black,fontSize: 15}})}).caretColor(Color.Orange).width(300).height(300)
效果如下:
⭐️ 设置空态提示文本(placeholder)
RichEditor(this.options).placeholder("此处为提示文本...", {fontColor: Color.Gray,font: {size: 15,weight: FontWeight.Normal,family: "HarmonyOS Sans",style: FontStyle.Normal}}).width(300).height(300)
通过onReady来添加组件初始化完成后可触发的回调。示例代码如下:
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('onReady回调内容是组件内预置文本。', {style: {fontColor: Color.Black,fontSize: 15}})})
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('选中此处文本,触发onselect回调。', {style: {fontColor: Color.Black,fontSize: 15}})}).onSelect((value: RichEditorSelection) => {this.controller1.addTextSpan(JSON.stringify(value), {style: {fontColor: Color.Gray,fontSize: 10}})}).width(300).height(50)Text('查看回调内容:').fontSize(10).fontColor(Color.Gray).width(300)RichEditor(this.options1).width(300).height(70)
onWillChange的callback中:RichEditorChangeValue为图文变化信息;boolean为true时,表示当前图文允许被更改。boolean为false时,表示当前图文不允许被更改。
onDidChange的callback中:OnDidChangeCallback为图文变化前后的内容范围。
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('组件内图文变化前,触发回调。\n图文变化后,触发回调。', {style: {fontColor: Color.Black,fontSize: 15}})}).onWillChange((value: RichEditorChangeValue) => {this.controller1.addTextSpan('组件内图文变化前,触发回调:\n' + JSON.stringify(value), {style: {fontColor: Color.Gray,fontSize: 10}})return true;}).onDidChange((rangeBefore: TextRange, rangeAfter: TextRange) => {this.controller1.addTextSpan('\n图文变化后,触发回调:\nrangeBefore:' + JSON.stringify(rangeBefore) + '\nrangeAfter:' + JSON.stringify(rangeBefore), {style: {fontColor: Color.Gray,fontSize: 10}})return true;}).width(300).height(50)Text('查看回调内容:').fontSize(10).fontColor(Color.Gray).width(300)RichEditor(this.options1).width(300).height(70)
aboutToIMEInput的callback中:RichEditorInsertValue为输入法将要输入内容信息;boolean为true时,组件执行添加内容操作。boolean为false时,组件不执行添加内容操作。
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('输入法输入内容前,触发回调。\n输入法完成输入后,触发回调。' , {style: {fontColor: Color.Black,fontSize: 15}})}).aboutToIMEInput((value: RichEditorInsertValue) => {this.controller1.addTextSpan('输入法输入内容前,触发回调:\n'+JSON.stringify(value), {style: {fontColor: Color.Gray,fontSize: 10}})return true;}).onIMEInputComplete((value: RichEditorTextSpanResult) => {this.controller1.addTextSpan('输入法完成输入后,触发回调:\n'+ JSON.stringify(value), {style: {fontColor: Color.Gray,fontSize: 10}})return true;}).width(300).height(50)Text('查看回调内容:').fontSize(10).fontColor(Color.Gray).width(300)RichEditor(this.options1).width(300).height(70)
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('对此处文本进行复制粘贴操作可触发对应回调。', {style: {fontColor: Color.Black,fontSize: 15}})}).onPaste(() => {this.controller1.addTextSpan('触发onPaste回调\n', {style: {fontColor: Color.Gray,fontSize: 10}})}).width(300).height(70)
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('对此处文本进行复制粘贴操作可触发对应回调。', {style: {fontColor: Color.Black,fontSize: 15}})}).onCut(() => {this.controller1.addTextSpan('触发onCut回调\n', {style: {fontColor: Color.Gray,fontSize: 10}})}).width(300).height(70)
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('对此处文本进行复制粘贴操作可触发对应回调。', {style: {fontColor: Color.Black,fontSize: 15}})}).onCopy(() => {this.controller1.addTextSpan('触发onCopy回调\n', {style: {fontColor: Color.Gray,fontSize: 10}})}).width(300).height(70)
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('点击按钮,改变组件预设样式。', {style: {fontColor: Color.Black,fontSize: 15}})}).width(300).height(60)Button('setTypingStyle', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.controller.setTypingStyle({fontWeight: 'medium',fontColor: Color.Pink,fontSize: 15,fontStyle: FontStyle.Italic,decoration: {type: TextDecorationType.Underline,color: Color.Gray}})})
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('点击按钮在此处选中0-2位置的文本。', {style: {fontColor: Color.Black,fontSize: 15}})}).width(300).height(60)Button('setSelection(0,2)', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.controller.setSelection(0, 2)})
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('点击按钮在此处添加text。', {style: {fontColor: Color.Black,fontSize: 15}})}).width(300).height(100)Button('addTextSpan', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.controller.addTextSpan('新添加一段文字。')})
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('点击按钮在此处添加image。', {style: {fontColor: Color.Black,fontSize: 15}})}).width(300).height(100)Button('addImageSpan', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.controller.addImageSpan($r("app.media.startIcon"), {imageStyle: {size: ["57px", "57px"]}})})
TextBuilder() {Row() {Image($r('app.media.startIcon')).width(50).height(50).margin(16)Column() {Text("文本文档.txt").fontWeight(FontWeight.Bold).fontSize(16)Text("123.45KB").fontColor('#8a8a8a').fontSize(12)}.alignItems(HorizontalAlign.Start)}.backgroundColor('#f4f4f4').borderRadius("20").width(220)}Button('addBuilderSpan', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.my_builder = () => {this.TextBuilder()}this.controller.addBuilderSpan(this.my_builder)})
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('点击按钮在此处添加symbol。', {style: {fontColor: Color.Black,fontSize: 15}})}).width(300).height(100)Button('addSymbolSpan', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.controller.addSymbolSpan($r("sys.symbol.basketball_fill"), {style: {fontSize: 30}})})
RichEditor(this.options).onReady(() => {this.controller.addTextSpan('点击按钮获取此处span信息。', {style: {fontColor: Color.Black,fontSize: 15}})}).width(300).height(50)Text('查看getSpans返回值:').fontSize(10).fontColor(Color.Gray).width(300)RichEditor(this.options1).width(300).height(50)Button('getSpans', {buttonStyle: ButtonStyleMode.NORMAL}).height(30).fontSize(13).onClick(() => {this.controller1.addTextSpan(JSON.stringify(this.controller.getSpans()), {style: {fontColor: Color.Gray,fontSize: 10}})})