这里使用的是cocos2dx的2.2.3版本,底层的RictText换行机制不能满足中文换行,需要改动。由于在3.x的版本已经优化了,而且以后的项目也会转到3.x的版本,所以这里只是做一个记录,对底层换行机制的思想做一个分析,仅供学习用。
RichText的换行原理:
以文本换行为例(图片同样的道理),先用一个不带换行的label,算出该label的总长度L,然后和程序设定的宽w比较,w<L则一行足以,否则按w在L中比例来截取原字符串,作为第一行,剩余部分递归处理。看代码:
- <spanstyle="font-size:14px;">voidRichText::handleTextRenderer(constchar*text,char*fontName,floatfontSize,153); font-weight:bold; background-color:inherit">constccColor3B&color,GLubyteopacity)
- {
- /*不换行时的label*/
- CCLabelTTF*textRenderer=CCLabelTTF::create(text,fontName,fontSize);
- /*不换行时的label宽度*/
- floattextRendererWidth=textRenderer->getContentSize().width;
- /*用设定的大小-label宽度*/
- _leftSpaceWidth-=textRendererWidth;
- if(_leftSpaceWidth<0.0f)
- /*需要换行,则需要按比例截取原字符串:先计算超出的宽度所占的比例*/
- floatoverstepPercent=(-_leftSpaceWidth)/textRendererWidth;
- std::stringcurText=text;
- /*计算字符串的长度*/
- intstringLength=curText.length();
- /*1-超出比例=当前(设定宽度所占比)来截取字符串*/
- intleftLength=stringLength*(1.0f-overstepPercent);
- /*使用stl标准库的string函数截取字串*/
- std::stringleftWords=curText.substr(0,leftLength);
- std::stringcutWords=curText.substr(leftLength,curText.length()-1);
- /*字符串不为空,则绘制第一行label*/
- if(leftLength>0)
- {
- CCLabelTTF*leftRenderer=CCLabelTTF::create(leftWords.substr(0,leftLength).c_str(),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> leftRenderer->setColor(color);
- leftRenderer->setOpacity(opacity);
- pushToContainer(leftRenderer);
- }
- /*开启新的一行,并作递归处理*/
- addNewLine();
- handleTextRenderer(cutWords.c_str(),fontSize,color,opacity);
- }
- else
- textRenderer->setColor(color);
- textRenderer->setOpacity(opacity);
- pushToContainer(textRenderer);
- }</span>
这里的重点是截取字串的方式,自带的substr不能很好的处理多字节字符的截取,中文会出现乱码,所以用自己写的函数实现,这个函数在网上能找到,但仍然有问题,我做了一些修改,将原来的substr改为自定义的“utf8_substr”函数:
copy