React-Native实现emoji表情图文混排方案

前端之家收集整理的这篇文章主要介绍了React-Native实现emoji表情图文混排方案前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言


在IM通讯软件中,基本上都会有emoji表情功能。聊天气泡中要显示文字和emoji表情的混排(下图所示),在原生iOS开发时,可以用富文本NSAttributedString实现,安卓中用SpannableString实现。当用到React-Native来开发这个功能的时候,貌似没有直接的现成的实现方案。经过一番努力,这个功能已经在项目中实现 ,在此记录。



思路


假设有一条信息在输入框是这样的:“假设[微笑]有一条信息[龇牙]是这样的”
[微笑],[龇牙]都是emoji表情的名称

处理步骤如下:
1.运用正则表达式将表情名称识别出来,然后把这条文本截成数组:
[
{content:假设},
{resource:[微笑]},
{content:有一条信息},
{resource:[龇牙]},
{content:是这样的}
]
2.根据这个数组进行组件排列,key是content的话放置Text,key是resources的话放置Image,一字排开。

字符串转成数组


1.编写正确的正则表达式;
2.根据正则表达式匹配出所有的表情名称,把他们在字符串中的位置用数组记录;
3.根据记录位置的数组,截断字符串;
4.组成相应的数组。

代码
export function stringToContentArray(text) {
    //text = "wwww[微笑]eeee[鬼脸]asdfasfasd[大笑]w222";
    var regex = new RegExp('\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]','g');
    var contentArray = [];
    var regArray = text.match(regex);
    console.log(regArray);
    if (regArray === null) {
        contentArray.push({"Content" : text});
        return contentArray;
    }

    var indexArray = [];
    var pos = text.indexOf(regArray[0]);//头
    for (let i = 1; i < regArray.length; i++) {
        indexArray.push(pos);
        pos = text.indexOf(regArray[i],pos + 1);
    }
    indexArray.push(pos);//尾

    console.log("indexArray = ",indexArray);
    for (let i=0; i<indexArray.length; i++) {
        if (indexArray[i] === 0) {//一开始就是表情
            contentArray.push({"Resources" : EMOTION_GIF_NAME[regArray[i]],attr: {Type:"0"}});
        } else {
            if (i === 0) {
                contentArray.push({"Content" : text.substr(0,indexArray[i])});
            } else {
                if (indexArray[i] - indexArray[i-1] - regArray[i-1].length > 0) {//两个表情相邻,中间不加content
                    contentArray.push({"Content" : text.substr(indexArray[i-1] + regArray[i-1].length,indexArray[i] - indexArray[i-1] - regArray[i-1].length)});
                }
            }
            contentArray.push({"Resources" : EMOTION_GIF_NAME[regArray[i]],attr: {Type:"0"}});
        }
    }

    let lastLocation = indexArray[indexArray.length - 1] + regArray[regArray.length - 1].length;
    if (text.length > lastLocation) {
        contentArray.push({"Content": text.substr(lastLocation,text.length - lastLocation)});
    }
    return contentArray;
}

根据数组排列组件

此步骤方法较多,可以用数组的map实现。贴上一段代码

analyseComponent() {
    if (!this.props.currentMessage.hasOwnProperty("contentArray")) {
      this.props.currentMessage.contentArray = MessageProvider.stringToContentArray(this.props.currentMessage.text);
    }
    let objArray = [];
    for (let subObj of this.props.currentMessage.contentArray) {
      objArray.push(this.renderSubObj(subObj));
    }
    return(
      <View style = {styles[this.props.position].container}>
        {objArray}
      </View>
    );
  }

  renderSubObj(subObj) {
    if (subObj["Content"] != null) {//文本
        return (
           <ParsedText
              style={[styles[this.props.position].text,this.props.textStyle[this.props.position]]}
              parse={[
                {type: 'url',style: StyleSheet.flatten([styles[this.props.position].link,this.props.linkStyle[this.props.position]]),onPress: this.onUrlPress},{type: 'phone',onPress: this.onPhonePress},{type: 'email',onPress: this.onEmailPress},]}
            >
              {subObj["Content"]}
            </ParsedText>
        );
      } else if (subObj["Resources"] != null) {//emoji
        return (
          <Image 
            style = {styleEmoji.emoji}
            source={EMOTION_PATH[subObj["Resources"]]}
          > 
          </Image>
        );
      }
  }

  render() {
    console.log("----------contentArray:" + this.props.currentMessage.contentArray);
    return (
      <View style={[styles[this.props.position].container,this.props.containerStyle[this.props.position]]}>
        {this.analyseComponent()}

      </View>
    );
  }
}

猜你在找的React相关文章