cocos2d-x lua開發筆記:ListView加載多個item優化處理 (轉)

轉自[sinat_24556247的博客]
coco2d-x開發過程當中,用過ListView的都知道,ListView是一次性將全部的item加載出來的,因此在加載數量較多的item的時候,後致使界面卡頓的現象。其實改用tableView就是解決這一問題,可是tableView的使用卻徹底不如listView成熟,因此我這裏主要是將listView進行優化處理,我使用的是coco3.5 版本,在lua下開發的。c++

具體的思路是,好比要加載100個item,首先先用常規方法建立100個空widget到ListView上。而後建立屏幕上能顯示下的item的最大個數加1(好比說10個),按順序加載到widget。以後監聽ListView的滾動事件,判斷當前要顯示的10個item是在哪幾個widget,而後將其從原來的widget上刪除,加到新的widget 上便可。優化

下面的具體代碼,寫的不是很好,僅供參考!ui

修改cocos/framework/extends/UIListView.lua 添加一下代碼lua

function ListView:tableShow(number, grid, callback, refresh)--參數說明 數量,模板temp,刷新回調,強制刷新
    if number == nil or grid == nil or callback == nil then
        return 
    end

    self:onScroll(nil)
    self:removeAllItems()
    if number == 0 then
        self:jumpToTop()
        return 
    end

    self.allItems = self.allItems or {}
    if refresh then
        for _, v in pairs(self.allItems) do 
            v:release()
        end

        self.allItems = {}
    end

    local gridSize = grid:getBoundingBox()
    local innerSize = self:getInnerContainerSize()
    local size = self:getContentSize()
    local direction = self:getDirection()
    local offset = self: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(self.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
            printWarn("temp not have parent")
            return 
        end

        local item = self:getItem(index - 1)
        if item == nil then
            printWarn("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)

        self.allItems[index] = temp
        callback(temp, index)
    end

    local function refreshItem(item, index) 
        local temp = self.allItems[index]
        temp.index = index
        local parent = temp:getParent()
        if parent then
            temp:removeFromParent()
        end
        item:addChild(temp)
        callback(temp, index)
    end

    local function checkAndRefreshItems()
        local percent = self:getPercent() / 100 --getPercent()c++裏面重寫的方法,取得當前當前位置與總距離的百分比
        if percent < 0 or percent > 100 then
            return 
        end

        innerSize = self: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(self.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" then
            checkAndRefreshItems()
        end
    end  

    local default = ccui.Widget:create()
    default:setContentSize(gridSize)
    self:setItemModel(default)
    for i = 1, number do 
        if i <= showNum then
            local item = default:clone()
            if self.allItems[i] then
                refreshItem(item, i)
            else
                initItem(item, i)
            end

            self:pushBackCustomItem(item)
        else
            self:pushBackDefaultItem()
        end
    end

    for k, v in pairs(self.allItems) do 
        if k > number then
            v:release()
            self.allItems[k] = nil
        end
    end

    self:refreshView()
    self:onScroll(listViewCallBack)
    checkAndRefreshItems()
end

function ListView:clearUp()
    self.allItems = self.allItems or {}
    for k, v in pairs(self.allItems) do 
        v:release()
        self.allItems[k] = nil
    end
    self:removeAllItems()
end

function ListView:getShowItems()
    return self.allItems or {}
end

實際調用時.net

local all = {}
for i=1, 100 do 
    table.insert(all, i)
end

local function updateTemp(temp, index)
    local info = all [index]
    if info == nil then
      	return 
    end

    print("item "..info )
    --temp:getChildByName("num"):setString(info)
end

self.listView_1:tableShow(#all,  panel, updateTemp)
相關文章
相關標籤/搜索