这里主要做的是游戏公告里面用到的,因此我加入了简单的html <font>标签解析,是为了给运营小白预览,但其中的size 属性没有,因为后来没有这个需求了,所以也就懒得改了。
实现思路很简单:设置好行宽和行高,然后一个一个字往上面添加,直到达到行宽上限或者换行符,就换行,再循环。
--简易html label
--[[
暂只对以下标签进行实现
<font> 标签进行实现,可添加 size 和 color属性
<br> 换行
--]]
--[=[
demo:
html = "<font size=\"50\" color=\"#ff0000\" > ab,casdjfladfasdgasdasdgasdfasdfqwetqwetrtwqrtqwerqwerqwerqwetqwetqwerqwerqwer44444444444222222222asdugowe<br>iurlsdjlkasdhga </font><font size=\"28\" color=\"#002\" > ab,21<br>iurlsdjlkasdhga </font><font size=\"22\" color=\"#2231\" > ab,12<br>12 </font><font size=\"10\" color=\"#2202\" > ab,.21<br>1 </font>"
local lable = require ("common.HtmlLabel").new(600,html)
lable:setPosition(400,400)
self._lay:addChild(lable)
--]=]
local HtmlLabel = class("HtmlLabel",function()
return Layout:create()
end)
function HtmlLabel:ctor(width , html)
self._width = width
self._height = 0
self._defaultFontSize = 18
self._defaultFontColor = 0x000000
self:initWithString(html)
end
local headTag = "<font .->"
local lastTag = "</font>"
function HtmlLabel:initWithString(html)
self._html = string.lower(html)
self:removeAllChildrenWithCleanup(true)
local labelList = {}
html = string.gsub(html , "<br>" , "\n")
while string.len(html) > 0 do
local bPos,ePos = string.find(html,lastTag)
local node = {}
local headTagEndPos = 1
if not find then
local hbPos,hePos = string.find(html,headTag)
if hbPos then
-- local head = string.sub(html , hbPos , (hePos-hbPos+1))
local head = string.sub(html , hbPos+5 , (hePos-1))
head = string.gsub(head , "#" , "0x")
head = string.gsub(head , "(%d\")" , "%1,")
local strFunc = " return {" .. head .. "}"
node = assert(loadstring(strFunc))()
if not node.color then
node.color = self._defaultFontColor
else
node.color = tonumber(node.color)
end
if not node.size then
node.size = self._defaultFontSize
else
node.size = tonumber(node.size)
end
headTagEndPos = hePos + 1
-- html = string.sub(html, hePos+1 , string.len(html))
else
node.color = self._defaultFontColor
node.size = self._defaultFontSize
end
node.str = string.sub(html,headTagEndPos,bPos-1)
html = string.sub(html , ePos+1 , string.len(html)) --去除已处理段
else
node.str = html
node.color = self._defaultFontColor
node.size = self._defaultFontSize
html = ""
end
table.insert(labelList , node)
end
if #labelList == 0 then
return
end
local node1 = labelList[1]
self:initRichLabel(node1.str,self._width ,node1.size*(1+0.2) , node1.size , ccc3(math.floor(node1.color/0x10000), math.floor(node1.color/0x100)%0x100 , node1.color % 0x100 ))
for i=2,#labelList do
node1 = labelList[i]
-- print ("%02x%02x%02x",math.floor(node1.color/0x10000), math.floor(node1.color/0x100)%0x100 , node1.color % 0x100 )
self:addString(node1.str, ccc3(math.floor(node1.color/0x10000), math.floor(node1.color/0x100)%0x100 , node1.color % 0x100 ))
end
end
function HtmlLabel:initRichLabel(content ,lineWidth , lineHeight , fntSize , color)
self.lineWidth = lineWidth
self.lineHeight = lineHeight
self._fntSize = fntSize
self._defaultColor = color
self.widthIndex = 0
self.rowIndex = 1
self.nodeList = {}
self.anchorPoint = ccp(0.5,0.5)
self:addString(content)
end
--重新设置一个string
function HtmlLabel:setString(content , color)
self:removeAllChildrenWithCleanup(true)
self.widthIndex = 0
self.rowIndex = 1
self.nodeList = {}
self._defaultColor = color or self._defaultColor
self:addString(content)
end
--增加一个string
function HtmlLabel:addString(labelStr , color)
color = color or self._defaultColor
if self.widthIndex >= self.lineWidth then
self.widthIndex = 0
self.rowIndex = self.rowIndex + 1
end
while labelStr ~= nil and labelStr ~= "" do
local begIndex,endIndex = self:getMaxSubStr(labelStr,self.lineWidth - self.widthIndex , self._fntSize)
if begIndex == nil then --换行
self.widthIndex = 0
self.rowIndex = self.rowIndex + 1
begIndex,endIndex = self:getMaxSubStr(labelStr,self.lineWidth - self.widthIndex, self._fntSize)
end
local subStr = string.sub(labelStr,begIndex,endIndex)
labelStr = string.sub(labelStr,endIndex+1,string.len(labelStr))
local label = Label:create()
label:setFontSize(self._fntSize)
local text = string.gsub(subStr, "\n", "")--去除换行符
label:setText(text)
label:setColor(color)
label:setPositionX(self.widthIndex)
self:addChild(label)
label:setAnchorPoint(ccp(0,0))
label.rowIndex = self.rowIndex
label.srcX = self.widthIndex
table.insert(self.nodeList,label)
self.widthIndex = self.widthIndex + label:getContentSize().width
if string.find(subStr , '\n') then --出现强制换行
self.widthIndex = 0
self.rowIndex = self.rowIndex + 1
end
end
self:updateInset()
end
function HtmlLabel:setContentSize( w , h)
local sz = w
if h then
sz = CCSize(w ,h )
end
self.contentSize = sz
end
function HtmlLabel:getContentSize()
return self.contentSize
end
--更新容器所有Node的位置
function HtmlLabel:updateInset()
local row = self.rowIndex
if self.widthIndex == 0 then --如果最后一行还没内容
row = row - 1
end
local contentSize = CCSize(self.lineWidth,row*self.lineHeight)
local anchorY = contentSize.height * self.anchorPoint.y
local anchorX = contentSize.width * self.anchorPoint.x
for k,v in pairs(self.nodeList) do
v:setPositionY((row-v.rowIndex)*self.lineHeight - anchorY)
v:setPositionX(v.srcX - anchorX)
end
self:setContentSize(contentSize)
end
--设置锚点
function HtmlLabel:setAnchorPoint( x, y )
local pt = nil
if not y then
pt = x
else
pt = ccp(x,y)
end
if pt.x == self.anchorPoint.x and pt.y == self.anchorPoint.y then
return
end
self.anchorPoint = pt
self:updateInset()
end
function HtmlLabel:setPosition( x , y )
local pt = nil
if not y then
pt = x
else
pt = ccp(x,y)
end
CCNode.setPosition(self,pt)
end
--获取宽度范围内,最长子串
function HtmlLabel:getMaxSubStr(_string,width,fntSize)
local result = ""
local index = 1
local is_end = true
local index_max = string.len(_string)
local label = Label:create()
label:setFontSize(fntSize)
while is_end do
local firstCase = string.byte(_string,index)
if firstCase == nil then
break
end
local caseLen = self:sizeof(firstCase) --字符宽度
local strCase = string.sub(_string,index,index + caseLen-1)
if strCase == "\n" then
result = result .. strCase
index = index + caseLen --保留回车返回
break
end
label:setText(result .. strCase)
local t = label:getContentSize().width*label:getScale()
if t < width then
result = result .. strCase
index = index + caseLen
else
is_end = false
end
if index>index_max then
is_end=false
end
end
if result == "" then
return nil
end
return 1,index-1
end
--获取某字符所占字节数
function HtmlLabel:sizeof(firstCase)
if (firstCase >= 0 and firstCase <= 0x7f) then
return 1
elseif firstCase >= 0x80 and firstCase < 0xe0 then
return 2
elseif firstCase >= 0xe0 then
return 3
end
end
function HtmlLabel:getSize()
return CCSize(self._width , self._height)
end
return HtmlLabel