cocos2dx实现RichText中英文不被强行截断
这几天需要使用RichText实现富文本的需要,看了下cocos2dx3.3中已实现的RichText,发现写的还是比较粗糙的。如果在富文本中使用英文的话,分段时会把单词强行截断,这是个烦恼的问题,一般英文的换行都是根据“ ”来分段。
查看问题所在,发现在RichText中的handleTextRenderer(const std::string& text, const std::string& fontName, float fontSize, const Color3B &color, GLubyte opacity)函数中,该函数的作用就是判断传入的text是否在改行已超过指定宽度,如果否继续放该行,否则就打断text,前部分放该行,后部分放在新的一行中,而他截断方式竟然是使用平均长度来分,这方式让人有点。。。于是参考label类的自动换行,自己重写了handleTextRenderer方法。
代码如下:
auto fileExist = FileUtils::getInstance()->isFileExist(fontName);
Label* textRenderer = nullptr;
if (fileExist)
{
textRenderer = Label::createWithTTF(text, fontName, fontSize);
}
else
{
textRenderer = Label::createWithSystemFont(text, fontName, fontSize);
}
if (!textRenderer){
return;
}
float textRendererWidth = textRenderer->getContentSize().width;
float leftSpaceWidth = _leftSpaceWidth;
leftSpaceWidth -= textRendererWidth;
if (leftSpaceWidth < 0.0f)
{
std::string curText = text;
//寻找空格位置
int found = text.find_last_of(" ");
int stringLength = text.length();
//判断text是否有空格
if (found >= stringLength - 1 || found == -1)
{
addNewLine();
handleTextRenderer(curText.c_str(), fontName, fontSize, color, opacity);
}
else
{
std::string leftWords = Helper::getSubStringOfUTF8String(curText,0,found);
std::string cutWords = Helper::getSubStringOfUTF8String(curText, found, stringLength - found);
while (true)
{
if (leftWords.length() > 0)
{
textRenderer->setString(leftWords);
float leftRendererWidth = textRenderer->getContentSize().width;
float tmpLeftSpaceWidth = _leftSpaceWidth;
tmpLeftSpaceWidth -= leftRendererWidth;
if (tmpLeftSpaceWidth < 0.0f)
{
int leftWordsLen = (int)leftWords.length();
if (leftWordsLen <= 0)
{
break;
}
else
{
//cut char one by one to get the fit length
int foundPos = leftWords.find_last_of(" ");
if (foundPos >= leftWords.length() - 1 || foundPos == -1)
{
//剩余字符串已没有“ ”
break;
}
leftWords = Helper::getSubStringOfUTF8String(text, 0, foundPos);
cutWords = Helper::getSubStringOfUTF8String(text, foundPos, stringLength - foundPos);
}
}
else {
//if _leftSpaceWidth > 0 break
break;
}
}
else {
//if leftWords is empty, break
break;
}
}
if (textRenderer)
{
textRenderer->setString(leftWords);
float leftRendererWidth = textRenderer->getContentSize().width;
float leftSpaceWidth = _leftSpaceWidth;
leftSpaceWidth -= leftRendererWidth;
if (leftSpaceWidth < 0)
{
addNewLine();
handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);
return;
}
else
{
_leftSpaceWidth = leftSpaceWidth;
textRenderer->setColor(color);
textRenderer->setOpacity(opacity);
pushToContainer(textRenderer);
}
}
addNewLine();
handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);
}
}
else
{
_leftSpaceWidth = leftSpaceWidth;
textRenderer->setColor(color);
textRenderer->setOpacity(opacity);
pushToContainer(textRenderer);
}
我的思路就是判断该text是否超框,不是就继续放这行,是的话就判断text是否有“ ”,无则新增一行,有“ ”的话逐个判断“ ”位置前的text内容是否超框,直到找到一个不超框的放在这一行,“ ”后的内容放下一行。