這幾天需要使用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內容是否超框,直到找到一個不超框的放在這一行,“ ”后的內容放下一行。