偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

我們一起聊聊鴻蒙富文本實(shí)踐

系統(tǒng) 其他OS
想要實(shí)現(xiàn)表情圖片自動(dòng)匹配,首先就需要先有表情圖片,要有對(duì)應(yīng)的表情配置表,項(xiàng)目中的表情配置分程序內(nèi)置默認(rèn)配置與線上后臺(tái)下發(fā)配置。

1.鴻蒙中的文本展示-Text組件

Text 組件的普通用法和其他語(yǔ)言一樣,可以直接使用字符串Text('我是一段文本')

通過(guò)點(diǎn)語(yǔ)法設(shè)置文本樣式:

Text('我是超長(zhǎng)文本,超出的部分顯示省略號(hào)。I am an extra long text, with ellipses displayed for any excess。')
  .width(250)
  .textOverflow({ overflow: TextOverflow.Ellipsis })
  .maxLines(1)
  .fontSize(12)
  .border({ width: 1 })
  .padding(10)

也可以將 Text 組件作為容器,添加 SpanImageSpan,針對(duì)每段文本設(shè)置不同的樣式并且統(tǒng)一換行,ImageSpan 可以展示本地圖片與網(wǎng)絡(luò)圖片:

Text() {
  Span('我是Span1,').fontSize(16).fontColor(Color.Grey)
    .decoration({ type: TextDecorationType.LineThrough, color: Color.Red })
  Span('我是Span2').fontColor(Color.Blue).fontSize(16)
    .fontStyle(FontStyle.Italic)
    .decoration({ type: TextDecorationType.Underline, color: Color.Black })
  Span(',我是Span3').fontSize(16).fontColor(Color.Grey)
    .decoration({ type: TextDecorationType.Overline, color: Color.Green })
}
.borderWidth(1)
.padding(10)

圖片圖片

// xxx.ets
@Entry
@Component
struct SpanExample {
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Text() {
        Span('This is the Span and ImageSpan component').fontSize(25).textCase(TextCase.Normal)
          .decoration({ type: TextDecorationType.None, color: Color.Pink })
      }.width('100%').textAlign(TextAlign.Center)

      Text() {
        ImageSpan($r('app.media.icon'))
          .width('200px')
          .height('200px')
          .objectFit(ImageFit.Fill)
          .verticalAlign(ImageSpanAlignment.CENTER)
        Span('I am LineThrough-span')
          .decoration({ type: TextDecorationType.LineThrough, color: Color.Red }).fontSize(25)
        ImageSpan($r('app.media.icon'))
          .width('50px')
          .height('50px')
          .verticalAlign(ImageSpanAlignment.TOP)
        Span('I am Underline-span')
          .decoration({ type: TextDecorationType.Underline, color: Color.Red }).fontSize(25)
        ImageSpan($r('app.media.icon'))
          .size({ width: '100px', height: '100px' })
          .verticalAlign(ImageSpanAlignment.BASELINE)
        Span('I am Underline-span')
          .decoration({ type: TextDecorationType.Underline, color: Color.Red }).fontSize(25)
        ImageSpan($r('app.media.icon'))
          .width('70px')
          .height('70px')
          .verticalAlign(ImageSpanAlignment.BOTTOM)
        Span('I am Underline-span')
          .decoration({ type: TextDecorationType.Underline, color: Color.Red }).fontSize(50)
      }
      .width('100%')
      .textIndent(50)
    }.width('100%').height('100%').padding({ left: 0, right: 0, top: 0 })
  }
}

圖片圖片

這樣通過(guò) Span、ImageSpan 混排就實(shí)現(xiàn)了基礎(chǔ)的圖文混排。

2.表情圖片自動(dòng)匹配

對(duì)于實(shí)際中的實(shí)操,往往不是固定寫(xiě)好的混排代碼,而是需要針對(duì)后端下發(fā)的數(shù)據(jù)自動(dòng)進(jìn)行轉(zhuǎn)譯。比如帶表情的文本。

