cocos2d RichText 换行 字体颜色 真实Size

本文详细介绍了如何在Cocos2d-x中利用RichText组件实现类似微信朋友圈的评论功能,包括处理换行、设置字体颜色及获取控件真实尺寸的方法。

<小白记录>

 

​​​​​​公司这期做了一个类似于微信朋友圈的功能,下面有评论功能,开发过程中,需要处理换行、设置字体不同的颜色以及控件真实size的问题

名字:xxxxxxx

需要换行,也就是自动换到名字下方。

考虑到还能更换颜色,网上找了其他人的解决方案结合一下 使用 RichText,结果如下:

 

 

使用cocos 自带的 RichText 组件,它是富文本组件,一行字符可以有不同的文字、图片。在里面放置 RichElementText ,它可以设置此段文字的颜色、字体、大小,结合上面的图片,可以创建两个 RichElementText 组件,pushBackElement 到 RichText 中,即可出现上述效果。

RichText* richText = RichText::create();
richText->pushBackElement(RichElementText::create(0, Color3B::GREEN, 255, "高寒" + ":", "PingFangSC-Regular.ttf", 28));
richText->pushBackElement(RichElementText::create(1, Color3B::BALCK, 255, "xxxxxxxx", "PingFangSC-Regular.ttf", 28));
richText->ignoreContentAdaptWithSize(false);
richText->setPosition(Vec2(自行定.x, 自行定.y));
this->addChild(richText);

RichElementText 不止这些参数,后续参数还很多,比如 url 等,这里只说实现上述样式。不清楚参数使用可以继续百度 RichElementText。

注意:上面还没有设置contentSize

内容可以实现了,再者是换行,根据内容的长度计算出 richText 需要的高度就可以了,因为显示时,宽度肯定是固定的嘛

Size size = richText->getContentSize();
float height = ceil(size.width / this->getContentSize().width) * size.height;
richText->setContentSize(Size(this->getContentSize().width, height));

用 richtext宽 / 当前需要显示的宽 * richtext高(宽除以宽,是文本内容在需要显示的宽度中的行数,如果=1,那就一行,如果>1,那就需要多行,再乘以高得到多行的高度)这样就可以实现多行不同颜色的文本

 

 

可能实际做的时候,你会发现一个问题,Size size = richText->getContentSize() 获得的值是(0,0),反正我是出现了,如果你没有问题,那你可以不用接着往下看了。由于我是多个评论,一层一层的,没有尺寸,我就没法设置后面的灰色背景尺寸,所以这里需要得到真实Size,需要改动底层,当然也很浅。

进入UIRichText.h 中,写上

Size _renderSize;
Size& getRenderSize();
void setRenderSize(const Size &size);

在UIRichText.cpp里面实现

Size& RichText::getRenderSize()
{
    return this->_renderSize;
}
void RichText::setRenderSize(const Size &size)
{
    _renderSize = size;
}

UIRichText.cpp中找到 formarRenderers() 方法

void RichText::formarRenderers()
{
    if (_ignoreSize)
    {
        float newContentSizeWidth = 0.0f;
        float nextPosY = 0.0f;
        for (auto& element: _elementRenders)
        {
            Vector<Node*>* row = element;
            float nextPosX = 0.0f;
            float maxY = 0.0f;
            for (ssize_t j=0, size = row->size(); j<size; j++)
            {
                Node* l = row->at(j);
                l->setAnchorPoint(Vec2::ZERO);
                l->setPosition(nextPosX, nextPosY);
                this->addProtectedChild(l, 1);
                Size iSize = l->getContentSize();
                newContentSizeWidth += iSize.width;
                nextPosX += iSize.width;
                maxY = MAX(maxY, iSize.height);
            }
            nextPosY -= maxY;
            this->setRenderSize(Size(newContentSizeWidth, maxY));  //这里是我加上的代码
        }
        this->setContentSize(Size(newContentSizeWidth, -nextPosY));
    }
    else
    {
        float newContentSizeHeight = 0.0f;
        float *maxHeights = new (std::nothrow) float[_elementRenders.size()];
        
        for (size_t i=0, size = _elementRenders.size(); i<size; i++)
        {
            Vector<Node*>* row = (_elementRenders[i]);
            float maxHeight = 0.0f;
            for (ssize_t j=0, size = row->size(); j<size; j++)
            {
                Node* l = row->at(j);
                maxHeight = MAX(l->getContentSize().height, maxHeight);
            }
            maxHeights[i] = maxHeight;
            newContentSizeHeight += maxHeights[i];
        }
        
        float nextPosY = _customSize.height;
        for (size_t i=0, size = _elementRenders.size(); i<size; i++)
        {
            Vector<Node*>* row = (_elementRenders[i]);
            float nextPosX = 0.0f;
            nextPosY -= (maxHeights[i] + _defaults.at(KEY_VERTICAL_SPACE).asFloat());
            
            for (ssize_t j=0, size = row->size(); j<size; j++)
            {
                Node* l = row->at(j);
                l->setAnchorPoint(Vec2::ZERO);
                l->setPosition(nextPosX, nextPosY);
                this->addProtectedChild(l, 1);
                nextPosX += l->getContentSize().width;
            }
        }
        this->setRenderSize(Size(_contentSize.width, newContentSizeHeight));  //这里是我加上的代码
        delete [] maxHeights;
    }
    
    size_t length = _elementRenders.size();
    for (size_t i = 0; i<length; i++)
	{
        Vector<Node*>* l = _elementRenders[i];
        l->clear();
        delete l;
	}    
    _elementRenders.clear();
    
    if (_ignoreSize)
    {
        Size s = getVirtualRendererSize();
        this->setContentSize(s);
    }
    else
    {
        this->setContentSize(_customSize);
    }
    updateContentSizeWithTextureSize(_contentSize);
}

里面写上了刚刚加的新方法 setRenderSize,算是官方的bug吧,他没有把size值用上,所以我这里就自己存储下来使用。但是版本不同,可能 formarRenderers 里面的实现会有一些不一样,主要是height,但是值一定是有得到的,请自行了解这个方法里面的实现。注意,我加了两处自己的代码,一定是需要的!

 

这个时候再去测试一下加的新方法

Size size = richText->getRenderSize();
CCLOG("%01f,%01f", size.width, size.height);

发现还是0,打断点可以知道,是先执行了getRenderSize 再执行的 setRenderSize

进入UIRichText.cpp,找到 pushBackElement() 

void RichText::pushBackElement(RichElement *element)
{
    _richElements.pushBack(element);
    this->formatText();  //这里是我加的
    _formatTextDirty = true;
}

每次在push内容的时候,就去set一次尺寸。注意:是 RichText 类下的 pushBackElement

再测试一下,size有了,真实size可以得到了,至此,我的功能完成了一半。就酱

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值