/*
* Set the untransformed size of the node.
* 设置节点转换前的大小
* The contentSize remiains the same no matter the node is scaled or rotated.
* 无论缩放还是旋转节点,它的contentSize始终保持不变
* All nodes has a size. Layer and Scene has the same size of the screen.
* 所有的节点都有一个大小,layer和scene的大小和屏幕大小保持一致
*/
/*
* 说明:
* 1、节点在使用的过程中可能进行缩放、旋转等变化,这样导致我们看见的节点的大小可能发生了变化。但是
* contentSize是一直保持
* 不变的,因为这是一个基准。可以想一下,如果这个contentSize在进行缩放之后发生了变化,那么在
* setScale(1.5f)之后再设置setScale(1.0f)如何能够还原呢?
*/
void Node::setContentSize(const Size& size)
{
if(!size.equals(_contentSize)
{
_contentSize = size;
_anchorPoints.set(_contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y);
_transformUpdated= _transformDiry = _inverseDirty = _contentSizeiryt = true;
}
}
/*
Sets the untransformed size of the Label in a more efficient way.
以一种更高效的方式设置Label未转换前的大小
*/
void Label::setDimensions(float width, float height)
{
if(_overflow == Overflow::RESIZE_HEIGHT){
height = 0;
}
if (height != _labelHeight || width != _labelWidth)
{
_labelWidth = width;
_labelHeight = height;
_labelDimensions.width = width;
_labelDimensions.height = height;
_maxLineWidth = width;
_contentDirty = true;
if(_overflow == Overflow::SHRINK){
if (_originalFontSize > 0) {
this->restoreFontSize();
}
}
}
}
在setDimensions的源码中我们看到了主要是对这几个成员变量进行了设置,那么这几个成员变量的使用方法以及相关的作用是什么呢?首先来看看_labelDimensions的使用:
从上图中可以知道,对于_labelDimensions成员变量的使用只在相关的set和get方法中出现了。接下来我们看看_labelWidth和_labelHeight的使用。
从上图中我们可以看到,在alignText方法中使用到了_labelWidth,即在文字的对齐方式中进行了使用。因此我们很自然的可以想到:_labelDimenSions与标签的对齐方式有关。其中setMaxLineWidth也说明了,只有在调用了setDimenSions方法之后,对于标签的对齐方式、显示方式才会生效。
auto labTest = Label::createWithSystmeFont("I love China, I am a Chinese", "", 30);
labTetst->setPosition(Vec2(_size.width / 2, _size.height * 0.75f));
this->addChild(labTest, 100);
auto labTest2 = Label::createWithSystemFont("I love China, I am a Chinese", "", 30);
labTest2->setPosition(Vec2(m_vSize.width / 2, m_vSize.height * 0.70));
labTest2->setDimensions(200.0f, 80.0f);
this->addChild(labTest2, 100);
auto labTest3 = Label::createWithSystemFont("I love China, I am a Chinese", "", 30);
labTest3->setPosition(Vec2(m_vSize.width / 2, m_vSize.height * 0.65));
labTest3->setContentSize(Size(200.0f, 80.0f));
this->addChild(labTest3, 100);
由上述的实验结果我们可以看到,分别使用setDimenSions和setContentSize方法对于Label进行同样大小的设置,但是setContentSize并没有起到什么效果;而使用setDimenSions对Label的设置产生了效果,同时使其进行了自动缩放和换行的调整。
在公司做产品的过程中遇到这样一个使用场景,需要对Label创建的字体加上一个下划线,但是又没有现成的接口可以设置下划线于是就自己封装了一个。
// Label增加下划线处理
void whStartLayer::labAttachUnderline(Label* labNode)
{
if (nullptr == labNode) {
return;
}
float labWidth = labNode->getContentSize().width;
auto underLine = DrawNode::create();
underLine->drawSegment(Vec2(0, 0), Vec2(labWidth, 0), 1, Color4F::BLACK);
labNode->addChild(underLine);
return;
}
示例1:
// 创建一个label
auto labPrivacy = Label::createWithSystemFont(u8"隐私协议", "", 40.0f);
labPrivacy->setTextColor(Color4B(0x2e, 0x2e, 0x2e, 0xff));
labPrivacy->setPosition(Vec2(visibleSize / 2));
this->addChild(labPrivacy);
// label增加下划线处理
labAttachUnderline(labPrivacy);
目前我在游戏开发的过程中经常会遇见文本内容过长的问题,我个人对于此类问题的处理主要是采用以下两种方式:1,设置label的最大宽度,不进行换行操作,当文本大小超过了最大宽度限定就会进行自动缩放;2,设置label的最大宽度,同时保持字体大小不变,超过最大限度之后之后进行换行处理。
对于第一种处理方式主要适用于标题、按钮文本等内容的处理,文本必须在一行呈现出来才比较美观。
// 标签内容一行呈现,字体进行自动缩放
void setLabAlignInOneLine(Label* labNode, float maxWidth)
{
auto curSize = labNode->getContentSize();
float dimenWidth = curSize.width > maxWidth ? maxWidth : curSize.width;
labNode->setDimensions(dimenWidth, curSize.height);
labNode->setOverflow(Label::Overflow::SHRINK); // 设置溢出处理方式(共有4种):缩放处理
labNode->setAlignment(TextHAlignment::CENTER, TextVAlignment::CENTER);
return;
}
对于第二种方式,我们保持字体的大小不变,在最大宽度限定下来自动适应高度。其实Label中的溢出处理方式中有一个“Label::Overflow::RESIZE_HEIGHT”,但是设置这个属性之后去获取标签的大小时,高度始终时0,因为这个bug我就放弃了这种处理方式。因为我在使用的过程中还是需要Label的大小去设置相应的位置坐标,因此我采用以下的方式进行处理。
使用过程中自己去判断为了保持字体大小不变,最大宽度限定下实际创建的Label会有多少行,然后手动去设定标签的大小。如果不手动设置标签大小的话,换行之后的部分文本可能无法显示出来。
void setLabAutoHeight(Label * labNode, float maxWidth, TextHAlignment hType, TextVAlignment vType, float lineSpace)
{
auto curSize = labNode->getContentSize();
int lineNum = (int)(curSize.width / maxWidth) + 1;
float dimenHeight = lineNum*(curSize.height + lineSpace) - lineSpace;
labNode->setDimensions(maxWidth, dimenHeight);
labNode->setAlignment(hType, vType);
labNode->setLineBreakWithoutSpace(true);
labNode->setLineSpacing(lineSpace);
return;
}
示例2:
// 示例代码:
string textStr = u8"这是一个标题示例,我们正在做溢出处理测试。";
auto labTemp = Label::createWithSystemFont(textStr, "", 40.0f);
labTemp->setPosition(Vec2(visibleSize.width / 2, 1000.0f));
labTemp->setTextColor(Color4B::BLACK);
this->addChild(labTemp);
auto labTemp2 = Label::createWithSystemFont(textStr, "", 40.0f);
labTemp2->setPosition(Vec2(visibleSize.width / 2, 900.0f));
labTemp2->setTextColor(Color4B::BLACK);
this->addChild(labTemp2);
setLabAlignInOneLine(labTemp2, 600.0f);
示例3:
// 示例代码:
// 文本内容一行展示
string textStr = u8"这是一个标题示例,我们正在做溢出处理测试。再继续增加一点文字长度!";
auto labTemp = Label::createWithSystemFont(textStr, "", 40.0f);
labTemp->setPosition(Vec2(visibleSize.width / 2, 900.0f));
labTemp->setTextColor(Color4B::BLACK);
this->addChild(labTemp);
// 水平居中对齐
auto labTemp2 = Label::createWithSystemFont(textStr, "", 40.0f);
labTemp2->setPosition(Vec2(visibleSize.width / 2, 700.0f));
labTemp2->setTextColor(Color4B::BLACK);
this->addChild(labTemp2);
setLabAutoHeight(labTemp2, 600.0f, TextHAlignment::CENTER, TextVAlignment::CENTER, 0.0f);
// 水平左对齐
auto labTemp3 = Label::createWithSystemFont(textStr, "", 40.0f);
labTemp3->setPosition(Vec2(visibleSize.width / 2, 500.0f));
labTemp3->setTextColor(Color4B::BLACK);
this->addChild(labTemp3);
setLabAutoHeight(labTemp3, 600.0f, TextHAlignment::LEFT, TextVAlignment::CENTER, 0.0f);
// 水平右对齐
auto labTemp4 = Label::createWithSystemFont(textStr, "", 40.0f);
labTemp4->setPosition(Vec2(visibleSize.width / 2, 300.0f));
labTemp4->setTextColor(Color4B::BLACK);
this->addChild(labTemp4);
setLabAutoHeight(labTemp4, 600.0f, TextHAlignment::RIGHT, TextVAlignment::CENTER, 0.0f);