• cocos2dx 富文本框,支持换行,支持神情(支持汉字截断无乱码)


    cocos2dx 富文本框,支持换行,支持表情(支持汉字截断无乱码)

    小工在做了一个游戏聊天功能,里面用到插入表情的富文本和换行的问题;

    先看效果,不是你要的效果,可return;(截图由于:输入的问题,未能输入汉字)

    实现方式;

    定义一个layer,在layer上摆放文本,表情,按钮,等控件,由此来形成一个多控件组成的一个富文本;

    表情:仿照QQ,用的是【xy】这种方式来表示,如【00】,对应资源就是00.png

    换行:就是是把超出指定宽度的内容回车,实现换行(主要是坐标x=起始位置)当然涉及到表情等,容易出问题;

    例子

    string m_sString = “待到山花烂漫时,他在花丛中笑【12】丛中笑【12】丛中笑【12】丛中笑【12】”;

     

    下面伪代码实现

    处理string 得到string的真实个数长度,一个汉字,一个字母代表一个长度;

    创建循环体,分别来遍历没一个汉字或者是字母+特殊字符等,遇到【就判断是否是表情,如果是表情就添加表情,表情添加之前需要将表情之前的汉字等先排列上,表情排列后继续,进行遍历;

    如果发现当前遍历的内容所占的屏幕长度就进行换行。表情的长度=getContextSize().width 来获取;

     

     

     

    具体实现如代码

    void MessageItem::changeLine()
    
    {  
        CCArray *array = getChildren();
        for (int i=0; i<array->count(); i++) {
            CCNode* node =(CCNode*) array->objectAtIndex(i);
            node->setPositionY(m_iDefaultSize);
        }
    }
    
    
    void MessageItem::showText(const ccColor3B cColor3B )
    {
        bool bDoubleLine=false;
        int posX= 0;//读取内容的长度小标
        int iMsgEnd = 1;
        int iMsgStart =1;
        int width = m_iPannelWidth ;//显示面板的宽度
        std::string r="";
        //按照一个汉字一个长度,一个字母或者是特殊符号一个长度,得到的长度;(这样避免换行的时候汉字被分开,出现乱码现象)
        int iRealLength = Tools::getRealStringLength(m_TotalMsg);
        CCLabelTTF* tempTextView = CCLabelTTF::create();
        tempTextView->setFontName("Arial-BoldMT");
        tempTextView->setFontSize(24);
        
        
        while( (r= Tools::subString(m_TotalMsg,iMsgStart,iMsgEnd))!= "")
        {
    	//先判断当前读取的字符内容是否是表情
            if(r[r.length()-1]=='[')
            {
                std::string tmp = Tools::subString(m_TotalMsg,iMsgEnd,iMsgEnd+3);
                if(tmp[3]==']'&&isNumber(tmp[1])&&isNumber(tmp[2]))//face
                {   
                    //表情前面若有内容的处理
                    if(iMsgEnd-iMsgStart>0)
                    {
                        CCLabelTTF* textView = CCLabelTTF::create();
                        textView->setFontName("Arial-BoldMT");
                        textView->setFontSize(24);
                        textView->setColor(cColor3B);
                        textView->setString(r.substr(0,r.length()-1).c_str());
                        textView->setPosition(ccp(m_LeftMsg_x+posX, 0));
                        textView->setAnchorPoint(ccp(0, 0));
                        posX+=textView->getContentSize().width;
                        this->addChild(textView);
                        
                    }
                    
     		//如果有表情的处理
                    char temp[10] = {0};
                    if(tmp[1]-'0' == 0)
                    {
                        sprintf(temp, "%d.png",tmp[2]-'0');
                    }
                    else
                    {
                        sprintf(temp, "%d%d.png",tmp[1]-'0',tmp[2]-'0');
                    }
                    bLineHaveFace = true;
                    
                    
                    CCSprite *sp = CCSprite::create(temp);
                    sp->setScaleX(0.6);
                    sp->setScaleY(0.6);
                    sp->setAnchorPoint(ccp(0, 0));
    		//如果最后表情在一行的最后的换行处理
                    if(sp->getContentSize().width+posX>width)
                    {
                        posX=0;
                        if (m_bLimitOneLine == true)
                        {
                            break;
                        }
                        changeLine();
                        bDoubleLine=true;
                    }
                    iMsgEnd+=4;
                    iMsgStart=iMsgEnd;
                    
                    sp->setPosition(ccp(m_LeftMsg_x+posX, 0));
                    posX+=sp->getContentSize().width*0.6;
                    
                    this->addChild(sp);
                    if(iMsgEnd>iRealLength)
                    {
                        break;
                    }
                    continue;
                }
            }
            tempTextView->setString(r.c_str());
    	//如果读取到都是无表情的内容,如下进行换行;
            if(tempTextView->getContentSize().width+posX+24 >= width)
            {
                CCLabelTTF* textView = CCLabelTTF::create();
                textView->setFontName("Arial-BoldMT");
                textView->setFontSize(24);
                textView->setColor(cColor3B);
                textView->setString(r.c_str());
                textView->setPosition(ccp(m_LeftMsg_x+posX, 0));
                textView->setAnchorPoint(ccp(0, 0));
                this->addChild(textView);
                iMsgEnd++;
                iMsgStart=iMsgEnd;
                posX=0;
                if(iMsgEnd>iRealLength)
                {
                    break;
                }
                if (m_bLimitOneLine)
                {
                    break;
                }
                changeLine();
                bDoubleLine=true;
              
                
            }
            else
            {
                iMsgEnd++;
                if(iMsgEnd>iRealLength)
                {
                    CCLabelTTF* textView = CCLabelTTF::create();
                    textView->setFontName("Arial-BoldMT");
                    textView->setColor(cColor3B);
                    textView->setFontSize(24);
                    textView->setString(r.c_str());
                    textView->setPosition(ccp(m_LeftMsg_x+posX, 0));
                    textView->setAnchorPoint(ccp(0, 0));
                    this->addChild(textView);
                    break;
                }
            }
        }
        if(bDoubleLine)
        {
            setContentSize(CCSizeMake(width, m_iDefaultSize*2));
            m_pTypeName->setPositionY(m_iDefaultSize);
            m_pUserName->setPositionY(m_iDefaultSize);
        }
        else
        {
            setContentSize(CCSizeMake(width, m_iDefaultSize));
            m_pTypeName->setPositionY(0);
            m_pUserName->setPositionY(0);
        }
    }
    // 截取字符,必满乱码的处理;
    std::string Tools::subString(std::string str ,int start ,int end)
    {
        if(typeid(str)==typeid(string) && str.length()>0)
        {
            int len=str.length();
            
            string tmp="";
            
            //先把str里的汉字和英文分开
            vector <string> dump;
            int i=0;
            while(i<len)
            {
                if (is_zh_ch(str.at(i))==1)
                {
                    dump.push_back(str.substr(i,3));
                    i=i+3;
                    
                }
                else
                {
                    dump.push_back(str.substr(i,1));
                    i=i+1;
                }
            }
            
            int iDumpSize = dump.size();
            end=end>0?end:iDumpSize;
            if(start<0||start>end)
                return "";
            for(i=start; i<=end; i++)
            {
                tmp+=dump[i-1];
            }
            return tmp;
        }
        else
        {
            printf("str is not string
    ");
            return "";
            
        }
    }
    //获取字符串的真实长度处理
    int Tools::getRealStringLength(std::string str){
        int i=0;
        int len=str.length();
        int r=0;
        while(i<len)
        {
            if (is_zh_ch(str.at(i))==1)
            {
                r++;
                i=i+3;
                
            }
            else
            {
                r++;
                i=i+1;
            }
        }
        return r;
    
    }
    
    
    



    如上基本上处理了一个富文本的基本操作,功能比较简单,但是做起来比较容易出问题,像换行,插入表情,截取汉字这个三个问题

  • 相关阅读:
    uva-11361
    HDU
    LCS
    CodeForces
    linux 有趣的命令组合
    opencv识别封闭区域 并标记该区域
    宜出行人口热力图
    美团酒店
    赶集租房
    发送企业微信应用通知
  • 原文地址:https://www.cnblogs.com/xiaoleiel/p/8301150.html
Copyright © 2020-2023  润新知