Unity版本:2017.4
简介:
UGUI使用ScrollView、GridLayoutGroup实现无限循环列表,支持数据刷新,支持跳转,支持动态插入/删除
实现思路:
基于Lua、UGUI(ScrollRect)实现
1.将全部样式存入一个Table
2.计算根据全部数据出整个Content的高度
3.根据当前Content的位置(anchoredPosition),计算出在显示区域内的子物体的索引
4.根据前面计算的可显示子物体索引,读取数据将相关数据进行显示
5.添加、删除、目标位置数据的跳转
Lua实现代码:
1.初始化样式
function InfiniteScrollRect:InitPreStyle()
for i = 1, self.srContent:GetComponent(UnityEngine.RectTransform).childCount do
local contentChild = self.srContent:GetComponent(UnityEngine.RectTransform):GetChild(i - 1)
table.insert(
self.preStyleTab,
{
content = contentChild,
height = contentChild.sizeDelta.y
}
)
table.insert(self.cachePool, {})
table.insert(self.cachePool[i], contentChild)
end
end
2.读取数据计算整个Content高度
function InfiniteScrollRect:CalculateHeight()
local contentHeight = 0
for dataIndex, dataItem in ipairs(self.dataTable) do
local height = self.preStyleTab[dataItem.style].height
contentHeight = contentHeight + height
end
self.srContent.sizeDelta = UnityEngine.Vector2(self.srContent.sizeDelta.x, contentHeight)
end
3.根据当前content的anchoredPosition计算可见
function InfiniteScrollRect:CalculateAreaIndexAndPadY( )
local height, padY = 0, 0
local viewAreaTopDataIndex, viewAreaBottomDataIndex = -1, -1
local contentPosY = self.srContent:GetComponent(UnityEngine.RectTransform).anchoredPosition.y
local scrollingScrollRectHeight = self.scrollingScrollRect:GetComponent(UnityEngine.RectTransform).sizeDelta.y
for dataIndex, dataItem in ipairs(self.dataTable) do
local tempH = height
height = height + self.preStyleTab[dataItem.style].height
if viewAreaTopDataIndex == -1 and height > contentPosY then
viewAreaTopDataIndex = dataIndex
padY = tempH
end
if viewAreaBottomDataIndex == -1 and (dataIndex == #self.dataTable or ((contentPosY + scrollingScrollRectHeight) < height)) then
viewAreaBottomDataIndex = dataIndex
break
end
end
return viewAreaTopDataIndex, viewAreaBottomDataIndex, padY
end
4.根据当前可见区域进行显示样式对应的GameObject,使用缓存池,如果缓存池轴中有可用的样式,将直接使用可用样式,缓存池中没有可用样式,实例化一个样式,并将其放入激活列表中
function InfiniteScrollRect:InstantiateScrollRectItems(topIndex, botIndex)
self:clearActivatingPool()
for i = topIndex, botIndex do
local curStyle = self.dataTable[i].style
local contentItem = nil
if #self.cachePool[curStyle] > 0 then
local item = table.remove(self.cachePool[curStyle])
item.gameObject:SetActive(true)
item:SetAsLastSibling()
contentItem = item
else
local opLuaFile = OpenLuaFile.StaticIT()
local instanceTr = opLuaFile:InstanceTransform(self.preStyleTab[curStyle].content, self.preStyleTab[curStyle].content.parent):GetComponent(UnityEngine.RectTransform)
instanceTr:SetAsLastSibling()
contentItem = instanceTr
end
table.insert(self.activatingPool, {content = contentItem, style = curStyle})
end
end
5.遍历已经激活的列表,根据数据进行内容刷新
function InfiniteScrollRect:CalculateViewArea(forceFresh)
local topIndex, botIndex, padY = self:CalculateAreaIndexAndPadY()
local topDif, botDif = (self.lastTopIndex ~= topIndex),(self.lastBottomIndex ~= botIndex)
if topDif or botDif or forceFresh then
if topDif then
local verticalLayoutGroup = self.srContent:GetComponent(UI.VerticalLayoutGroup)
verticalLayoutGroup.padding.top = padY
end
self:InstantiateScrollRectItems(topIndex, botIndex)
self:ShowItemDatas(topIndex, botIndex)
end
self.lastTopIndex = topIndex
self.lastBottomIndex = botIndex
end
function InfiniteScrollRect:ShowItemDatas(topIndex, botIndex)
for i, v in ipairs(self.activatingPool) do
self.freshFunc(v.content, self.dataTable[topIndex + i - 1], topIndex + i - 1)
end
end
网友评论