cocos2d-x lua 实现listview动态加载item,优化加载

--listview 加载item优化
function gFunUtils.tableShow(listview, number, grid, callback, refresh)--参数说明 数量,模板temp,刷新回调,强制刷新
    if number == nil or grid == nil or callback == nil then
        return 
    end
 
    listview:onScroll(nil)
    listview:removeAllItems()
    if number == 0 then
        listview:jumpToTop()
        return 
    end
 
    local allItems = {}
    if refresh then
        for _, v in pairs(allItems) do 
            v:release()
        end
 
        allItems = {}
    end
 
    local gridSize = grid:getBoundingBox()
    local innerSize = listview:getInnerContainerSize()
    local size = listview:getContentSize()
    local direction = listview:getDirection()
    local offset = listview:getItemsMargin()
    local showNum = 0
 
    if direction == cc.SCROLLVIEW_DIRECTION_HORIZONTAL then
        offset = offset + gridSize.width
        showNum = math.ceil(size.width / offset) + 2
    elseif direction == cc.SCROLLVIEW_DIRECTION_VERTICAL then
        offset = offset + gridSize.height    
        showNum = math.ceil(size.height / offset) + 2
    else
        return
    end
 
    local function sortItems()
        local function func(x, y)
            return x.index < y.index
        end
 
        table.sort(allItems, func)
    end
 
    local function reflushTemp(temp, index)
        if index <= 0 or index > number then
            return 
        end
 
        local parent = temp:getParent()
        if parent == nil then
            print("temp not have parent")
            return 
        end
 
        local item = listview:getItem(index - 1)
        if item == nil then
            print("can not get item, item is nil")
            return 
        end
        
        temp:removeFromParent(false)
        item:addChild(temp)
        temp.index = index
 
        callback(temp, index)
    end
 
    local function initItem(item, index)
        local temp = grid:clone()
        temp:setVisible(true)
        temp:setPosition(cc.p(0, 0))
        temp:setAnchorPoint(cc.p(0, 0))
        temp.index = index
        temp:retain()
        item:addChild(temp)
 
        allItems[index] = temp
        callback(temp, index)
    end
 
    local function refreshItem(item, index) 
        local temp = allItems[index]
        temp.index = index
        local parent = temp:getParent()
        if parent then
            temp:removeFromParent()
        end
        item:addChild(temp)
        callback(temp, index)
    end


    local function getPercent(listview)
        if listview == nil then return end
        local size = listview:getInnerContainerSize()         --内容区大小
        local pos = listview:getInnerContainerPosition()      --内容区当前位置
        local listSize = listview:getContentSize()            --列表可见区域大小
         
        local persent = 100
        --顶部是100,底部是0,所以用100去减       偏移量只移动左下角,所以最大偏移量=总高度 - 列表可见区域
        if size.height-listSize.height > 0 then
            persent = 100 - math.abs(pos.y/(size.height-listSize.height) *100)
        end
     
        return persent
    end
 
    local function checkAndRefreshItems()
        local percent = getPercent(listview) / 100 --getPercent()c++里面重写的方法,取得当前当前位置与总距离的百分比
        if percent < 0 or percent > 100 then
            return 
        end
 
        innerSize = listview:getInnerContainerSize()
        local index = 0
        if direction == cc.SCROLLVIEW_DIRECTION_HORIZONTAL then
            index = math.ceil((innerSize.width - size.width) * percent / offset)
        elseif direction == cc.SCROLLVIEW_DIRECTION_VERTICAL then
            index = math.ceil((innerSize.height - size.height) * percent / offset)
        end
 
        if index > 1 then
            index = index - 1
        end
 
        sortItems()
        local i = 0
        for _, v in pairs(allItems) do 
            if v.index < index then
                reflushTemp(v, index + showNum - 1 - i)
            elseif v.index > index + showNum - 1 then
                reflushTemp(v, index + showNum - (i + 1))
            end
 
            i = i + 1
        end
    end
 
    local function listViewCallBack(event)
        if event.name == "SCROLLING" or event.name == "CONTAINER_MOVED"
            or event.name == "AUTOSCROLL_ENDED" then
            checkAndRefreshItems()
        end
    end  
 
    local default = ccui.Widget:create()
    default:setContentSize(gridSize)
    listview:setItemModel(default)
    for i = 1, number do 
        if i <= showNum then
            local item = default:clone()
            if allItems[i] then
                refreshItem(item, i)
            else
                initItem(item, i)
            end
 
            listview:pushBackCustomItem(item)
        else
            listview:pushBackDefaultItem()
        end
    end
 
    for k, v in pairs(allItems) do 
        if k > number then
            v:release()
            allItems[k] = nil
        end
    end
 
    -- listview:refreshView()
    listview:onScroll(listViewCallBack)
    checkAndRefreshItems()
end

用法:

local function updateTemp(temp, index)
        local info = friendData [index]
        if info == nil then
            return 
        end
        table.print(info)
        --temp:getChildByName("num"):setString(info)
    end

    gFunUtils.tableShow(listview, number, grid,updateTemp)

由于listview 是一次加载完所有item,当列表数据过多时,会造成卡顿,优化为每次滑动到指定位置便加载对应的item,实现动态加载,避免页面卡顿。

你可能感兴趣的:(Cocos2d-x)