通用cocos lua scroll list view 框架进行中。。。

local scroll = {}
local MARGIN_UP
local MARGIN_LEFT
local MARGIN_V_BETWEEN
local MARGIN_H_BETWEEN
local NUM_PER_ROW
local THRESHOLD -- 与self['node' .. iHead]相对Container的高度差
local NODE_IHEAD_POS --inner的子节点位置




--[[
    marginV: item间垂直间距,默认为 0
    marginUp: 上下空白长度, 默认为 0
    marginLeft: 左右空白长度,默认为 0
    numPerRow: 每行item个数 ,默认为 1
]]
function setMargin(self, marginV, marginUp, marginLeft, numPerRow) --如果要设置则在create之前调用
    MARGIN_V_BETWEEN = marginV or 0 
    MARGIN_UP = marginUp or 0
    MARGIN_LEFT = marginLeft or 0
    THRESHOLD = self.scv_height + (self.item_height + MARGIN_V_BETWEEN) / 2 + self.item_height
    NUM_PER_ROW = numPerRow or 1
end




--[[
    modName: 模块名
    refScv: scroll view
    refItem: item model
    refData: 数据table, 用 #refData可获取长度
    startRow: 希望从第几行开始显示, 默认为 1 ,程序会根据情况调整至合理位置
]]
function create(self, modName, refScv, refItem, refData, startRow)--一个页面可以重复调用
    if self.iHead then
        self:onExit() --主要为释放上一次的资源
    end
    self.modName = modName
    self.scv = refScv
    self.inner= self.scv:getInnerContainer()
    self.item = refItem
    self.item:setAnchorPoint(0, 0)
    self.item:retain()
    self.data = refData
    self.item_width = self.item:getContentSize().width
    self.item_height = self.item:getContentSize().height
    self.scv_width = self.scv:getContentSize().width
    self.scv_height = self.scv:getContentSize().height
    self.iHead = startRow or 1
    self:set_new_iHead_iTail() --首尾行需修正
    self.pre_iHead = self.iHead
    
    self:refresh('two_more_rows')
    
    local function monitor()
        self:monitor()
    end
    self.handle = cc.Director:getInstance():getScheduler():scheduleScriptFunc(monitor, 0, false)
end


local function monitor(self)
    local innerY = self.inner:getPositionY()
    if innerY + NODE_IHEAD_POS > THRESHOLD then --把头行移至尾后
        if self.iTail == #self.data then
            return
        end
        self['node' .. self.iHead + 1]:removeFromParent()
        self['node' .. self.iHead + 1]:setPosition(0, NODE_IHEAD_POS)
        self.inner:addChild(self['node' .. self.iHead + 1])
        self['node' .. self.iHead]:removeFromParent()
        self['node' .. self.iHead]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
        self['node' .. self.iTail]:addChild(self['node' .. self.iHead])
        self.inner:setPosition(0, innerY - (self.item_height + MARGIN_V_BETWEEN))
        
        self['node' .. self.iTail + 1] = self['node' .. self.iHead]
        self['node' .. self.iHead] = nil
        for j = 1, NUM_PER_ROW do
            local index1 = (self.iHead - 1) * NUM_PER_ROW + j
            local index2 = (self.iTail + 1 - 1) * NUM_PER_ROW + j
            self['item' .. index2] = self['item' .. index1]
            self['item' .. index1] = nil
        end
        self.iHead = self.iHead + 1
        self.iTail = self.iTail + 1
        self:show_a_row(self.iTail)
    else
        if self.iHead == 1 then
            return
        end
        self['node' .. self.iTail]:removeFromParent()
        self['node' .. self.iTail]:setPosition(0, NODE_IHEAD_POS)
        self.inner:addChild(self['node' .. self.iTail])
        self['node' .. self.iHead]:removeFromParent()
        self['node' .. self.iHead]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
        self['node' .. self.iTail]:addChild(self['node' .. self.iHead])
        self.inner:setPosition(0, innerY + (self.item_height + MARGIN_V_BETWEEN))
        
        self['node' .. self.iHead - 1] = self['node' .. self.iTail]
        self['node' .. self.iTail] = nil
        for j = 1, NUM_PER_ROW do
            local index1 = (self.iTail - 1) * NUM_PER_ROW + j
            local index2 = (self.iHead - 1 - 1) * NUM_PER_ROW + j
            self['item' .. index2] = self['item' .. index1]
            self['item' .. index1] = nil 
            if not self['item' .. index2]:isVisible() then
                self['item' .. index2]:setVisible(true)
            end
        end
        self.iHead = self.iHead - 1
        self.iTail = self.iTail - 1
        self:show_a_row(self.iHead)
    end
