美文网首页
Unity-UGUI无限循环列表

Unity-UGUI无限循环列表

作者: 祝你万事顺利 | 来源:发表于2019-07-25 11:35 被阅读0次

    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
    

    相关文章

      网友评论

          本文标题:Unity-UGUI无限循环列表

          本文链接:https://www.haomeiwen.com/subject/esxglctx.html