实现功能:基于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