項(xiàng)目中的自定義表情一般會(huì)以配置表的形式進(jìn)行管理:

{"imageName":"icon_emotion_1","description":"[微笑]","id":44},{"imageName":"icon_emotion_2","description":"[嘻嘻]","id":43}

用特殊格式的字符串,如:"[微笑]"、"[嘻嘻]",來(lái)分別對(duì)應(yīng)相應(yīng)的表情圖片。

而后端下發(fā)的數(shù)據(jù)則只是一段包含表情關(guān)鍵字的普通文本,并且沒(méi)有額外下發(fā)表情文本的位置信息,如:"第一次見(jiàn)面她幫他出頭,他被她拽拽的氣質(zhì)吸引,對(duì)她一見(jiàn)鐘情,多年后重逢續(xù)寫(xiě)故事[色]這該死的羈絆~",轉(zhuǎn)換后為:

圖片圖片

這樣就需要將文本切塊,把本文中的表情關(guān)鍵字提取出來(lái)。上面的文本就轉(zhuǎn)換為:"第一次見(jiàn)面她幫他出頭,他被她拽拽的氣質(zhì)吸引,對(duì)她一見(jiàn)鐘情,多年后重逢續(xù)寫(xiě)故事"、"[色]"、"這該死的羈絆~"。切塊的過(guò)程采用正則匹配方式。

首先,需要將表情配置表中的所有關(guān)鍵字整合加工為正則匹配字符串:"[微笑]|[嘻嘻]|[哭笑]...",這樣只要目標(biāo)文本中包含任意一個(gè)關(guān)鍵字,都可以獲得匹配結(jié)果。在加工正則字符串的過(guò)程中,同時(shí)將表情關(guān)鍵字與圖片名組裝為鍵值對(duì)表:["[微笑]":"icon_emotion_1","[嘻嘻]":"icon_emotion_2",...],用以后續(xù)獲取轉(zhuǎn)譯圖片。

鴻蒙中的正則匹配代碼:

let reg = RegExp(EmoticonManager.getInstance().emojiRegExpStr,'g') //正則匹配串
let result: IterableIterator<RegExpMatchArray> = content.matchAll(reg)//可迭代匹配結(jié)果
let next = result.next()//第一個(gè)結(jié)果
while (next.done == false) {
 let matchArr: RegExpMatchArray = next.value
  
  //分割字符串
  
 next = result.next() //下一個(gè)結(jié)果
}

注意項(xiàng):RegExp(xxx,'g') ,'g' 代表貪婪模式,會(huì)返回所有匹配結(jié)果,不然只會(huì)獲取第一個(gè)匹配結(jié)果。

最終將文本 "第一次見(jiàn)面她幫他出頭,他被她拽拽的氣質(zhì)吸引,對(duì)她一見(jiàn)鐘情,多年后重逢續(xù)寫(xiě)故事[色]這該死的羈絆~" 轉(zhuǎn)換為數(shù)據(jù)模型數(shù)組:

[
 [
  content: "第一次見(jiàn)面她幫他出頭,他被她拽拽的氣質(zhì)吸引,對(duì)她一見(jiàn)鐘情,多年后重逢續(xù)寫(xiě)故事",
  type: Text,
  resource: NULL
 ],
 [
  content: "[色]",
  type: Emoji,
  resource: xxxx
 ],
 [
  content: "這該死的羈絆~",
  type: Text,
  resource: NULL
 ]
]

再在 Text 組件中遍歷組裝:

Text(){
 ForEach(this.model.getDecodedContentArr(), (element: CommentTextModel) => {
  if (element.type == CommentTextType.Text) {
      Span(element.content)
        .onClick(() => {
         this.openCommentInput()
       })
    }
    if (element.type == CommentTextType.Emoji && element.resource != null) {
      ImageSpan(element.resource)
        .width(EmoticonManager.emojiSideLengthForFontSize(this.contentFontSize))
        .height(EmoticonManager.emojiSideLengthForFontSize(this.contentFontSize))
        .verticalAlign(ImageSpanAlignment.CENTER)
        .onClick(() => {
         this.openCommentInput()
       })
    }
  })
}

