您的位置:首页 > 移动开发 > Cocos引擎

cocos2dx中RichText富文本的换行问题

2015-10-25 09:13 881 查看
wod开飞行太难谁特么的有空刷声望啊!还不如写博客!

  关于富文本什么的,之前在南京那家公司做一个国外外包iOS应用项目的时候曾经做过一个,当时的感觉是——很难。因为需要处理wordwrap,而又没找到适合ios系统控件的文本宽度计算算法,当时的处理是直接使用Label控件一个个去匹配适应,然后超过4行的文本,计算时间就想当长了,所以当时找了一堆都是使用html+js做富文本编辑器的。当然这算题外话,因为cocos2dx的RichText没有换行算法选项,也就没有这个问题,但那逗逼的换行算法也是坑了我…(cocos2dx 3.3)

  所谓富文本,大体就是图片等其他东西和文本混排,很多情况下图片等看作文本单元排布。以一般思路来说,也就是做个展示容器,容器接收文本和图片等的片段,然后容器内封装了对排布的处理方法。而cocos2dx的RichText控件也就是这么做的。

  cocos2dx的富文本换行算法…相当的…有想法?…这是相当令人无语的…写法…上代码:

UIRichText.cpp:

size_t stringLength = StringUtils::getCharacterCountInUTF8String(text);
int leftLength = stringLength * (1.0f - overstepPercent);
std::string leftWords = Helper::getSubStringOfUTF8String(curText,0,leftLength);
std::string cutWords = Helper::getSubStringOfUTF8String(curText, leftLength, stringLength - leftLength);


  简单来说,就是…如果超长了,用unicode字符数乘以超长的…长度比,然后字符串直接截取对应的字符个数来换行…那么,面对例如
测试文本测试文本测试文本123443211234
或是
123443211234测试文本测试文本测试文本
这种要么头重脚轻要么臀部过大的字符串,放进一个element中塞给UIRichText之后,见到的不是吞文本就是断行了…

  还好他们没去做word wrap处理…还好产品没给我说需要加word wrap换行…

  于是我把
handleTextRenderer
这块儿稍微改了下,在原来个数计算的基础上加了两块操作——超了切,短了补,现在运行基本正常——暂时没发现不正常的情况。

主要代码:

Label* leftRenderer = nullptr;

if (leftWords.length() > 0) {

if (fileExist)
{
leftRenderer = Label::createWithTTF(leftWords, fontName, fontSize);
}
else
{
leftRenderer = Label::createWithSystemFont(leftWords, fontName, fontSize);
}
}

if (!leftRenderer) {
return;
}

// 处理需截文本字宽度不均,前半部分超出的情况 例如 "测试文本测试文本12341234",取宽度10/16 前半部分宽度10则超出很多
while (true) {
if (leftWords.length() > 0)
{
leftRenderer->setString(leftWords);

float leftRendererWidth = leftRenderer->getContentSize().width;
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
while (true) {
leftLength -= 1;
leftWords = Helper::getSubStringOfUTF8String(curText, 0, leftLength);
cutWords = Helper::getSubStringOfUTF8String(curText, leftLength, stringLength - leftLength);
if (leftWords.length() == 0) {
break;
}
if (leftWords.length() < leftWordsLen) {
break;
}
}
}
}
else {
//if _leftSpaceWidth > 0 break
break;
}
}
else {
//if leftWords is empty, break
break;
}
}

// 处理需截文本字宽度不均,后半部分超出的情况 例如 "12341234测试文本测试文本",取宽度10/16 前半部分宽度10则缺少很多
std::string lastLeftWords = leftWords;
std::string lastCutWords = cutWords;
float lastTmpLeftSpaceWidth = tmpLeftSpaceWidth;
while (true) {
if (cutWords.length() > 0)
{
int leftWordsLen = (int)leftWords.length();
while (true) {
leftLength += 1;
leftWords = Helper::getSubStringOfUTF8String(curText, 0, leftLength);
cutWords = Helper::getSubStringOfUTF8String(curText, leftLength, stringLength - leftLength);
if (cutWords.length() == 0) {
break;
}
if (leftWords.length() > leftWordsLen) {
break;
}
}

leftRenderer->setString(leftWords);

float leftRendererWidth = leftRenderer->getContentSize().width;
tmpLeftSpaceWidth = _leftSpaceWidth;
tmpLeftSpaceWidth -= leftRendererWidth;

if (tmpLeftSpaceWidth < 0.0f) {
leftWords = lastLeftWords;
cutWords = lastCutWords;
tmpLeftSpaceWidth = lastTmpLeftSpaceWidth;
leftRenderer->setString(leftWords);
break;
}
else {
lastLeftWords = leftWords;
lastCutWords = cutWords;
lastTmpLeftSpaceWidth = tmpLeftSpaceWidth;
}
}
else {
//if cutWords is empty, break
leftWords = lastLeftWords;
cutWords = lastCutWords;
tmpLeftSpaceWidth = lastTmpLeftSpaceWidth;
leftRenderer->setString(leftWords);
break;
}
}

_leftSpaceWidth = tmpLeftSpaceWidth;
leftRenderer->setColor(color);
leftRenderer->setOpacity(opacity);
pushToContainer(leftRenderer);

_leftSpaceWidth = tmpLeftSpaceWidth;
addNewLine();
handleTextRenderer(cutWords.c_str(), fontName, fontSize, color, opacity);


工程源码(使用cocos2dx3.3):

github
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: