local scroll = {}
local MARGIN_UP = 0
local MARGIN_LEFT = 0
local MARGIN_V_BETWEEN = 0
local MARGIN_H_BETWEEN
local NUM_PER_ROW
local THRESHOLD -- 与self['node' .. iHead]相对Container的高度差阈值
local NODE_IHEAD_POS --inner的子节点位置高度 ,每次inner height 有变化都要更新
--[[
marginV: item间垂直间距,默认为 0
marginUp: 上下空白长度, 默认为 0
marginLeft: 左右空白长度,默认为 0
]]
function scroll:set_margin(marginV, marginUp, marginLeft) --如果不调set_margin将使用上次的margin,整个游戏第一次调用前为上面的值
print("set_margin enter")
MARGIN_V_BETWEEN = marginV or 0
MARGIN_UP = marginUp or 0
MARGIN_LEFT = marginLeft or 0
end
--[[
modName: 模块名
refScv: scroll view
refItem: item,要能克隆 item:clone() ,和获得item大小 item:getContentSize()
refData: 数据table, 用 #refData可获取长度
numPerRow: 每行item个数 ,默认为 1
startRow: 希望从第几行开始显示, 默认为 1 ,程序会根据情况调整至合理位置
]]
function scroll:create( modName, refScv, refItem, refData, numPerRow, startRow)--一个页面中打开一个标签使用一次,上次的scv作废,但下面有方法还原状态
print("create enter ")
if self.iHead then
self:onExit() --主要为释放上一次的资源
end
self.modName = modName
self.scv = refScv
self.inner= self.scv:getInnerContainer()
self.item = refItem
self.item:ignoreAnchorPointForPosition(false)
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.scv:setInnerContainerSize(cc.size(self.scv_width, self.scv_height)) --这个很重要,否则inner会有偏移(受上次位置影响)
NUM_PER_ROW = numPerRow or 1
MARGIN_H_BETWEEN = 0
if NUM_PER_ROW ~= 1 then
MARGIN_H_BETWEEN = (self.scv_width - 2 * MARGIN_LEFT - NUM_PER_ROW * self.item_width) / (NUM_PER_ROW - 1)
MARGIN_H_BETWEEN = math.max(0, MARGIN_H_BETWEEN)
end
THRESHOLD = self.scv_height + (self.item_height + MARGIN_V_BETWEEN) / 2 + self.item_height
self.iHead = startRow or 1
self:set_new_iHead_iTail() --首尾行需修正(首行为self.iHead,尾行为self.iTail)
self.pre_iHead = self.iHead
self:reuse_pre_rows() --这个函数有复用,删除,新增综合功能
self:head_tail_head_tail()
self.delY = 0 -- monitor()内会率先用到
local function monitor()
self:monitor()
end
self.handle = cc.Director:getInstance():getScheduler():scheduleScriptFunc(monitor, 0, false)
local function onTouchBegan(touch, event)
self.delY = 0
return true
end
local function onTouchMoved(touch, event)
self.delY = touch:getLocation().y - touch:getPreviousLocation().y
end
local function onTouchEnded(touch, event)
-- if self.delY == 0 then
-- if self.item_touch_enabled and self.iTail ~= 0 then --不为空
-- local touchX = touch:getLocation().x
-- local touchY = touch:getLocation().y
-- local item_i = self:get_the_item_touched(touchX,touchY)
-- if item_i then
-- _G[modName].getInstance():touch_an_item(self['item' .. item_i], item_i) -- item, i
-- end
-- end
-- end
end
self.listener1 = cc.EventListenerTouchOneByOne:create()
self.listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
self.listener1:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED )
self.listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
end
function scroll:jump_to( i) -- jump to i'th row
self.pre_iHead = self.iHead
self.iHead = i
self:reuse_pre_rows()
self:head_tail_head_tail()
if self.max_row - i + 1 < self.visible_rows then -- 为了能完全显示最后一个item
self.inner:setPosition(0, 0)
end
end
function scroll:refresh() --外部刷新
print("refresh enter")
self.pre_iHead = self.iHead
self.pre_iTail = self.iTail
self.pre_max_row = self.max_row
self.pre_innerY = self.inner:getPositionY()
self:reuse_pre_rows()
self:tail_tail_head_head()
if self.pre_max_row >= self.max_row then --行数减少或不变
if self.iTail == self.pre_iTail then
self.inner:setPosition(0, self.pre_innerY)
else
self.inner:setPosition(0, 0)
end
else --行数增多
if self.iTail == self.pre_iTail then
self.inner:setPosition(0, self.pre_innerY)
else
local pre_height = 2 * MARGIN_UP + (self.pre_iTail - self.pre_iHead + 1) * (self.item_height + MARGIN_V_BETWEEN) - MARGIN_V_BETWEEN
pre_height = math.max(self.scv_height, pre_height)
local pre_y = self.scv_height - pre_height
local del_y = self.pre_innerY - pre_y
local height = 2 * MARGIN_UP + (self.iTail - self.iHead + 1) * (self.item_height + MARGIN_V_BETWEEN) - MARGIN_V_BETWEEN
height = math.max(self.scv_height, height)
local y = self.scv_height - height
self.inner:setPosition(0, y + del_y)
end
end
end
--function scroll:register_item_touch()
-- self.item_touch_enabled = true
--end
--
--function scroll:unregister_item_touch()
-- self.item_touch_enabled = false
--end
function scroll:get_current_state() --离开标签时获取信息 “info”
local innerY = self.inner:getPositionY() --有两种情况要调整位置
if self.iHead == 1 then
if innerY < self.scv_height - (NODE_IHEAD_POS + MARGIN_UP) then
innerY = self.scv_height - (NODE_IHEAD_POS + MARGIN_UP)
end
end
if self.iTail == #self.data then
if innerY > 0 then
innerY = 0
end
end
return {self.iHead, self.iTail, innerY}
end
function scroll:set_current_state(state) --再次回到标签,先调用set_margin, create,再用参数“info”调
self.pre_iHead = self.iHead -- 考虑到之前的标签会有items个数变化
self.iHead = state[1]
self:reuse_pre_rows()
self:tail_tail_head_head()
if self.iTail - self.iHead == state[2] - state[1] and self.iHead == state[1] then
self.inner:setPosition(0, state[3])
else
self.inner:setPosition(0, 0)
end
end
function scroll:onExit() --前端关闭页面前一定要调用,页面中不用手动调用
print("onExit enter")
if self.handle then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
self.handle = nil
end
if self.listener1 then
cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
self.listener1 = 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]:release()
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
----------------------------------------------------------------------------
------------------------------以上函数外部可调用-----------------------------
----------------------------------------------------------------------------
function scroll:get_the_item_touched(x, y) --注意前提:缩放均为 100% ,scv的父源点和世界源点重合
local scv_x = self.scv:getPositionX()
local scv_y = self.scv:getPositionY()
local inner_x = self.inner:getPositionX()
local inner_y = self.inner:getPositionY()
local head_x = self['node' .. self.iHead]:getPositionX()
local head_y = self['node' .. self.iHead]:getPositionY()
x = x - scv_x
y = y - scv_y
x = x - inner_x
y = y - inner_y
x = x - head_x
y = y - head_y
x = x * -1
y = y * -1
x = x - (MARGIN_LEFT - MARGIN_H_BETWEEN / 2)
y = y + MARGIN_V_BETWEEN / 2
local num_x = math.ceil(x / (self.item_width + MARGIN_H_BETWEEN))
local num_y = math.ceil(y / (self.item_height + MARGIN_V_BETWEEN))
if num_x < 1 or num_x > NUM_PER_ROW then
return false
end
if num_y < 1 or self.iHead + num_y - 1 > self.max_row then
return false
end
local item_i = (self.iHead + num_y - 1 - 1) * NUM_PER_ROW + num_x
if item_i > #self.data then
return false
end
return item_i
end
function scroll:show_a_row( i) -- i'th row
print("show_a_row enter " .. i)
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])
end
self['item' .. index]:setVisible(false)
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
function scroll:set_an_item( item, i)
_G[self.modName].getInstance():set_an_item(item, i)
end
function scroll:reuse_pre_rows() -- 包括复用已有的行资源和删除多余资源和创建新资源
local j = self.pre_iHead -- the previous index of head row
while self['node' .. j] do -- 必须重命名,不然会错,比如从第1行(1,2,3)跳转至第2行(2,3,4),这样1,2,3 和 2,3,4有交错
for k = 1, NUM_PER_ROW do
local index = (j - 1) * NUM_PER_ROW + k
self['item_pre' .. index] = self['item' .. index]
self['item' .. index] = nil
end
self['node_pre' .. j] = self['node' .. j]
self['node' .. j] = nil
j = j + 1
end
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)
local i = self.iHead -- the current index of head row
local father
while i <= self.iTail do
if j == self.pre_iHead then
if not self['node_pre' .. j] then
self['node_pre' .. j] = cc.Node:create()
self['node_pre' .. j]:retain() --如果不retain,后面调用removeFromParent会报错
self.inner:addChild(self['node_pre' .. j])
end
self['node_pre' .. j]:setPosition(0, NODE_IHEAD_POS)
else
if not self['node_pre' .. j] then
self['node_pre' .. j] = cc.Node:create()
self['node_pre' .. j]:retain()
self['node_pre' .. j]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
--self['node_pre' .. j - 1]:addChild(self['node_pre' .. j]) -- 错! self['node_pre' .. j - 1]已经在上一步置为nil
father:addChild(self['node_pre' .. j])
end
end
self['node' .. i] = self['node_pre' .. j]
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_pre' .. index1]
self['item_pre' .. index1] = nil
end
father = self['node_pre' .. j]
self['node_pre' .. j] = nil
self:show_a_row(i)
i = i + 1
j = j + 1 --这里 j不用担心上界,如果item是nil则会在show_a_row里创建
end
father = nil
if self['node_pre' .. j] then --因为node(i)的父节点是node(i - 1),所以remove一个就行
self['node_pre' .. j]:removeFromParent()
end
while self['node_pre' .. j] do --虽然上面已经释放,但是self内相关引用值不为nil,需赋为nil
self['node_pre' .. j]:release()
self['node_pre' .. j] = nil
for k = 1, NUM_PER_ROW do
local index = (j - 1) * NUM_PER_ROW + k
self['item_pre' .. index] =nil
end
j = j + 1
end
end
function scroll:head_tail_head_tail()
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
function scroll:tail_tail_head_head()
self.count = 0
if self.count < 2 then
self:one_more_row_to_tail()
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_head()
end
end
function scroll:one_more_row_to_head()
if self.iHead == 1 then
return
end
self.count = self.count + 1
local height = self.inner:getContentSize().height
height = height + (self.item_height + MARGIN_V_BETWEEN)
self.inner:setContentSize(cc.size(self.scv_width, height)) --这和setInnerContainerSize( 延伸方向不同
NODE_IHEAD_POS = height - MARGIN_UP
self['node' .. self.iHead - 1] = cc.Node:create()
self['node' .. self.iHead - 1]:retain()
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
function scroll:one_more_row_to_tail()
if self.iTail == self.max_row then
return
end
self.count = self.count + 1
local height = self.inner:getContentSize().height
height = height + (self.item_height + MARGIN_V_BETWEEN)
self.scv:setInnerContainerSize(cc.size(self.scv_width, height))
NODE_IHEAD_POS = height - MARGIN_UP
self['node' .. self.iHead]:setPosition(0, NODE_IHEAD_POS)
self['node' .. self.iTail + 1] = cc.Node:create()
self['node' .. self.iTail + 1]:retain()
self['node' .. self.iTail + 1]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
self['node' .. self.iTail]:addChild(self['node' .. self.iTail + 1])
self:show_a_row(self.iTail + 1)
self.iTail = self.iTail + 1
end
--当删除或添加items后应该调整之前的头尾位置
function scroll:set_new_iHead_iTail()
self.visible_rows = math.ceil(self.scv_height / (self.item_height + MARGIN_V_BETWEEN)) --可视域行数
self.max_row = math.ceil(#self.data / NUM_PER_ROW)
self.iTail = self.iHead + self.visible_rows - 1
self.iTail = math.min(self.max_row, self.iTail)
self.iHead = self.iTail - self.visible_rows + 1
self.iHead = math.max(1, self.iHead)
end
function scroll:monitor()
local innerY = self.inner:getPositionY()
if self.delY > 0 and innerY + NODE_IHEAD_POS > THRESHOLD then --把头行移至尾后
if self.iTail == self.max_row 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
if _G[self.modName].getInstance().item_change_i_to_j then
_G[self.modName].getInstance():item_change_i_to_j(self['item'..self.iTail + 1], self.iHead, self.iTail + 1) --从第几个变成第几个
end
self.iHead = self.iHead + 1
self.iTail = self.iTail + 1
self:show_a_row(self.iTail)
end
if self.delY < 0 and innerY + NODE_IHEAD_POS < THRESHOLD - self.item_height then --这里的第二个判断不能为上面第二个判断的补集,否则滑动会出现空白
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
if _G[self.modName].getInstance().item_change_i_to_j then
_G[self.modName].getInstance():item_change_i_to_j(self['item'..self.iHead - 1], self.iTail, self.iHead - 1) --从第几个变成第几个
end
self.iHead = self.iHead - 1
self.iTail = self.iTail - 1
self:show_a_row(self.iHead)
end
end
_G['scroll'] = scroll
local MARGIN_UP = 0
local MARGIN_LEFT = 0
local MARGIN_V_BETWEEN = 0
local MARGIN_H_BETWEEN
local NUM_PER_ROW
local THRESHOLD -- 与self['node' .. iHead]相对Container的高度差阈值
local NODE_IHEAD_POS --inner的子节点位置高度 ,每次inner height 有变化都要更新
--[[
marginV: item间垂直间距,默认为 0
marginUp: 上下空白长度, 默认为 0
marginLeft: 左右空白长度,默认为 0
]]
function scroll:set_margin(marginV, marginUp, marginLeft) --如果不调set_margin将使用上次的margin,整个游戏第一次调用前为上面的值
print("set_margin enter")
MARGIN_V_BETWEEN = marginV or 0
MARGIN_UP = marginUp or 0
MARGIN_LEFT = marginLeft or 0
end
--[[
modName: 模块名
refScv: scroll view
refItem: item,要能克隆 item:clone() ,和获得item大小 item:getContentSize()
refData: 数据table, 用 #refData可获取长度
numPerRow: 每行item个数 ,默认为 1
startRow: 希望从第几行开始显示, 默认为 1 ,程序会根据情况调整至合理位置
]]
function scroll:create( modName, refScv, refItem, refData, numPerRow, startRow)--一个页面中打开一个标签使用一次,上次的scv作废,但下面有方法还原状态
print("create enter ")
if self.iHead then
self:onExit() --主要为释放上一次的资源
end
self.modName = modName
self.scv = refScv
self.inner= self.scv:getInnerContainer()
self.item = refItem
self.item:ignoreAnchorPointForPosition(false)
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.scv:setInnerContainerSize(cc.size(self.scv_width, self.scv_height)) --这个很重要,否则inner会有偏移(受上次位置影响)
NUM_PER_ROW = numPerRow or 1
MARGIN_H_BETWEEN = 0
if NUM_PER_ROW ~= 1 then
MARGIN_H_BETWEEN = (self.scv_width - 2 * MARGIN_LEFT - NUM_PER_ROW * self.item_width) / (NUM_PER_ROW - 1)
MARGIN_H_BETWEEN = math.max(0, MARGIN_H_BETWEEN)
end
THRESHOLD = self.scv_height + (self.item_height + MARGIN_V_BETWEEN) / 2 + self.item_height
self.iHead = startRow or 1
self:set_new_iHead_iTail() --首尾行需修正(首行为self.iHead,尾行为self.iTail)
self.pre_iHead = self.iHead
self:reuse_pre_rows() --这个函数有复用,删除,新增综合功能
self:head_tail_head_tail()
self.delY = 0 -- monitor()内会率先用到
local function monitor()
self:monitor()
end
self.handle = cc.Director:getInstance():getScheduler():scheduleScriptFunc(monitor, 0, false)
local function onTouchBegan(touch, event)
self.delY = 0
return true
end
local function onTouchMoved(touch, event)
self.delY = touch:getLocation().y - touch:getPreviousLocation().y
end
local function onTouchEnded(touch, event)
-- if self.delY == 0 then
-- if self.item_touch_enabled and self.iTail ~= 0 then --不为空
-- local touchX = touch:getLocation().x
-- local touchY = touch:getLocation().y
-- local item_i = self:get_the_item_touched(touchX,touchY)
-- if item_i then
-- _G[modName].getInstance():touch_an_item(self['item' .. item_i], item_i) -- item, i
-- end
-- end
-- end
end
self.listener1 = cc.EventListenerTouchOneByOne:create()
self.listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
self.listener1:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED )
self.listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
end
function scroll:jump_to( i) -- jump to i'th row
self.pre_iHead = self.iHead
self.iHead = i
self:reuse_pre_rows()
self:head_tail_head_tail()
if self.max_row - i + 1 < self.visible_rows then -- 为了能完全显示最后一个item
self.inner:setPosition(0, 0)
end
end
function scroll:refresh() --外部刷新
print("refresh enter")
self.pre_iHead = self.iHead
self.pre_iTail = self.iTail
self.pre_max_row = self.max_row
self.pre_innerY = self.inner:getPositionY()
self:reuse_pre_rows()
self:tail_tail_head_head()
if self.pre_max_row >= self.max_row then --行数减少或不变
if self.iTail == self.pre_iTail then
self.inner:setPosition(0, self.pre_innerY)
else
self.inner:setPosition(0, 0)
end
else --行数增多
if self.iTail == self.pre_iTail then
self.inner:setPosition(0, self.pre_innerY)
else
local pre_height = 2 * MARGIN_UP + (self.pre_iTail - self.pre_iHead + 1) * (self.item_height + MARGIN_V_BETWEEN) - MARGIN_V_BETWEEN
pre_height = math.max(self.scv_height, pre_height)
local pre_y = self.scv_height - pre_height
local del_y = self.pre_innerY - pre_y
local height = 2 * MARGIN_UP + (self.iTail - self.iHead + 1) * (self.item_height + MARGIN_V_BETWEEN) - MARGIN_V_BETWEEN
height = math.max(self.scv_height, height)
local y = self.scv_height - height
self.inner:setPosition(0, y + del_y)
end
end
end
--function scroll:register_item_touch()
-- self.item_touch_enabled = true
--end
--
--function scroll:unregister_item_touch()
-- self.item_touch_enabled = false
--end
function scroll:get_current_state() --离开标签时获取信息 “info”
local innerY = self.inner:getPositionY() --有两种情况要调整位置
if self.iHead == 1 then
if innerY < self.scv_height - (NODE_IHEAD_POS + MARGIN_UP) then
innerY = self.scv_height - (NODE_IHEAD_POS + MARGIN_UP)
end
end
if self.iTail == #self.data then
if innerY > 0 then
innerY = 0
end
end
return {self.iHead, self.iTail, innerY}
end
function scroll:set_current_state(state) --再次回到标签,先调用set_margin, create,再用参数“info”调
self.pre_iHead = self.iHead -- 考虑到之前的标签会有items个数变化
self.iHead = state[1]
self:reuse_pre_rows()
self:tail_tail_head_head()
if self.iTail - self.iHead == state[2] - state[1] and self.iHead == state[1] then
self.inner:setPosition(0, state[3])
else
self.inner:setPosition(0, 0)
end
end
function scroll:onExit() --前端关闭页面前一定要调用,页面中不用手动调用
print("onExit enter")
if self.handle then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
self.handle = nil
end
if self.listener1 then
cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
self.listener1 = 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]:release()
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
----------------------------------------------------------------------------
------------------------------以上函数外部可调用-----------------------------
----------------------------------------------------------------------------
function scroll:get_the_item_touched(x, y) --注意前提:缩放均为 100% ,scv的父源点和世界源点重合
local scv_x = self.scv:getPositionX()
local scv_y = self.scv:getPositionY()
local inner_x = self.inner:getPositionX()
local inner_y = self.inner:getPositionY()
local head_x = self['node' .. self.iHead]:getPositionX()
local head_y = self['node' .. self.iHead]:getPositionY()
x = x - scv_x
y = y - scv_y
x = x - inner_x
y = y - inner_y
x = x - head_x
y = y - head_y
x = x * -1
y = y * -1
x = x - (MARGIN_LEFT - MARGIN_H_BETWEEN / 2)
y = y + MARGIN_V_BETWEEN / 2
local num_x = math.ceil(x / (self.item_width + MARGIN_H_BETWEEN))
local num_y = math.ceil(y / (self.item_height + MARGIN_V_BETWEEN))
if num_x < 1 or num_x > NUM_PER_ROW then
return false
end
if num_y < 1 or self.iHead + num_y - 1 > self.max_row then
return false
end
local item_i = (self.iHead + num_y - 1 - 1) * NUM_PER_ROW + num_x
if item_i > #self.data then
return false
end
return item_i
end
function scroll:show_a_row( i) -- i'th row
print("show_a_row enter " .. i)
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])
end
self['item' .. index]:setVisible(false)
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
function scroll:set_an_item( item, i)
_G[self.modName].getInstance():set_an_item(item, i)
end
function scroll:reuse_pre_rows() -- 包括复用已有的行资源和删除多余资源和创建新资源
local j = self.pre_iHead -- the previous index of head row
while self['node' .. j] do -- 必须重命名,不然会错,比如从第1行(1,2,3)跳转至第2行(2,3,4),这样1,2,3 和 2,3,4有交错
for k = 1, NUM_PER_ROW do
local index = (j - 1) * NUM_PER_ROW + k
self['item_pre' .. index] = self['item' .. index]
self['item' .. index] = nil
end
self['node_pre' .. j] = self['node' .. j]
self['node' .. j] = nil
j = j + 1
end
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)
local i = self.iHead -- the current index of head row
local father
while i <= self.iTail do
if j == self.pre_iHead then
if not self['node_pre' .. j] then
self['node_pre' .. j] = cc.Node:create()
self['node_pre' .. j]:retain() --如果不retain,后面调用removeFromParent会报错
self.inner:addChild(self['node_pre' .. j])
end
self['node_pre' .. j]:setPosition(0, NODE_IHEAD_POS)
else
if not self['node_pre' .. j] then
self['node_pre' .. j] = cc.Node:create()
self['node_pre' .. j]:retain()
self['node_pre' .. j]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
--self['node_pre' .. j - 1]:addChild(self['node_pre' .. j]) -- 错! self['node_pre' .. j - 1]已经在上一步置为nil
father:addChild(self['node_pre' .. j])
end
end
self['node' .. i] = self['node_pre' .. j]
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_pre' .. index1]
self['item_pre' .. index1] = nil
end
father = self['node_pre' .. j]
self['node_pre' .. j] = nil
self:show_a_row(i)
i = i + 1
j = j + 1 --这里 j不用担心上界,如果item是nil则会在show_a_row里创建
end
father = nil
if self['node_pre' .. j] then --因为node(i)的父节点是node(i - 1),所以remove一个就行
self['node_pre' .. j]:removeFromParent()
end
while self['node_pre' .. j] do --虽然上面已经释放,但是self内相关引用值不为nil,需赋为nil
self['node_pre' .. j]:release()
self['node_pre' .. j] = nil
for k = 1, NUM_PER_ROW do
local index = (j - 1) * NUM_PER_ROW + k
self['item_pre' .. index] =nil
end
j = j + 1
end
end
function scroll:head_tail_head_tail()
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
function scroll:tail_tail_head_head()
self.count = 0
if self.count < 2 then
self:one_more_row_to_tail()
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_head()
end
end
function scroll:one_more_row_to_head()
if self.iHead == 1 then
return
end
self.count = self.count + 1
local height = self.inner:getContentSize().height
height = height + (self.item_height + MARGIN_V_BETWEEN)
self.inner:setContentSize(cc.size(self.scv_width, height)) --这和setInnerContainerSize( 延伸方向不同
NODE_IHEAD_POS = height - MARGIN_UP
self['node' .. self.iHead - 1] = cc.Node:create()
self['node' .. self.iHead - 1]:retain()
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
function scroll:one_more_row_to_tail()
if self.iTail == self.max_row then
return
end
self.count = self.count + 1
local height = self.inner:getContentSize().height
height = height + (self.item_height + MARGIN_V_BETWEEN)
self.scv:setInnerContainerSize(cc.size(self.scv_width, height))
NODE_IHEAD_POS = height - MARGIN_UP
self['node' .. self.iHead]:setPosition(0, NODE_IHEAD_POS)
self['node' .. self.iTail + 1] = cc.Node:create()
self['node' .. self.iTail + 1]:retain()
self['node' .. self.iTail + 1]:setPosition(0, -(self.item_height + MARGIN_V_BETWEEN))
self['node' .. self.iTail]:addChild(self['node' .. self.iTail + 1])
self:show_a_row(self.iTail + 1)
self.iTail = self.iTail + 1
end
--当删除或添加items后应该调整之前的头尾位置
function scroll:set_new_iHead_iTail()
self.visible_rows = math.ceil(self.scv_height / (self.item_height + MARGIN_V_BETWEEN)) --可视域行数
self.max_row = math.ceil(#self.data / NUM_PER_ROW)
self.iTail = self.iHead + self.visible_rows - 1
self.iTail = math.min(self.max_row, self.iTail)
self.iHead = self.iTail - self.visible_rows + 1
self.iHead = math.max(1, self.iHead)
end
function scroll:monitor()
local innerY = self.inner:getPositionY()
if self.delY > 0 and innerY + NODE_IHEAD_POS > THRESHOLD then --把头行移至尾后
if self.iTail == self.max_row 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
if _G[self.modName].getInstance().item_change_i_to_j then
_G[self.modName].getInstance():item_change_i_to_j(self['item'..self.iTail + 1], self.iHead, self.iTail + 1) --从第几个变成第几个
end
self.iHead = self.iHead + 1
self.iTail = self.iTail + 1
self:show_a_row(self.iTail)
end
if self.delY < 0 and innerY + NODE_IHEAD_POS < THRESHOLD - self.item_height then --这里的第二个判断不能为上面第二个判断的补集,否则滑动会出现空白
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
if _G[self.modName].getInstance().item_change_i_to_j then
_G[self.modName].getInstance():item_change_i_to_j(self['item'..self.iHead - 1], self.iTail, self.iHead - 1) --从第几个变成第几个
end
self.iHead = self.iHead - 1
self.iTail = self.iTail - 1
self:show_a_row(self.iHead)
end
end
_G['scroll'] = scroll