unity滑动列表简单优化(资源复用)

实现功能:基于UGUI自带的ScrollRect,对列表元素进行复用
基本思路:在原生ScrollRect的基础上,添加onValueChanged监听,通过Content节点的anchoredPosition来判断当前可见的第一个元素的索引值,回收超出视图的部分,加载出视图上的所有元素(对回收的元素进行复用)
与上一版的区别:删除了网格布局(Grid Layout Group)和内容大小适配器(Content Size Fitter)的使用
PS:一定要先计算好Content的sizeDelta,这边元素的预制体锚点设置在(0.5, 0.5)。
核心部分代码:
 function M:initialize()
    --- 当前的index
    self._index         = -1
    --- 可视的item链表
    self._itemList      = {}
    --- 未使用的池子
    self._unUseQueue    = {}    
    --- 存储已经加载过的sprite
    self._picSprites = {}
end

--- 初始化数值参数
function M:initParams()
    self._rowNum        = 2
    --- 列表数量
    self._count         = 20
    self._colNum        = Mathf.CeilToInt(self._count/self._rowNum)
    --- item的大小
    self._cellSize      = Vector2(225, 225)--self._gridGroup.cellSize
    --- 间隔
    self._spacing       = Vector2(6.5, 10)--self._gridGroup.spacing
    --- 可视列数量
    self._viewCount     = Mathf.CeilToInt(CAMERA_WIDTH * 200/(self._cellSize.x +  self._spacing.x)) + 2
    --- 设置content的大小
    self._content.sizeDelta = Vector2(self._cellSize.x * self._colNum + (self._spacing.x * self._colNum - 1), self._cellSize.y * self._rowNum + self._spacing.y * (self._rowNum - 1))
end

--- 值变化
function M:onValueChanged(pos)
    local index = self:getPosIndex()
    if self._index ~= index and index > -1 then
        self._index = index
        for i = #self._itemList, 1, -1 do
            local item = self._itemList[i]
            if item._col < index or item._col > index + self._viewCount then
                --- 收入回收池
                self:addUnUseQueue(item, i)
            end
        end
        for i = self._index, self._index + self._viewCount do
            if i > 0 and i <= self._colNum then
                local isOk = false
                for k,v in pairs(self._itemList) do
                    if v._col == i then
                        isOk = true
                        -- break
                    end
                end
                if not isOk then
                    self:createItem(1, i)
                    self:createItem(2, i)
                end
            end
        end
    end
end

--- 收入回收池
function M:addUnUseQueue(item, i)
    table.remove(self._itemList, i)
    item:unUse()
    table.insert(self._unUseQueue, item)
end

--- 创建元素
function M:createItem(row, col)
    if (col - 1) * 2 + row > self._count then return end
    local item = nil
    if #self._unUseQueue > 0 then
        item = table.remove(self._unUseQueue, 1)
    else
        item = self:createNewItem()
    end
    item:recycle()
    item:updateData(row, col)
    item._rectTF.anchoredPosition = self:getPosition(row, col)
    table.insert(self._itemList, item)
end

--- 创建一个新的可用的元素
function M:createNewItem()
    local go = UnityEngine.GameObject.Instantiate(self._iconPre, self._content)
    local item = go.transform:GetLuaTable()
    return item
end

--- 获取当前位置的index
function M:getPosIndex()
    -- print(self._content.anchoredPosition.x)
    return Mathf.FloorToInt(self._content.anchoredPosition.x / -(self._cellSize.x + self._spacing.x))
end

--- 获取当前位置
function M:getPosition(row, col)
    local y = row == 1 and (self._cellSize.y + self._spacing.y) or -(self._cellSize.y + self._spacing.y)
    return Vector3((col - 0.5) * (self._cellSize.x + self._spacing.x), y/2, 0)
end

 

posted @ 2022-04-14 11:16  -XZY  阅读(415)  评论(0编辑  收藏  举报