這樣就完成了字符串到帶圖富文本的自動(dòng)轉(zhuǎn)換。

2.1 表情配置管理

想要實(shí)現(xiàn)表情圖片自動(dòng)匹配,首先就需要先有表情圖片,要有對(duì)應(yīng)的表情配置表,項(xiàng)目中的表情配置分程序內(nèi)置默認(rèn)配置與線上后臺(tái)下發(fā)配置。

2.1.1 本地配置

我們采用字符串的形式,將配置表保存到管理類的靜態(tài)屬性中:

export class LocalEmoticon {
  static readonly data = '{"emoticons":[{"imageName":"icon_emotion_1","description":"[微笑]","id":44},{"imageName":"icon_emotion_2","description":"[嘻嘻]","id":43},{"imageName":"icon_emotion_3","description":"[笑哭]","id":42}, ... ]}'
}

這樣讀取字符串后直接映射就可以得到序列化好的類型數(shù)據(jù):

let jsonString = LocalEmoticon.data
const model = plainToClass(EmoticonConfigModel,JSON.parse(jsonString))

表情圖片文件直接放置在 resources -> base -> media 文件夾中,獲取的時(shí)候直接通過(guò):

let str = 'app.media.' + imageName
let resourceStr = $r(str)

獲取 ResourceStr ,這里選取 media 文件夾是因?yàn)?運(yùn)行中生成的字符串不生效,但是r 可以

圖片圖片

2.1.2 線上配置

線上配置會(huì)下發(fā)配置表數(shù)據(jù)以及對(duì)應(yīng)的圖片壓縮包下載地址,配置表和本地配置一樣讀取并序列化就可以,但是圖片文件需要先下載到沙盒文件夾中再訪問(wèn)。

鴻蒙中下載文件需要使用 request.downloadFile ,下載到指定的文件夾目錄后再使用 zlib.decompressFile 解壓縮到圖片存儲(chǔ)目錄。

讀取的時(shí)候拼接出文件地址,再通過(guò) fileUri 獲取文件 uri 字符串就可以:

let path = EmoticonManager.getInstance().folderPath() + '/' + imageName
return fileUri.getUriFromPath(path)

這樣無(wú)論是本地配置還是線上配置獲取到的圖片資源都統(tǒng)一成了 ResourceStr 類型,直接丟給 ImageSpan 就可以加載出對(duì)應(yīng)圖片。

3.富文本輸入框

輸入框選用 RichEditor 組件。RichEditor 通過(guò)綁定 RichEditorController 來(lái)控制布局樣式和插入富文本內(nèi)容。

圖片圖片

圖片圖片

3.1 自定義表情面板

通過(guò) customKeyboard 傳入自定義組件,并在點(diǎn)擊事件中通過(guò) RichEditorController 來(lái)控制輸入框的插入和刪除:

RichEditor({controller:this.editorController})
  .key(this.editorKey)
  .customKeyboard(this.useCustomKeyboard ? this.emojiKeyboard():undefined)

//自定義鍵盤(pán)實(shí)體
@Builder emojiKeyboard() {
  EmojiKeyboard({
    currentWidth:this.currentWidth,
    emojiOnClick: (model) => { this.emojiOnClick(model) },
    deleteOnClick: () => { this.emojiOnDelete() }})
    .backgroundColor('#F2F5F7')
    .width('100%')
    .height(this.emojiKeyboardHeight)
    .onAreaChange((oldValue:Area,newValue:Area) => {
     if (typeof newValue.width === 'number') {
        this.currentWidth = newValue.width as number
      }
  })
}

