cocos2dx中RichText富文本的换行问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值