end


function jump_to(self, i) -- jump to i'th row
    self.pre_iHead = self.iHead
    self.iHead = i
    self:refresh('two_more_rows')
end


function get_head_index(self) --返回self.iHead(首行标记)和innerContainer 的位置
    return self.iHead
end


function get_inner_posY(self)
    return self.inner:getPositionY()
end


function set_inner_posY(self, innerY)
    self.inner:setPosition(0, innerY)
end


function onExit(self) --前端关闭页面前一定要调用,页面中不用手动调用
    if self.handle then
        cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
        self.handle = nil
    end
    if self.item then
        self.item:release()
        self.item = nil
    end
    local j =self.iHead
    if self['node' .. j] then
        self['node' .. j]:removeFromParent()
    end
    while self['node' .. j] do  --虽然上面已经释放,但是self内相关引用值不为nil,需赋为nil
        self['node' .. j] = nil
        for k = 1, NUM_PER_ROW do
            local index = (j - 1) * NUM_PER_ROW + k
            self['item' .. index] =nil
        end
        j = j + 1
    end
    self.iHead = nil
end


----------------------------------------------------------------------------
------------------------------以上函数外部可调用-----------------------------
----------------------------------------------------------------------------


local function show_a_row(self, i) -- i'th row
    for j = 1, NUM_PER_ROW do
        local index = (i - 1)*NUM_PER_ROW + j
        if index > #self.data then
            if not self['item' .. index] then
                self['item' .. index] = self.item:clone()
                self['item' .. index]:setPosition(MARGIN_LEFT + (self.item_width + MARGIN_H_BETWEEN) * (j - 1), -self.item_height)
                self['node' .. i]:addChild(self['item' .. index])
                self['item' .. index]:setVisible(false)
            end
        else
            if not self['item' .. index] then
                self['item' .. index] = self.item:clone()
                self['item' .. index]:setPosition(MARGIN_LEFT + (self.item_width + MARGIN_H_BETWEEN) * (j - 1), -self.item_height)
                self['node' .. i]:addChild(self['item' .. index])
            else
                if not self['item' .. index]:isVisible() then
                    self['item' .. index]:setVisible(true)
                end
            end
            
            self:set_an_item(self['item' .. index], index) 
        end
    end
end


local function set_an_item(self, item, i)
--    _G[self.modName].getInstance():set_an_item(item, i) --测试时注释掉
end