//插入圖片
emojiOnClick(model: EmoticonModel) {
  this.editorController.addImageSpan(
    EmoticonManager.getInstance().getPixelMap(model.description),
    {imageStyle: {
      size:[EmoticonManager.emojiSideLengthForFontSize(this.fontSize),
            EmoticonManager.emojiSideLengthForFontSize(this.fontSize)],
      verticalAlign:ImageSpanAlignment.CENTER },
     offset: this.editorController.getCaretOffset() })
  }

//刪除按鈕點(diǎn)擊
emojiOnDelete() {
  const currentIndex = this.editorController.getCaretOffset() //獲取光標(biāo)位置
  if (currentIndex > 0) {
    this.editorController.deleteSpans({start:currentIndex-1,end:currentIndex})//從光標(biāo)位置向前刪除
  }
}

圖片圖片

3.2 獲取已輸入內(nèi)容

想要將輸入的富文本作為評(píng)論發(fā)送出去,還需要拿到轉(zhuǎn)譯之前的原始字符串,但是鴻蒙不是像 iOS 一樣給文字掛載樣式掛載圖片。iOS 這種給圖文掛載樣式的實(shí)現(xiàn)原始文字一直都在,直接獲取就可以了。鴻蒙的輸入框中的文字是文字組件,圖片是圖片組件,而且圖片組件里面只有圖片相關(guān)的屬性,沒(méi)有關(guān)聯(lián)文字的地方。只能先獲取所有組件,再反向轉(zhuǎn)譯。獲取全部組件是通過(guò) RichEditorController 的 getSpans API 。

圖片圖片

但是從上面的截圖可以看到 getSpans 所獲取到的數(shù)組,內(nèi)容物是聯(lián)合類型,轉(zhuǎn)譯之前就需要先判斷。鴻蒙沒(méi)有像iOS isKindOfClass 一樣的判斷方法,由于 RichEditorImageSpanResult 比 RichEditorTextSpanResult 多了一個(gè) imageStyle 屬性,鴻蒙官方推薦使用判斷該屬性是不是 undefined 的方式來(lái)區(qū)分類型:

if (typeof (element as RichEditorImageSpanResult)['imageStyle'] != 'undefined')

區(qū)分出類型之后,文字組件 RichEditorTextSpanResult 直接獲取 .value 就可以獲取到文字。圖片組件 RichEditorImageSpanResult 就麻煩一些,首先通過(guò) .valueResourceStr 可以獲取到圖片的資源路徑 resource:///icon_emotion_8.png ,刨除協(xié)議頭 resource:/// 與文件后綴 .png ,就得到了圖片名 icon_emotion_8,通過(guò)配置表可以匹配到對(duì)應(yīng)的表情關(guān)鍵字"[鼓掌]"。這樣按照順序?qū)⑽淖纸M裝起來(lái),就實(shí)現(xiàn)了富文本的反向轉(zhuǎn)譯。

責(zé)任編輯:武曉燕 來(lái)源: 搜狐技術(shù)產(chǎn)品
相關(guān)推薦

2023-04-07 07:14:34

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-08-04 08:20:56

DockerfileDocker工具

2023-06-30 08:18:51

敏捷開(kāi)發(fā)模式

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-09-10 21:42:31

2024-02-20 21:34:16

循環(huán)GolangGo

2021-08-27 07:06:10

IOJava抽象

2023-11-03 12:54:00

KAFKA探索中間件

2023-03-26 23:47:32

Go內(nèi)存模型

2024-07-26 09:47:28

2022-10-08 00:00:05

SQL機(jī)制結(jié)構(gòu)

2022-02-23 08:41:58

NATIPv4IPv6

2022-09-22 08:06:29

計(jì)算機(jī)平板微信

2024-11-28 09:57:50

C#事件發(fā)布器

2021-08-12 07:49:24

mysql

2023-07-24 09:41:08

自動(dòng)駕駛技術(shù)交通

2022-10-28 07:27:17

Netty異步Future

2022-11-12 12:33:38

CSS預(yù)處理器Sass

2022-06-26 09:40:55

Django框架服務(wù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)