前言。
由于自己最近工作需要用到这个功能。但是通过发现原有的不能设置颜色和大小。以前也没去细看,最近才去看了底层。自己也对此做了底层的修改。希望对各位有所帮助。
通过发现。最后的实现是通过Label的函数enableUnderline中在Label的基础上加上DrawNode实现。您自己也可以通过自己创建Label和DrawNode去实现,也有发现 Cocos2d-Lua-Community 通过在enableUnderline增加设置下划线颜色 在Label的函数 updateContent 中改变颜色。这个方案比较简单 也推荐大家使用。具体实现代码片段在如下
if (_numberOfLines)
{
// This is the logic for TTF fonts
const float charheight = (_textDesiredHeight / _numberOfLines);
_underlineNode->setLineWidth(charheight/6);
// atlas font
for (int i=0; i<_numberOfLines; ++i)
{
float offsety = 0;
if (_strikethroughEnabled)
offsety += charheight / 2;
// FIXME: Might not work with different vertical alignments
float y = (_numberOfLines - i - 1) * charheight + offsety;
// Github issue #15214. Uses _displayedColor instead of _textColor for the underline.
// This is to have the same behavior of SystemFonts.
Color4F color = _underlineColor4B.a > 0 ? Color4F(_underlineColor4B) : Color4F(_displayedColor);
_underlineNode->drawLine(Vec2(_linesOffsetX[i] + 1, y), Vec2(_linesWidth[i] + _linesOffsetX[i] - 1, y), color);
}
}
else if (_textSprite)
{
// ...and is the logic for System fonts
float y = 0;
const auto spriteSize = _textSprite->getContentSize();
_underlineNode->setLineWidth(spriteSize.height/6);
if (_strikethroughEnabled)
// FIXME: system fonts don't report the height of the font correctly. only the size of the texture, which is POT
y += spriteSize.height / 2;
// FIXME: Might not work with different vertical alignments
Color4F color = _underlineColor4B.a > 0 ? Color4F(_underlineColor4B) : Color4F(_textSprite->getDisplayedColor());
_underlineNode->drawLine(Vec2(0.0f + 1, y), Vec2(spriteSize.width - 1, y), color);
}
}
还有一个简单的实现:就是将此函数中 这句代码
_underlineNode->drawLine(Vec2(_linesOffsetX[i] + 1, y), Vec2(_linesWidth[i] + _linesOffsetX[i] - 1, y), color);
的 _displayedColor 改成 _textColor 就是和字体颜色一样了
自己实现部分。
为了方便我自己,实现创建createWithXML时候直接通过原有标识“u”就直接设置颜色和线的宽度。
UIRichText部分
MyXMLVisitor::setTagDescription("u", true, [](const ValueMap& tagAttrValueMap) {
// no supported attributes
ValueMap attrValueMap;
attrValueMap[RichText::KEY_TEXT_LINE] = RichText::VALUE_TEXT_LINE_UNDER;
if (tagAttrValueMap.find("color") != tagAttrValueMap.end()) {
attrValueMap[RichText::KEY_TEXT_LINE_COLOR] = tagAttrValueMap.at("color").asString();
}
if (tagAttrValueMap.find("size") != tagAttrValueMap.end()) {
attrValueMap[RichText::KEY_TEXT_LINE_SIZE] = tagAttrValueMap.at("size").asString();
}
return make_pair(attrValueMap, nullptr);
});
这里是添加 u 标识下 识别color和size 的实现部分。其中 KEY_TEXT_LINE_COLOR 和 KEY_TEXT_LINE_SIZE 自行添加 在 KEY_TEXT_LINE 下面。
const std::string RichText::KEY_TEXT_LINE_COLOR("KEY_TEXT_LINE_COLOR");
const std::string RichText::KEY_TEXT_LINE_SIZE("KEY_TEXT_LINE_SIZE");
既然在 MyXMLVisitor 中 那就把在此需要添加的加完。在 struct Attributes 中添加
Color3B underlineColor; /*!< the color of the underline */
int underlineSize; /*!< the underline effect size value */
在下面 public 函数中添加
std::tuple<bool, Color3B, int> getUnderline() const;
实现如下
std::tuple<bool, Color3B, int>MyXMLVisitor::getUnderline() const
{
for (auto i = _fontElements.rbegin(), iRend = _fontElements.rend(); i != iRend; ++i)
{
if (i->line == StyleLine::UNDERLINE)
{
return std::make_tuple(true, i->underlineColor, i->underlineSize);
}
}
return std::make_tuple(false, Color3B::WHITE, -1);
}
在 MyXMLVisitor::startElement 函数。 在
keyTextLine == RichText::VALUE_TEXT_LINE_UNDER 和
keyTextStyle == RichText::VALUE_TEXT_LINE_UNDER 判断下替换以下代码
attributes.line = StyleLine::UNDERLINE;
if (attrValueMap.find(RichText::KEY_TEXT_LINE_COLOR) != attrValueMap.end()) {
attributes.underlineColor = _richText->color3BWithString(attrValueMap.at(RichText::KEY_TEXT_LINE_COLOR).asString());
}
if (attrValueMap.find(RichText::KEY_TEXT_LINE_SIZE) != attrValueMap.end()) {
attributes.underlineSize = attrValueMap.at(RichText::KEY_TEXT_LINE_SIZE).asInt();
}
在 MyXMLVisitor::textHandler下改变这句代码 后面两个是我自己加的。
auto element = RichElementText::create(0, color, 255, text, face, fontSize, flags, url,
std::get<1>(outline), std::get<2>(outline),
std::get<1>(shadow), std::get<2>(shadow), std::get<3>(shadow),
std::get<1>(glow),
std::get<1>(underline), std::get<2>(underline));
然后在这两个函数 RichElementText::create、RichElementText::init 中作修改。
RichElementText* RichElementText::create(int tag, const Color3B &color, GLubyte opacity, const std::string& text,
const std::string& fontName, float fontSize, uint32_t flags, const std::string& url,
const Color3B& outlineColor, int outlineSize ,
const Color3B& shadowColor, const cocos2d::Size& shadowOffset, int shadowBlurRadius,
const Color3B& glowColor,
const Color3B& underlineColor, int underlineSize)
{
RichElementText* element = new (std::nothrow) RichElementText();
if (element && element->init(tag, color, opacity, text, fontName, fontSize, flags, url,
outlineColor, outlineSize, shadowColor, shadowOffset, shadowBlurRadius, glowColor, underlineColor, underlineSize))
{
element->autorelease();
return element;
}
CC_SAFE_DELETE(element);
return nullptr;
}
bool RichElementText::init(int tag, const Color3B &color, GLubyte opacity, const std::string& text,
const std::string& fontName, float fontSize, uint32_t flags, const std::string& url,
const Color3B& outlineColor, int outlineSize ,
const Color3B& shadowColor, const cocos2d::Size& shadowOffset, int shadowBlurRadius,
const Color3B& glowColor,
const Color3B& underlineColor, int underlineSize)
{
if (RichElement::init(tag, color, opacity))
{
_text = text;
_fontName = fontName;
_fontSize = fontSize;
_flags = flags;
_url = url;
_outlineColor = outlineColor;
_outlineSize = outlineSize;
_shadowColor = shadowColor;
_shadowOffset = shadowOffset;
_shadowBlurRadius = shadowBlurRadius;
_glowColor = glowColor;
_underlineColor = underlineColor;
_underlineSize = underlineSize;
return true;
}
return false;
}
这是我修改后的。
接下来 在 formatText 函数中 的 判断 if (elmtText->_flags & RichElementText::UNDERLINE_FLAG)下 改成
label->enableUnderline(Color4B(elmtText->_underlineColor), elmtText->_underlineSize);
case RichElement::Type::TEXT: 这个条件下改成
RichElementText* elmtText = static_cast<RichElementText*>(element);
handleTextRenderer(elmtText->_text, elmtText->_fontName, elmtText->_fontSize, elmtText->_color,
elmtText->_opacity, elmtText->_flags, elmtText->_url,
elmtText->_outlineColor, elmtText->_outlineSize,
elmtText->_shadowColor, elmtText->_shadowOffset, elmtText->_shadowBlurRadius,
elmtText->_glowColor,
elmtText->_underlineColor, elmtText->_underlineSize);
break;
在 handleTextRenderer 中修改如下
void RichText::handleTextRenderer(const std::string& text, const std::string& fontName, float fontSize, const Color3B &color,
GLubyte opacity, uint32_t flags, const std::string& url,
const Color3B& outlineColor, int outlineSize ,
const Color3B& shadowColor, const Size& shadowOffset, int shadowBlurRadius,
const Color3B& glowColor,
const Color3B& underlineColor, int underlineSize)
if (flags & RichElementText::UNDERLINE_FLAG)
textRenderer->enableUnderline(Color4B(underlineColor), underlineSize);
CCLabel修改
Label::reset() 中添加
_underlineColor = Color4B::WHITE;
_underlineSize = -1;
enableUnderline 中为
void Label::enableUnderline(const Color4B& underlineColor, int underlineSize)
{
// remove it, just in case to prevent adding two or more
if (!_underlineNode)
{
_underlineNode = DrawNode::create();
addChild(_underlineNode, 100000);
_contentDirty = true;
_underlineColor = underlineColor;
if (underlineSize > 0)
{
_underlineSize = underlineSize;
}
}
}
updateContent 这个函数中的修改部分 两个地方。
// Github issue #15214. Uses _displayedColor instead of _textColor for the underline.
// This is to have the same behavior of SystemFonts.
Color4F Linecolor = _underlineColor != Color4B::WHITE ? Color4F(_underlineColor) : Color4F(_displayedColor);
_underlineNode->drawLine(Vec2(_linesOffsetX[i], y), Vec2(_linesWidth[i] + _linesOffsetX[i], y), Linecolor);
lua_cocos2dx_auto
lua_cocos2dx_Label_enableUnderline 部分
int lua_cocos2dx_Label_enableUnderline(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Label* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Label",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Label*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 0)
{
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
return 0;
}
cobj->enableUnderline();
lua_settop(tolua_S, 1);
return 1;
}
if (argc == 1)
{
cocos2d::Color4B arg0;
ok &= luaval_to_color4b(tolua_S, 2, &arg0, "cc.Label:enableUnderline");
if (!ok)
{
tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
return 0;
}
cobj->enableOutline(arg0);
lua_settop(tolua_S, 1);
return 1;
}
if (argc == 2)
{
cocos2d::Color4B arg0;
int arg1;
ok &= luaval_to_color4b(tolua_S, 2, &arg0, "cc.Label:enableUnderline");
ok &= luaval_to_int32(tolua_S, 3, (int*)&arg1, "cc.Label:enableUnderline");
if (!ok)
{
tolua_error(tolua_S, "invalid arguments in function 'lua_cocos2dx_Label_enableUnderline'", nullptr);
return 0;
}
cobj->enableOutline(arg0, arg1);
lua_settop(tolua_S, 1);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Label:enableUnderline",argc, 0);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_Label_enableUnderline'.",&tolua_err);
#endif
return 0;
}
lua_cocos2dx_ui_RichElementText_init 和 lua_cocos2dx_ui_RichElementText_create 这些并没有做修改。方便使用XML 创建的UIRichText 方式设置下划线颜色 。不过您可以通过enableUnderline 函数去实现改变需要颜色和宽度。 至于其他您可以自己把 lua_cocos2dx_ui_RichElementText_init 和 lua_cocos2dx_ui_RichElementText_create 这个完善。
大概就这样了。本来不想写完的直接上代码。但是坚持把。谢谢阅读!!!