往期推文全新看點(文中附帶全新鴻蒙5.0全棧學習筆錄)
?? 鴻蒙(HarmonyOS)北向開發知識點記錄~
?? 鴻蒙(OpenHarmony)南向開發保姆級知識點匯總~
?? 鴻蒙應用開發與鴻蒙系統開發哪個更有前景?
?? 嵌入式開發適不適合做鴻蒙南向開發?看完這篇你就了解了~
?? 對于大前端開發來說,轉鴻蒙開發究竟是福還是禍?
?? 鴻蒙崗位需求突增!移動端、PC端、IoT到底該怎么選?
?? 記錄一場鴻蒙開發崗位面試經歷~
?? 持續更新中……
場景描述
RichEditor是支持圖文混排和文本交互式編輯的組件,在我們使用的APP中是很常見的,比如評論區編輯內容發布、對話框或者聊天室。下面列舉一些遇到的場景需求:
- 場景一:基于文字圖片以及@信息的好友評論
- 場景二:右下角的剩余字數
- 場景三:評論中攜帶所@的用戶的附屬信息
- 場景四:文本選擇區域發生變化或編輯狀態下光標位置發生變化回調
- 場景五:自由切換系統鍵盤和自定義鍵盤。
方案描述
場景一:基于文字圖片以及@信息的好友評論
效果圖
方案
1、通過addTextSpan來添加文字,2、通過addImageSpan來添加圖片3、通過addBuilderSpan來實現一段內容光標不可插入的效果4、addTextSpan等支持gesture等手勢操作,比如onClick點擊和onLongPress長按事件
核心代碼
1、由于RichEditor是支持圖文混排的,所以RichEditor里面的內容也就是由Text和Image組成的,分別通過addTextSpan和addImageSpan添加,而且還可以設置字體和圖片樣式,如下代碼1:
@Entry@Componentstruct getSpans {editorController = new RichEditorController()build() {Column() {RichEditor({ controller: this.editorController }).width('100%').backgroundColor(Color.Yellow).onReady(() => {this.editorController.addImageSpan($r("app.media.icon"),{imageStyle:{size: ["100px", "100px"]}})this.editorController.addTextSpan('男生女生向前沖',{style:{fontColor: Color.Blue,fontSize: 30}})})Button('getSpans-圖片').onClick((event: ClickEvent) => {let getSpans = this.editorController.getSpans({ start: 0 })console.log('getSpans0' + JSON.stringify(getSpans[0]))// 必須進行強轉才能獲取文字信息或者圖片信息let span0 = getSpans[0] as RichEditorTextSpanResultconsole.log('圖片相關的信息: ' + JSON.stringify(span0))})Button('getSpans-文字').onClick((event: ClickEvent) => {let getSpans = this.editorController.getSpans({ start: 0 })console.log('getSpans1' + JSON.stringify(getSpans[1]))let span1 = getSpans[1] as RichEditorImageSpanResultconsole.log('文字相關的信息: ' + JSON.stringify(span1))})}}}
2、在常見的評論區艾特好友時,會將“@華為官方客服”視作一個整體,光標無法插入其中,且第一次按刪除鍵時整體會高亮選中,第二次再按刪除鍵才會刪除。**需要注意的是,如果使用的全局@Builder,則需要配合bind(this)使用。**后續也可以通過事件阻止“即RichEditor控件ClickEvent/TouchEvent支持preventDefault”。
@Entry@Componentstruct BuilderSpan {editorController = new RichEditorController()@BuilderAt(str: string) {Stack() {Text('@' + str).fontColor(Color.Blue)}}build() {Column() {RichEditor({ controller: this.editorController }).width('100%').height(50).backgroundColor(Color.Yellow).onReady(() => {this.editorController.addBuilderSpan(() => {this.At('華為官方客服')})this.editorController.addTextSpan('!!!')})}}}
3、發微博的時候可以輸入表情、超鏈接、文字等一起的內容
代碼3:
@Componentstruct Index {@State message: string = '#超話社區#';controller: RichEditorController = new RichEditorController();@State show: boolean = false;build() {Column() {RichEditor({controller: this.controller}).height(56).width("90%").borderStyle(BorderStyle.Solid).borderColor(Color.Black).borderWidth(1).onReady(() => {})Button('輸入表情').onClick((event: ClickEvent) => {this.controller.addImageSpan($r('app.media.app_icon'), {imageStyle: {size: ["80px", "80px"]}})})Button('超鏈接').onClick((event: ClickEvent) => {this.controller.addTextSpan(this.message, {offset: this.controller.getCaretOffset(),style:{fontColor: Color.Orange,fontSize: 16},gesture:{onClick: () => {console.log('要跳轉鏈接了哦')},onLongPress: () => {console.log('我被長按了')}}})this.controller.setCaretOffset(this.controller.getCaretOffset() + this.message.length)})}.width('100%')}}
場景二:右下角的剩余字數
效果圖
方案
使用overlay浮層,顯示“0/20”字數提示符在組件的右下角。再通過aboutToIMEInput回調(輸入法輸入內容前),獲取插入的文本偏移位置,對輸入內容進行限制。
核心代碼
import promptAction from '@ohos.promptAction';@Entry@Componentstruct MaxDemo {@State message: string = '蠟筆小新';controller: RichEditorController = new RichEditorController();@State getContentLength: number = 0;@State BOnSt:promptAction.ShowToastOptions = {'message': '已超出內容最大限制.'}build() {Column() {RichEditor({ controller: this.controller }).height(100).borderWidth(1).borderColor(Color.Red).width("100%").overlay(this.getContentLength + "/20", {align: Alignment.BottomEnd}).aboutToIMEInput((value: RichEditorInsertValue) => {console.log("insertOffset:" + JSON.stringify(value.insertValue)) // 插入的文本偏移位置。if (this.getContentLength < 20) {this.getContentLength = this.getContentLength + value.insertValue.lengthconsole.log('實時的內容長度:' + this.getContentLength)return true}promptAction.showToast(this.BOnSt)return false}).aboutToDelete((value: RichEditorDeleteValue) => {console.log('刪除:' + JSON.stringify(value))this.getContentLength = this.getContentLength - value.lengthreturn true})}.width('100%')}}
場景三:評論中攜帶所@的用戶的附屬信息
效果圖
方案
使用HashMap的set向HashMap中添加或更新一組數據,使用get方法獲取指定key所對應的value。
核心代碼
@Entry@Componentstruct SameNameDemo {controller: RichEditorController = new RichEditorController();@BuilderAt(str: string) {Stack() {Text('@' + str).fontColor(Color.Blue)}.onClick(() => {// 添加不同的身份信息const hashMap: HashMap<string, number> = new HashMap();hashMap.set("friend1", 123);let result = hashMap.get("friend1");console.log('result: ' + result)})}build() {Column() {RichEditor({ controller: this.controller }).height(100).borderWidth(1).borderColor(Color.Red).width("100%")Button('好友1').onClick((event: ClickEvent) => {this.controller.addBuilderSpan(() => {this.At('華為官方客服')})})Button('好友2').onClick((event: ClickEvent) => {this.controller.addBuilderSpan(() => {this.At('華為官方客服')})})}.width('100%')}}
場景四:文本選擇區域發生變化或編輯狀態下光標位置發生變化回調
效果圖
方案
使用RichEditor組件在API 12支持的新接口 onSelectionChange,在文本選擇區域發生變化或編輯狀態下光標位置發生變化時觸發該回調。光標位置發生變化回調時,選擇區域的起始位置等于終止位置(即start = end)。
核心代碼
@Entry@Componentstruct Index {@State message: string = '蠟筆小新';controller: RichEditorController = new RichEditorController();@State show: boolean = false;build() {Column() {RichEditor({controller: this.controller}).defaultFocus(true).padding(0).height(56).width("90%").borderStyle(BorderStyle.Solid).borderColor(Color.Black).borderWidth(1).padding({left: 10}).onReady(() => {this.controller.addTextSpan(this.message, {offset: this.controller.getCaretOffset(),style:{fontColor: Color.Orange,fontSize: 16}})this.controller.setCaretOffset(this.controller.getCaretOffset() + this.message.length)}).onSelectionChange((value:RichEditorRange) => {console.log('光標位置改變了')console.log('start: ' + value.start)console.log('end: ' + value.end)})}.width('100%')}}
場景五:自由切換系統鍵盤和自定義鍵盤
效果圖
方案
使用RichEditor的屬性customKeyboard控制切換系統鍵盤還是自定義鍵盤,添加表情使用addImageSpan,刪除內容使用deleteSpans,并通過獲取光標所在位置進行刪除。
核心代碼
@Entry@Componentstruct Index {@State message: string = 'Hello World';controller = new RichEditorController()@State showKeyboard:boolean = false;private listData: (string | number | Resource)[] = [$r('app.media.img'), $r('app.media.img_1'), $r('app.media.img_2'), $r('app.media.img_3'), $r('app.media.img_4'), $r('app.media.img_5'), $r('app.media.img_6'),$r('app.media.img'), $r('app.media.img_1'), $r('app.media.img_2'), $r('app.media.img_3'), $r('app.media.img_4'), $r('app.media.img_5'), $r('app.media.img_6'),$r('app.media.img'), $r('app.media.img_1'), $r('app.media.img_2'), $r('app.media.img_3'), $r('app.media.img_4'), $r('app.media.img_5'), $r('app.media.img_6'),$r('app.media.img'), $r('app.media.img_1'), $r('app.media.img_2'), $r('app.media.img_3'), $r('app.media.img_4'), $r('app.media.img_5'), $r('app.media.img_6'),$r('app.media.img'), $r('app.media.img_1'), $r('app.media.img_2'), $r('app.media.img_3'), $r('app.media.img_4'), $r('app.media.img_5'), $r('app.media.img_6'),];// 自定義鍵盤組件@Builder CustomKeyboardBuilder() {Column() {Text('自定義表情鍵盤').fontSize(25).fontWeight(900)Grid() {ForEach(this.listData, (item: string | number | Resource) => {GridItem() {if (typeof item !== 'number' && typeof item !== 'string') {Image(item).width(30).onClick(() => {this.controller.addImageSpan(item, { imageStyle: { size: ['110px', '110px'] } })})}}})}.columnsGap(10).rowsGap(10).padding(5)Row() {Image($r('app.media.img_7')).width(30).onClick(() => {this.controller.deleteSpans({start: this.controller.getCaretOffset() - 1, end: this.controller.getCaretOffset()})})}.width('100%').justifyContent(FlexAlign.End).margin({ bottom: 40 })}.borderColor(Color.Gray).borderWidth(5)}build() {Column() {RichEditor({ controller: this.controller }).width('100%').borderWidth(1).borderColor(Color.Black).onReady(() => {this.controller.addTextSpan('有序排隊')}).customKeyboard(this.showKeyboard ? this.CustomKeyboardBuilder() : undefined)Button('切換系統鍵盤與自定義鍵盤').onClick((event: ClickEvent) => {this.showKeyboard = ! this.showKeyboard})}.height('100%')}}