cocos2d-lua 3.4版本的富文本[转载的]

-- Author: zlf
-- Date: 2016年5月9日17:05:37
-- 简易富文本

RichText = class("RichText", function()
    return ccui.Layout:create()
end)

--自适应最大宽度,自动换行
RichText.auto = 1
--系统公告,无限宽
RichText.gmnotice = 2

local cache = cc.SpriteFrameCache:getInstance()

--[[
    @param data 富文本参数(table)
    data示例:{{txt="12呵呵asdasad###3", color="#FF9966", isUnLine = 1, data = "函数回调参数"}, {img = "Star.png", data = "函数回调参数"}}

    使用方式:
    local richLabel = RichText:create()
    setDrawType可用可不用,但是create之后一定要手动调用init函数
    richLabel:setDrawType(1)
    richLabel:init(param, 300)
    richLabel:setPosition(300, 320)
    self:addChild(richLabel) 

    data里面元素作用详解:
    txt代表要创建的控件是ccui.Text,img则代表ccui.ImageView, color设置ccui.Text的字体颜色
    isUnLine用来表示ccui.Text是否需要下划线,nil或者false代表不画, data作为控件回调函数的参数
    fontSize用来设置ccui.Text的字体大小

    @param maxWidth 富文本的最大宽度,设置了最大宽度,可以自动换行

    @param globalCallBack 全局回调函数,当这个参数存在时,所有的控件回调都调用这个函数

    @param globalFontSize 全局字体大小,当这个参数存在时,所有的ccui.Text的字体大小都设置为这个参数

    @param this 类指针,callback(this, callParam)这个作用,语法糖


]]
function RichText:create()
    local ret = RichText.new()
    return ret
end

--2016年6月12日19:53:03 去掉了几个全局参数  callback字段也不用了  
-- function RichText:init(param, maxWidth, globalCallBack, globalColor, globalFontSize, this)
function RichText:init(param, maxWidth, globalCallBack, this)
    if type(param) ~= "table" then
        return
    end
    self:removeAllChildren() 
    self.globalCallBack = globalCallBack
    self.globalFontSize = globalFontSize
    self.renderWidth = 0
    self.renderLine = 0
    maxWidth = maxWidth or 400
    local curWidth = 0
    local row = 0
    local curIndex = 1
    local allWidget = {}
    for i=1,#param do
        local x, y = 0
        if param[i].txt and param[i].txt ~= "" then
            local textTb = Utils.separate(param[i].txt)
            for j=1,#textTb do
                local color = self:getNeedColor(globalColor, param[i].color)
                local widget = self:getLabel(textTb[j], color, globalCallBack, param[i].data, globalFontSize or param[i].fontSize, this)
                widget.isUnLine = param[i].isUnLine
                local size = widget:getContentSize()
                x, y = curWidth, size.height * row
                local width = size.width
                if curWidth + width > maxWidth then
                    curWidth = width
                    row = row - 1
                    curIndex = curIndex + 1
                    x, y = 0, size.height * row
                else
                    curWidth = curWidth + width
                end
                if not allWidget[curIndex] then
                    allWidget[curIndex] = {}
                end
                table.insert(allWidget[curIndex], widget)
                widget:setPosition(x, y)
                widget:setAnchorPoint(cc.p(0, 0.5))
                widget.trueRow = curIndex
                self:addChild(widget)
            end
        elseif param[i].img then
            local widget = self:getImage(param[i].img, globalCallBack, globalParam or param[i].data, this)
            local size = widget:getContentSize()
            x, y = curWidth, size.height * row
            if curWidth + size.width > maxWidth then
                curWidth = size.width
                row = row - 1
                curIndex = curIndex + 1
                x, y = 0, size.height * row
            else
                curWidth = curWidth + size.width
            end
            if not allWidget[curIndex] then
                allWidget[curIndex] = {}
            end
            table.insert(allWidget[curIndex], widget)
            widget:setAnchorPoint(cc.p(0, 0.5))
            widget:setPosition(x, y)
            self:addChild(widget)
        elseif param[i].anim then
        end
    end
    self.renderWidth = curIndex > 1 and maxWidth or curWidth
    self.renderLine = curIndex    
    self:adjust(allWidget)
end

function RichText:setDrawType(type)
    self.DrawType = type
end

function RichText:setRowSpace(space)
    self.rowSpace = space
end

