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

cocos2d RichText 换行 字体颜色 真实Size

2020-02-28 19:58 169 查看

<小白记录>

 

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

名字:xxxxxxx

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

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

 

 

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

[code]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 需要的高度就可以了,因为显示时,宽度肯定是固定的嘛

[code]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 中,写上

[code]Size _renderSize;
Size& getRenderSize();
void setRenderSize(const Size &size);

在UIRichText.cpp里面实现

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

UIRichText.cpp中找到 formarRenderers() 方法

[code]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,但是值一定是有得到的,请自行了解这个方法里面的实现。注意,我加了两处自己的代码,一定是需要的!

 

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

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

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

进入UIRichText.cpp,找到 pushBackElement() 

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

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

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

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