local function refresh(self , two_more_rows) --外界调用忽略第二个参数
    local j = self.pre_iHead  -- the previous index of head row
    self:set_new_iHead_iTail()
    local height = 2 * MARGIN_UP + (self.iTail - self.iHead + 1) * (self.item_height + MARGIN_V_BETWEEN) - MARGIN_V_BETWEEN --现在所需的inner高度
    height = math.max(self.scv_height, height)
    self.scv:setInnerContainerSize(cc.size(self.scv_width, height))   
    NODE_IHEAD_POS =  height - MARGIN_UP -- 头节点的位置(相对于inner) ,其余node(i)的父节点是其上面的节点node(i - 1)
    --复用之前可能存在的行,但之前的iHead ~ iTail 的行数或多或少或正好
    local i = self.iHead  -- the current index of head row
    while i <= self.iTail do  
        if j == self.pre_iHead then
            if not self['node' .. j] then
                self['node' .. j] = cc.Node:create()
                self.inner:addChild(self['node' .. j])
            end
            self['node' .. j]:setPosition(0, NODE_IHEAD_POS)
        else  
            if not self['node' .. j] then
                self['node' .. j]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
                self['node' .. j - 1]:addChild(self['node' .. j]) 
            end
        end
        self['node' .. i] = self['node' .. j]  --需要注意前后node名可能相同
        for k = 1, NUM_PER_ROW do 
            local index1 = (j - 1) * NUM_PER_ROW + k
            local index2 = (i - 1) * NUM_PER_ROW + k
            self['item' .. index2] = self['item' .. index1]  --需要注意前后item名可能相同
            if index2 ~= index1 then
                self['item' .. index1] = nil
            end
        end
        if i ~= j then
            self['node' .. j] = nil --现在仅有 self['node' .. i]引用着 之前self['node' .. j]引用的 node
        end
        self:show_a_row(i)
        i = i + 1
        j = j + 1      --这里 j不用担心上界,如果item是nil则会在show_a_row里创建
    end
    
    if self['node' .. j] then   --因为node(i)的父节点是node(i - 1),所以remove一个就行
        self['node' .. j]:removeFromParent()
    end
    while self['node' .. j] do  --虽然上面已经释放,但是self内相关引用值不为nil,需赋为nil
        self['node' .. j] = nil
        for k = 1, NUM_PER_ROW do
            local index = (j - 1) * NUM_PER_ROW + k
            self['item' .. index] =nil
        end
        j = j + 1
    end
    
    if two_more_rows then
        self.count = 0
        if self.count < 2 then
            self:one_more_row_to_head()
        end
        if self.count < 2 then
            self:one_more_row_to_tail()
        end
        if self.count < 2 then
            self:one_more_row_to_head()
        end
        if self.count < 2 then
            self:one_more_row_to_tail()
        end
    end
end


local function one_more_row_to_head(self)
    if self.iHead == 1 then
        return
    end
    self.count = self.count + 1
    local height = self.inner:getContentSize().height
    self.inner:setContentSize(cc.size(self.scv_width, height + (self.item_height + MARGIN_V_BETWEEN))) --这和setInnerContainerSize( 延伸方向不同
    self['node' .. self.iHead - 1] = cc.Node:create()
    NODE_IHEAD_POS =  height - MARGIN_UP
    self['node' .. self.iHead - 1]:setPosition(0, NODE_IHEAD_POS)
    self.inner:addChild(self['node' .. self.iHead - 1])
    self['node' .. self.iHead]:removeFromParent()
    self['node' .. self.iHead]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
    self['node' .. self.iHead - 1]:addChild(self['node' .. self.iHead])
    self:show_a_row(self.iHead - 1)
    self.iHead = self.iHead - 1
end


local function one_more_row_to_tail(self)
    if self.iTail == #self.data then
        return
    end
    self.count = self.count + 1
    local height = self.inner:getContentSize().height
    self.scv:setInnerContainerSize(cc.size(self.scv_width, height + (self.item_height + MARGIN_V_BETWEEN)))
    self['node' .. self.iTail + 1] = cc.Node:create()
    NODE_IHEAD_POS =  height - MARGIN_UP
    self['node' .. self.iTail + 1]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
    self['node' .. self.iTail]:addChild(self['node' .. self.iTail])
    self:show_a_row(self.iTail + 1)
    self.iTail = self.iTail + 1
end




--当删除或添加items后应该调整之前的头尾位置
local function set_new_iHead_iTail(self )
    local visible_rows = math.ceil(self.scv_height / (self.item_height + self.MARGIN_V_BETWEEN)) --可视域行数
    local max_rows = math.ceil(#self.data / NUM_PER_ROW)
    self.iTail = self.iHead + visible_rows - 1
    self.iTail = math.min(max_rows, self.iTail)
    self.iHead = self.iTail - visible_rows + 1
    self.iHead = math.max(1, self.iHead)
    --首先会显示可见区域items,然后最多添加 2 行,添加顺序  头  -> 尾  -> 头  -> 尾
end




_G['scroll'] = scroll
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值