function RichText:adjust(allWidget)
    self.DrawType = self.DrawType or self.auto
    self.renderHeight = 0
    if self.DrawType == self.auto then
        self.rowSpace = self.rowSpace or 0
        local _max = {}
        for i=1,#allWidget do
            local maxHeight = 0
            for k,v in pairs(allWidget[i]) do
                local size
                if v.isAnim then
                    size = v.size
                else
                    size = v:getContentSize()
                end
                if size.height * 0.5 > maxHeight then
                    maxHeight = size.height * 0.5 + self.rowSpace
                end
            end
            self.renderHeight = self.renderHeight + maxHeight
            if i == 1 then
                self.posX = maxHeight - self.rowSpace
            end
            if maxHeight > 0 then
                if _max[i-1] then
                    _max[i] = maxHeight*2 + _max[i-1]
                else
                    _max[i] = maxHeight
                end
            
                for k,v in pairs(allWidget[i]) do
                    local height = 0 
                    if _max[i-1] then
                        height = -maxHeight - _max[i-1]
                    else
                        height = 0
                    end
                    v:setPositionY(height)
                    if v.isUnLine then
                        self:drawUnLine(self, v)
                    end
                end
            end
        end
        self:setContentSize(cc.size(self.renderWidth, self.renderHeight))
    else
        local all = {}
        local allWidth = {}
        local maxHeight = -100
        for k,v in pairs(allWidget) do
            for key,value in pairs(v) do
                local size
                if value.isAnim then
                    size = value.size
                else
                    size = value:getContentSize()
                end
                if size.height * 0.5 > maxHeight then
                    maxHeight = size.height * 0.5
                end
                table.insert(all, value)
                table.insert(allWidth, value:getContentSize().width)
            end
            if k == 1 then
                self.posX = maxHeight
            end
        end
        self.renderHeight = maxHeight
        local curWidth = 0
        for i=1,#all do
            all[i]:setPosition(curWidth, 0)
            curWidth = curWidth + allWidth[i]
            self.renderWidth = curWidth
            if all[i].isUnLine then
                self:drawUnLine(self, all[i])
            end
        end
        self.renderLine = 1
    end
    self:setContentSize(cc.size(self.renderWidth, 0))
end

function RichText:getRenderWidth()
    return self.renderWidth
end

function RichText:getRenderLine()
    return self.renderLine
end

function RichText:getRenderHeight()
    return self.renderHeight
end

function RichText:drawUnLine(parent, widget)
    local color4F = cc.convertColor(widget:getColor(), "4f")
    color4F.a = 1
    local pos = cc.p(widget:getPosition())
    self:getDrawNode(parent):drawLine(cc.p(pos.x, pos.y - widget:getContentSize().height/2), cc.p(pos.x + widget:getContentSize().width, pos.y - widget:getContentSize().height/2), color4F)
end

function RichText:getDrawNode(parent)
    if not self.drawNode then
        self.drawNode = cc.DrawNode:create()
        parent:addChild(self.drawNode)
    end
    return self.drawNode
end

function RichText:getLabel(param, color, callback, funcParam, fontSize, this)
    local text = ccui.Text:create()
    text:setFontName("Arial")
    text:setFontSize(fontSize or 22)
    text:setString(param)
    if color then
        text:setColor(color)
    end
    if funcParam then
        text:setTouchEnabled(true)
        if type(callback) == "function" then
            text:addTouchEventListener(function(sender, event)
                if event == ccui.TouchEventType.ended then
                    if this then
                        callback(this, funcParam)
                    else
                        callback(funcParam)
                    end
                end
            end)
        end
    end
    text:enableShadow(cc.c4b(0,0,0,255), cc.size(1,-1))
    return text
end

function RichText:getImage(param, callback, callParam, this)
    local img = ccui.ImageView:create()
    if not cache:getSpriteFrame(param) then
        img:loadTexture(param)
    else
        img:loadTexture(param, ccui.TextureResType.plistType)
    end
    if callParam then
        img:setTouchEnabled(true)
        if type(callback) == "function" then
            img:addTouchEventListener(function(sender, event)
                if event == ccui.TouchEventType.ended then
                    if this then
                        callback(this, callParam)
                    else
                        callback(callParam)
                    end
                end
            end)
        end
    end
    return img
end

function RichText:getNeedColor(p1, p2)
    local result
    if p1 then
        result = p1
    elseif p2 then
        result = p2
    else
        result = cc.c3b(255,255,255)
    end
    if type(result) == "string" then
        result = Utils.str2Color(result)
    end
    return result
end

function RichText:setPos(x, y)
    self.posX = self.posX or 0
    if type(x) == "table" then
        x.y = x.y - self.posX
        self:setPosition(x)
    else
        y = y - self.posX
        self:setPosition(x, y)
    end
end

 

posted @ 2017-05-13 12:01  黔王  阅读(2034)  评论(0编辑  收藏  举报