这两天简单实现了一下富文本。主要用了网上找的一个HtmlParser类,非常感谢作者!
// HtmlParser类,用于解析HTML文本
// http://blog.csdn.net/liigo/article/details/6153829 (重要)
// by liigo, @2010-2012
主要麻烦的就在长文字换行,我用了比较粗暴的办法。先把文字放进UILabel,得到总长,然后setTextareaSize强制换行,计算行高和右偏移,然后继续添加下一个控件。A标签按钮和img标签图片的实现反而要简单一些,只要计算是否换行和右偏移。暂时只添加了项目里需要用到的,慢慢来
int HtmlLabel::setHtmlText(std::string htmltext,std::string& strback)
{
if(m_lastHtml==htmltext)
{
return m_textBottom;
}
m_lastHtml=htmltext;
clearHtml();
string_replace(htmltext,"\n","<br>");
liigo::HtmlParser htmlParser;
htmlParser.parseHtml(htmltext.c_str());
for(int index = 0, count = htmlParser.getHtmlNodeCount(); index < count; index++)
{
liigo::HtmlNode* pNode = htmlParser.getHtmlNode(index);
switch (pNode->type)
{
case NODE_START_TAG:
{
switch (pNode->tagType)
{
case TAG_FONT:
{
if(pNode->attributeCount>0)
{
std::string text=liigo::HtmlParser::getAttributeStringValue(pNode,"color");
if(text!="")
{
m_color=getColor(text.substr(1));
}
}
index++;
liigo::HtmlNode* cNode = htmlParser.getHtmlNode(index);
if(cNode->type==NODE_CONTENT)
{
std::string content=cNode->text;
addNormalText(content,m_color);
}
}
break;
case TAG_BR:
{
m_textTop=m_textBottom;
m_textRight=0;
}
break;
case TAG_A:
{
std::string link;
if(pNode->attributeCount>0)
{
link=liigo::HtmlParser::getAttributeStringValue(pNode,"href");
}
index++;
liigo::HtmlNode* cNode = htmlParser.getHtmlNode(index);
if(cNode->type==NODE_CONTENT)
{
std::string content=cNode->text;
addLinkButton(content,link);
}
}
break;
default:
{
}
break;
}
}
break;
case NODE_CONTENT:
{
std::string content=pNode->text;
addNormalText(content,m_color);
}
break;
case NODE_END_TAG:
{
if(strcmp(pNode->tagName,"font")==0)
{
m_color=ccWHITE;
}
}
break;
default:
{
}
break;
}
}
return m_textBottom>m_constHeight?m_textBottom:m_constHeight;
}
void HtmlLabel::string_replace(std::string& strBig, const std::string & strsrc, const std::string &strdst)
{
std::string::size_type pos = 0;
while( (pos = strBig.find(strsrc, pos)) != std::string::npos)
{
strBig.replace(pos, strsrc.length(), strdst);
pos += strdst.length();
}
}
ccColor3B HtmlLabel::getColor(std::string str)
{
int r,g,b;
sscanf(str.substr(1,2).c_str(),"%x",&r);
sscanf(str.substr(3,2).c_str(),"%x",&g);
sscanf(str.substr(5,2).c_str(),"%x",&b);
return ccc3(r,g,b);
}
int HtmlLabel::addNormalText(std::string content,ccColor3B color)
{
UILabel* label=UILabel::create();
label->setFontSize(m_fontSize);
label->setFontName(m_fontName);
label->setColor(color);
label->setText(content.c_str());
int textLength=label->getSize().width;
std::string spaceText=getSpaceOfNumber(m_textRight/m_spaceLength);
content=spaceText+content;
label->setText(content.c_str());
int totalLength=label->getSize().width;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
totalLength*=1.1;
#endif
label->setAnchorPoint(ccp(0,1));
label->setPosition(ccp(0,-m_textTop));
addChild(label);
int lastLegth=totalLength%m_constWidth;
if(m_textRight+textLength>m_constWidth)
{
m_textRight=lastLegth+(totalLength/m_constWidth)*10;
label->setTextAreaSize(CCSizeMake(m_constWidth,0));
m_textBottom=m_textTop+label->getSize().height+10;
m_textTop=m_textBottom-m_spaceHeight-10;
}
else
{
m_textRight=lastLegth;
if(m_textTop+label->getSize().height>m_textBottom)
{
m_textBottom=m_textTop+label->getSize().height+10;
}
}
return 0;
}