local scroll2 = {} --横向滑动,只考虑一行的情况,如果一列有2个item,那么事先把这2个合为一个,在模块中的set_an_item稍微复杂一点
local MARGIN_BETWEEN
local MARGIN_LEFT
local ITEM_Y
local THRESHOLD -- 与innerX做比较
function scroll2:set_margin(marginB, marginL) --如果要设置则在create之前调用
ccprint("set_margin 2 enter")
MARGIN_BETWEEN = marginB or 0
MARGIN_LEFT = marginL or 0
end
--[[
modName: 模块名
reuseLastRes : 是否重用上次的资源,比如同一个页面中不同标签的item都是一样,则可以复用上次的
refScv: 横向 scroll view
refItem: item
refData: 数据table, 用 #refData可获取长度
startItem: 希望从第几个item开始显示, 默认为 1 ,程序会根据情况调整至合理位置
]]
function scroll2:create( modName, reuseLastRes, refScv, refItem, refData, startItem)--一个页面中打开一个标签使用一次,上次的scv作废,但下面有方法还原状态
ccprint("create 2 enter ")
if not reuseLastRes then
self:onExit() --主要为释放上一次的资源
self.item = refItem
self.item:ignoreAnchorPointForPosition(false)
self.item:setAnchorPoint(0, 0)
self.item:retain()
else -- 以防出错,先把handle和listener关掉
ccprint("Re use 2 ...")
if self.handle then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
self.handle = nil
end
if self.listener1 then
-- self.modSelf._core:getEventDispatcher():removeEventListener(self.listener1)
cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
self.listener1 = nil
end
if self.item_touch_enabled then --重用了但点击事件注销,目前这么写吧
self.item_touch_enabled = false
end
end
self.modName = modName
self.modSelf = _G[modName].getInstance()
self.scv = refScv
self.inner= self.scv:getInnerContainer()
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)) --见垂直滑动 scv.lua的注释
self.inner:setPosition(0, 0) --垂直滑动不用这句,由上句就能自动还原至原点
THRESHOLD = -(MARGIN_LEFT + self.item_width / 2 + MARGIN_BETWEEN + self.item_width)
ITEM_Y = (self.scv_height - self.item_height) / 2
ITEM_Y = math.max(0, ITEM_Y)
self.pre_iHead = self.iHead --当reuseLastRes 为 true的情形这句才有效
self.iHead = startItem or 1
--self:set_new_iHead_iTail() -- self:reuse_pre_rows() 内有矫正
self.pre_iHead = self.pre_iHead or self.iHead
self:reuse_pre_items() --这个函数有复用,删除,新增综合功能
self:head_tail_head_tail()
self.delX = 0 -- monitor()内会率先用到
local function monitor()
self:monitor()
end
self.handle = cc.Director:getInstance():getScheduler():scheduleScriptFunc(monitor, 0, false)
local function onTouchBegan(touch, event)
self.delX = 0
return true
end
local function onTouchMoved(touch, event)
self.delX = touch:getLocation().x - touch:getPreviousLocation().x
end
local function onTouchEnded(touch, event)
if self.delX == 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, modX, modY = self:get_the_item_touched(touchX,touchY)
ccprint("item_i " .. touchX .. ' ' .. touchY .. ' ' .. tostring(item_i))
if item_i then
self.modSelf:touch_an_item(self['item' .. item_i], item_i, modX, modY) -- 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 )
-- self.modSelf._core:getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
-- self.modSelf._core:getEventDispatcher():addEventListenerWithSceneGraphPriority(self.listener1, self.modSelf._core) --这种注册有点问题
end
function scroll2:jump_to( i) -- jump to i'th item
self.pre_iHead = self.iHead
self.iHead = i
self:reuse_pre_items()
self:head_tail_head_tail()
if #self.data - i + 1 < self.visible_items then -- 为了能完全显示最后一个item
self.inner:setPosition(self.scv_width - (2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN), 0)
end
end
function scroll2:refresh() --外部刷新
ccprint("refresh 2 enter")
self.pre_iHead = self.iHead
self.pre_iTail = self.iTail
self.pre_data_len = #self.data
self.pre_innerX = self.inner:getPositionX()
self:reuse_pre_items()
self:tail_tail_head_head()
if self.pre_data_len >= #self.data then --item数减少或不变
if self.iTail == self.pre_iTail then
self.inner:setPosition(self.pre_innerX, 0)
else
local x = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN
x = math.max(self.scv_width, x)
self.inner:setPosition(self.scv_width - x, 0)
end
else --item数增多
self.inner:setPosition(self.pre_innerX, 0)
end
end
function scroll2:get_current_state() --离开标签时获取信息 “info”
local innerX = self.inner:getPositionX() --有两种情况要调整位置
if self.iHead == 1 then
if innerX > 0 then
innerX = 0
end
end
if self.iTail == #self.data then
local x = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN
x = math.max(self.scv_width, x)
if innerX < self.scv_width - x then
innerX = self.scv_width - x
end
end
return {self.iHead, self.iTail, innerX}
end
function scroll2:set_current_state(state) --再次回到标签,先调用set_MARGIN_BETWEEN, create,再用参数“info”调
ccprint("set_current_state 2 enter")
self.pre_iHead = self.iHead -- 考虑到之前的标签会有items个数变化
self.iHead = state[1]
self:reuse_pre_items()
self:tail_tail_head_head()
if self.iTail - self.iHead == state[2] - state[1] and self.iHead == state[1] then
self.inner:setPosition(state[3], 0)
else
local x = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN
x = math.max(self.scv_width, x)
self.inner:setPosition(self.scv_width - x, 0)
end
end
function scroll2:register_item_touch()
self.item_touch_enabled = true
end
function scroll2:unregister_item_touch()
self.item_touch_enabled = false
end
function scroll2:onExit()
ccprint("onExit 2 enter")
if self.handle then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
self.handle = nil
end
if self.listener1 then
-- self.modSelf._core:getEventDispatcher():removeEventListener(self.listener1)
cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
self.listener1 = nil
end
if self.item then
self.item:release()
self.item = nil
end
if self.item_touch_enabled then
self.item_touch_enabled = false
end
if self.iHead then
for i = self.iHead, self.iTail do
self['item' .. i]:removeFromParent()
self['item' .. i] = nil
end
self.iHead = nil
end
end
----------------------------------------------------------------------------
------------------------------以上函数外部可调用-----------------------------
----------------------------------------------------------------------------
function scroll2: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['item' .. self.iHead]:getPositionX()
local head_y = self['item' .. 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 -- notice
--y = y * -1
x = x + MARGIN_BETWEEN / 2
local num_x = math.ceil(x / (self.item_width + MARGIN_BETWEEN))
if num_x < 1 or self.iHead + num_x - 1 > #self.data then
return false
end
if y < 0 or y > self.item_height then
return false
end
local item_i = self.iHead + num_x - 1
local modX = x % (self.item_width + MARGIN_BETWEEN)
local modY = y % self.item_height
return item_i, modX, modY
end
function scroll2:set_an_item( item, i)
self.modSelf:set_an_item(item, i)
end
function scroll2:reuse_pre_items() -- 包括复用已有的item资源和删除多余资源和创建新资源
local j = self.pre_iHead -- the previous index of head row
while self['item' .. j] do -- 必须重命名,不然会错,比如从第1item(1,2,3)跳转至第2item(2,3,4),这样1,2,3 和 2,3,4有交错
self['item_pre' .. j] = self['item' .. j]
self['item' .. j] = nil
j = j + 1
end
self:set_new_iHead_iTail()
local width = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN --现在所需的inner宽度
width = math.max(self.scv_width, width)
self.inner:setContentSize(cc.size(width, self.scv_height))
self.inner:setPosition(0, 0) -- 水平滑动要加上这句
local i = self.iHead -- the current index of head item
j = self.pre_iHead -- the previous index of head item
local posX = MARGIN_LEFT
while i <= self.iTail do
if not self['item_pre' .. j] then
self['item_pre' .. j] = self.item:clone()
self.inner:addChild(self['item_pre' .. j])
end
self['item_pre' .. j]:setPosition(posX, ITEM_Y)
self['item' .. i] = self['item_pre' .. j]
self['item_pre' .. j] = nil
self:set_an_item(self['item' .. i], i)
posX = posX + self.item_width + MARGIN_BETWEEN
i = i + 1
j = j + 1
end
while self['item_pre' .. j] do --把多余的释放并设为nil
self['item_pre' .. j]:removeFromParent()
self['item_pre' .. j] = nil
j = j + 1
end
end
function scroll2:head_tail_head_tail()
self.count = 0
if self.count < 2 then
self:one_more_item_to_head()
end
if self.count < 2 then
self:one_more_item_to_tail()
end
if self.count < 2 then
self:one_more_item_to_head()
end
if self.count < 2 then
self:one_more_item_to_tail()
end
end
function scroll2:tail_tail_head_head()
self.count = 0
if self.count < 2 then
self:one_more_item_to_tail()
end
if self.count < 2 then
self:one_more_item_to_tail()
end
if self.count < 2 then
self:one_more_item_to_head()
end
if self.count < 2 then
self:one_more_item_to_head()
end
end
function scroll2:one_more_item_to_head()
if self.iHead == 1 then
return
end
self.count = self.count + 1
local width = self.inner:getContentSize().width
width = width + (self.item_width + MARGIN_BETWEEN)
self.inner:setContentSize(cc.size(width, self.scv_height)) --横向scv中和setInnerContainerSize延伸方向相同
self['item' .. self.iHead - 1] = self.item:clone()
self['item' .. self.iHead - 1]:setPosition(MARGIN_LEFT, ITEM_Y)
self.inner:addChild(self['item' .. self.iHead - 1])
local posX = MARGIN_LEFT
for i = self.iHead, self.iTail do
posX = posX + self.item_width + MARGIN_BETWEEN
self['item' .. i]:setPosition(posX, ITEM_Y)
end
local innerX = self.inner:getPositionX() --self.inner:getPositionX()不一定是0,比如两次往头部加
innerX = innerX - (self.item_width + MARGIN_BETWEEN)
self.inner:setPosition(innerX, 0)
self.iHead = self.iHead - 1
self:set_an_item(self['item' .. self.iHead], self.iHead)
end
function scroll2:one_more_item_to_tail()
if self.iTail == #self.data then
return
end
self.count = self.count + 1
local width = self.inner:getContentSize().width
width = width + (self.item_width + MARGIN_BETWEEN)
self.inner:setContentSize(cc.size(width, self.scv_height))
self['item' .. self.iTail + 1] = self.item:clone()
local x = MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) --这里容易写错 ,写成 self.iTail - self.iHead + 1 - 1
self['item' .. self.iTail + 1]:setPosition(x, ITEM_Y)
self.inner:addChild(self['item' .. self.iTail + 1])
self.iTail = self.iTail + 1
self:set_an_item(self['item' .. self.iTail], self.iTail)
end
--当删除或添加items后应该调整之前的头尾位置
function scroll2:set_new_iHead_iTail()
self.visible_items = math.ceil(self.scv_width / (self.item_width + MARGIN_BETWEEN)) --可视域item数
self.iTail = self.iHead + self.visible_items - 1
self.iTail = math.min(#self.data, self.iTail)
self.iHead = self.iTail - self.visible_items + 1
self.iHead = math.max(1, self.iHead)
end
function scroll2:monitor()
local innerX = self.inner:getPositionX()
if self.delX < 0 and innerX < THRESHOLD then --把头item移至尾后
if self.iTail == #self.data then
return
end
local posX = MARGIN_LEFT
for i = self.iHead + 1, self.iTail do
self['item' .. i]:setPosition(posX, ITEM_Y)
posX = posX + (self.item_width + MARGIN_BETWEEN)
end
self.inner:setPosition(innerX + (self.item_width + MARGIN_BETWEEN), 0)
self['item' .. self.iHead]:setPosition(MARGIN_LEFT + (self.iTail - self.iHead + 1 - 1) * (self.item_width + MARGIN_BETWEEN), ITEM_Y)
self['item' .. self.iTail + 1] = self['item' .. self.iHead]
self['item' .. self.iHead] = nil
self.iHead = self.iHead + 1
self.iTail = self.iTail + 1
self:set_an_item(self['item' .. self.iTail], self.iTail)
if self.modSelf.item_change_i_to_j then
self.modSelf:item_change_i_to_j(self['item'.. self.iTail], self.iHead - 1, self.iTail) --从第i个变成第j个
end
end
if self.delX > 0 and innerX > THRESHOLD + self.item_width + MARGIN_BETWEEN then --这里的第二个判断不能为上面第二个判断的补集,否则滑动会出现空白
if self.iHead == 1 then
return
end
local posX = MARGIN_LEFT
for i = self.iHead, self.iTail - 1 do
posX = posX + (self.item_width + MARGIN_BETWEEN)
self['item' .. i]:setPosition(posX, ITEM_Y)
end
self.inner:setPosition(innerX - (self.item_width + MARGIN_BETWEEN), 0)
self['item' .. self.iTail]:setPosition(MARGIN_LEFT, ITEM_Y)
self['item' .. self.iHead - 1] = self['item' .. self.iTail]
self['item' .. self.iTail] = nil
self.iHead = self.iHead - 1
self.iTail = self.iTail - 1
self:set_an_item(self['item' .. self.iHead], self.iHead)
if self.modSelf.item_change_i_to_j then
self.modSelf:item_change_i_to_j(self['item'.. self.iHead], self.iTail + 1, self.iHead) --从第i个变成第j个
end
end
end
_G['scroll2'] = scroll2
local MARGIN_BETWEEN
local MARGIN_LEFT
local ITEM_Y
local THRESHOLD -- 与innerX做比较
function scroll2:set_margin(marginB, marginL) --如果要设置则在create之前调用
ccprint("set_margin 2 enter")
MARGIN_BETWEEN = marginB or 0
MARGIN_LEFT = marginL or 0
end
--[[
modName: 模块名
reuseLastRes : 是否重用上次的资源,比如同一个页面中不同标签的item都是一样,则可以复用上次的
refScv: 横向 scroll view
refItem: item
refData: 数据table, 用 #refData可获取长度
startItem: 希望从第几个item开始显示, 默认为 1 ,程序会根据情况调整至合理位置
]]
function scroll2:create( modName, reuseLastRes, refScv, refItem, refData, startItem)--一个页面中打开一个标签使用一次,上次的scv作废,但下面有方法还原状态
ccprint("create 2 enter ")
if not reuseLastRes then
self:onExit() --主要为释放上一次的资源
self.item = refItem
self.item:ignoreAnchorPointForPosition(false)
self.item:setAnchorPoint(0, 0)
self.item:retain()
else -- 以防出错,先把handle和listener关掉
ccprint("Re use 2 ...")
if self.handle then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
self.handle = nil
end
if self.listener1 then
-- self.modSelf._core:getEventDispatcher():removeEventListener(self.listener1)
cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
self.listener1 = nil
end
if self.item_touch_enabled then --重用了但点击事件注销,目前这么写吧
self.item_touch_enabled = false
end
end
self.modName = modName
self.modSelf = _G[modName].getInstance()
self.scv = refScv
self.inner= self.scv:getInnerContainer()
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)) --见垂直滑动 scv.lua的注释
self.inner:setPosition(0, 0) --垂直滑动不用这句,由上句就能自动还原至原点
THRESHOLD = -(MARGIN_LEFT + self.item_width / 2 + MARGIN_BETWEEN + self.item_width)
ITEM_Y = (self.scv_height - self.item_height) / 2
ITEM_Y = math.max(0, ITEM_Y)
self.pre_iHead = self.iHead --当reuseLastRes 为 true的情形这句才有效
self.iHead = startItem or 1
--self:set_new_iHead_iTail() -- self:reuse_pre_rows() 内有矫正
self.pre_iHead = self.pre_iHead or self.iHead
self:reuse_pre_items() --这个函数有复用,删除,新增综合功能
self:head_tail_head_tail()
self.delX = 0 -- monitor()内会率先用到
local function monitor()
self:monitor()
end
self.handle = cc.Director:getInstance():getScheduler():scheduleScriptFunc(monitor, 0, false)
local function onTouchBegan(touch, event)
self.delX = 0
return true
end
local function onTouchMoved(touch, event)
self.delX = touch:getLocation().x - touch:getPreviousLocation().x
end
local function onTouchEnded(touch, event)
if self.delX == 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, modX, modY = self:get_the_item_touched(touchX,touchY)
ccprint("item_i " .. touchX .. ' ' .. touchY .. ' ' .. tostring(item_i))
if item_i then
self.modSelf:touch_an_item(self['item' .. item_i], item_i, modX, modY) -- 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 )
-- self.modSelf._core:getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(self.listener1, -1)
-- self.modSelf._core:getEventDispatcher():addEventListenerWithSceneGraphPriority(self.listener1, self.modSelf._core) --这种注册有点问题
end
function scroll2:jump_to( i) -- jump to i'th item
self.pre_iHead = self.iHead
self.iHead = i
self:reuse_pre_items()
self:head_tail_head_tail()
if #self.data - i + 1 < self.visible_items then -- 为了能完全显示最后一个item
self.inner:setPosition(self.scv_width - (2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN), 0)
end
end
function scroll2:refresh() --外部刷新
ccprint("refresh 2 enter")
self.pre_iHead = self.iHead
self.pre_iTail = self.iTail
self.pre_data_len = #self.data
self.pre_innerX = self.inner:getPositionX()
self:reuse_pre_items()
self:tail_tail_head_head()
if self.pre_data_len >= #self.data then --item数减少或不变
if self.iTail == self.pre_iTail then
self.inner:setPosition(self.pre_innerX, 0)
else
local x = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN
x = math.max(self.scv_width, x)
self.inner:setPosition(self.scv_width - x, 0)
end
else --item数增多
self.inner:setPosition(self.pre_innerX, 0)
end
end
function scroll2:get_current_state() --离开标签时获取信息 “info”
local innerX = self.inner:getPositionX() --有两种情况要调整位置
if self.iHead == 1 then
if innerX > 0 then
innerX = 0
end
end
if self.iTail == #self.data then
local x = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN
x = math.max(self.scv_width, x)
if innerX < self.scv_width - x then
innerX = self.scv_width - x
end
end
return {self.iHead, self.iTail, innerX}
end
function scroll2:set_current_state(state) --再次回到标签,先调用set_MARGIN_BETWEEN, create,再用参数“info”调
ccprint("set_current_state 2 enter")
self.pre_iHead = self.iHead -- 考虑到之前的标签会有items个数变化
self.iHead = state[1]
self:reuse_pre_items()
self:tail_tail_head_head()
if self.iTail - self.iHead == state[2] - state[1] and self.iHead == state[1] then
self.inner:setPosition(state[3], 0)
else
local x = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN
x = math.max(self.scv_width, x)
self.inner:setPosition(self.scv_width - x, 0)
end
end
function scroll2:register_item_touch()
self.item_touch_enabled = true
end
function scroll2:unregister_item_touch()
self.item_touch_enabled = false
end
function scroll2:onExit()
ccprint("onExit 2 enter")
if self.handle then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.handle)
self.handle = nil
end
if self.listener1 then
-- self.modSelf._core:getEventDispatcher():removeEventListener(self.listener1)
cc.Director:getInstance():getEventDispatcher():removeEventListener(self.listener1)
self.listener1 = nil
end
if self.item then
self.item:release()
self.item = nil
end
if self.item_touch_enabled then
self.item_touch_enabled = false
end
if self.iHead then
for i = self.iHead, self.iTail do
self['item' .. i]:removeFromParent()
self['item' .. i] = nil
end
self.iHead = nil
end
end
----------------------------------------------------------------------------
------------------------------以上函数外部可调用-----------------------------
----------------------------------------------------------------------------
function scroll2: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['item' .. self.iHead]:getPositionX()
local head_y = self['item' .. 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 -- notice
--y = y * -1
x = x + MARGIN_BETWEEN / 2
local num_x = math.ceil(x / (self.item_width + MARGIN_BETWEEN))
if num_x < 1 or self.iHead + num_x - 1 > #self.data then
return false
end
if y < 0 or y > self.item_height then
return false
end
local item_i = self.iHead + num_x - 1
local modX = x % (self.item_width + MARGIN_BETWEEN)
local modY = y % self.item_height
return item_i, modX, modY
end
function scroll2:set_an_item( item, i)
self.modSelf:set_an_item(item, i)
end
function scroll2:reuse_pre_items() -- 包括复用已有的item资源和删除多余资源和创建新资源
local j = self.pre_iHead -- the previous index of head row
while self['item' .. j] do -- 必须重命名,不然会错,比如从第1item(1,2,3)跳转至第2item(2,3,4),这样1,2,3 和 2,3,4有交错
self['item_pre' .. j] = self['item' .. j]
self['item' .. j] = nil
j = j + 1
end
self:set_new_iHead_iTail()
local width = 2 * MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) - MARGIN_BETWEEN --现在所需的inner宽度
width = math.max(self.scv_width, width)
self.inner:setContentSize(cc.size(width, self.scv_height))
self.inner:setPosition(0, 0) -- 水平滑动要加上这句
local i = self.iHead -- the current index of head item
j = self.pre_iHead -- the previous index of head item
local posX = MARGIN_LEFT
while i <= self.iTail do
if not self['item_pre' .. j] then
self['item_pre' .. j] = self.item:clone()
self.inner:addChild(self['item_pre' .. j])
end
self['item_pre' .. j]:setPosition(posX, ITEM_Y)
self['item' .. i] = self['item_pre' .. j]
self['item_pre' .. j] = nil
self:set_an_item(self['item' .. i], i)
posX = posX + self.item_width + MARGIN_BETWEEN
i = i + 1
j = j + 1
end
while self['item_pre' .. j] do --把多余的释放并设为nil
self['item_pre' .. j]:removeFromParent()
self['item_pre' .. j] = nil
j = j + 1
end
end
function scroll2:head_tail_head_tail()
self.count = 0
if self.count < 2 then
self:one_more_item_to_head()
end
if self.count < 2 then
self:one_more_item_to_tail()
end
if self.count < 2 then
self:one_more_item_to_head()
end
if self.count < 2 then
self:one_more_item_to_tail()
end
end
function scroll2:tail_tail_head_head()
self.count = 0
if self.count < 2 then
self:one_more_item_to_tail()
end
if self.count < 2 then
self:one_more_item_to_tail()
end
if self.count < 2 then
self:one_more_item_to_head()
end
if self.count < 2 then
self:one_more_item_to_head()
end
end
function scroll2:one_more_item_to_head()
if self.iHead == 1 then
return
end
self.count = self.count + 1
local width = self.inner:getContentSize().width
width = width + (self.item_width + MARGIN_BETWEEN)
self.inner:setContentSize(cc.size(width, self.scv_height)) --横向scv中和setInnerContainerSize延伸方向相同
self['item' .. self.iHead - 1] = self.item:clone()
self['item' .. self.iHead - 1]:setPosition(MARGIN_LEFT, ITEM_Y)
self.inner:addChild(self['item' .. self.iHead - 1])
local posX = MARGIN_LEFT
for i = self.iHead, self.iTail do
posX = posX + self.item_width + MARGIN_BETWEEN
self['item' .. i]:setPosition(posX, ITEM_Y)
end
local innerX = self.inner:getPositionX() --self.inner:getPositionX()不一定是0,比如两次往头部加
innerX = innerX - (self.item_width + MARGIN_BETWEEN)
self.inner:setPosition(innerX, 0)
self.iHead = self.iHead - 1
self:set_an_item(self['item' .. self.iHead], self.iHead)
end
function scroll2:one_more_item_to_tail()
if self.iTail == #self.data then
return
end
self.count = self.count + 1
local width = self.inner:getContentSize().width
width = width + (self.item_width + MARGIN_BETWEEN)
self.inner:setContentSize(cc.size(width, self.scv_height))
self['item' .. self.iTail + 1] = self.item:clone()
local x = MARGIN_LEFT + (self.iTail - self.iHead + 1) * (self.item_width + MARGIN_BETWEEN) --这里容易写错 ,写成 self.iTail - self.iHead + 1 - 1
self['item' .. self.iTail + 1]:setPosition(x, ITEM_Y)
self.inner:addChild(self['item' .. self.iTail + 1])
self.iTail = self.iTail + 1
self:set_an_item(self['item' .. self.iTail], self.iTail)
end
--当删除或添加items后应该调整之前的头尾位置
function scroll2:set_new_iHead_iTail()
self.visible_items = math.ceil(self.scv_width / (self.item_width + MARGIN_BETWEEN)) --可视域item数
self.iTail = self.iHead + self.visible_items - 1
self.iTail = math.min(#self.data, self.iTail)
self.iHead = self.iTail - self.visible_items + 1
self.iHead = math.max(1, self.iHead)
end
function scroll2:monitor()
local innerX = self.inner:getPositionX()
if self.delX < 0 and innerX < THRESHOLD then --把头item移至尾后
if self.iTail == #self.data then
return
end
local posX = MARGIN_LEFT
for i = self.iHead + 1, self.iTail do
self['item' .. i]:setPosition(posX, ITEM_Y)
posX = posX + (self.item_width + MARGIN_BETWEEN)
end
self.inner:setPosition(innerX + (self.item_width + MARGIN_BETWEEN), 0)
self['item' .. self.iHead]:setPosition(MARGIN_LEFT + (self.iTail - self.iHead + 1 - 1) * (self.item_width + MARGIN_BETWEEN), ITEM_Y)
self['item' .. self.iTail + 1] = self['item' .. self.iHead]
self['item' .. self.iHead] = nil
self.iHead = self.iHead + 1
self.iTail = self.iTail + 1
self:set_an_item(self['item' .. self.iTail], self.iTail)
if self.modSelf.item_change_i_to_j then
self.modSelf:item_change_i_to_j(self['item'.. self.iTail], self.iHead - 1, self.iTail) --从第i个变成第j个
end
end
if self.delX > 0 and innerX > THRESHOLD + self.item_width + MARGIN_BETWEEN then --这里的第二个判断不能为上面第二个判断的补集,否则滑动会出现空白
if self.iHead == 1 then
return
end
local posX = MARGIN_LEFT
for i = self.iHead, self.iTail - 1 do
posX = posX + (self.item_width + MARGIN_BETWEEN)
self['item' .. i]:setPosition(posX, ITEM_Y)
end
self.inner:setPosition(innerX - (self.item_width + MARGIN_BETWEEN), 0)
self['item' .. self.iTail]:setPosition(MARGIN_LEFT, ITEM_Y)
self['item' .. self.iHead - 1] = self['item' .. self.iTail]
self['item' .. self.iTail] = nil
self.iHead = self.iHead - 1
self.iTail = self.iTail - 1
self:set_an_item(self['item' .. self.iHead], self.iHead)
if self.modSelf.item_change_i_to_j then
self.modSelf:item_change_i_to_j(self['item'.. self.iHead], self.iTail + 1, self.iHead) --从第i个变成第j个
end
end
end
_G['scroll2'] = scroll2