--[[
** 重用版本 使用对象池cell节点的重用
** 提高了刷新的效率,能够实现几百个节点不掉帧
*********************注意************************
*
* 重用的字体,设置颜色失效,慎用
* 重用的字体,设置颜色失效,慎用
* 重用的字体,设置颜色失效,慎用
* 暂时没有适配横向排列非一个的滑动cell
*
* 使用方式没有改变 参考 ScrollViewBase.lua
*
*************************************************
]]
local ScrollViewBase = class("ScrollViewBase")
function ScrollViewBase:ctor(tempView, auto)
self.cellpool = {}
self:init()
self:initScrollView(tempView)
self.autoGetNextData = auto == nil and false or auto
end
function ScrollViewBase:init()
self.getDataFunc = function()
print("-->>>>>>>>>ERROR: self.getDataFunc需要重写此方法")
end
self.updateCell = function()
print("-->>>>>>>>>ERROR: self.updateCell需要重写此方法")
end
self.createCell = function()
print("-->>>>>>>>>ERROR: self.createCell需要重写此方法")
end
self.page_num = 1
self.page_size = TM.R_PAGESIZE
self.nextData = nil
-- 横向排列
self.row = 1
self.row_sub_width = 10
-- 是否更新下个
self.isNextData = false
self.isUpdata = false
-- 单个cell的宽高
self.cellWidth = 0
self.cellHeight = 0
-- 额外增加高度
self.height_add = 0
-- 纵向的间距
self.subHeight = 10
-- 根据是否大于滑动框显示 ScrollBar
self.autohideBar = true
self.isRuning = false
-- 数据表格
self.listArr = {}
end
-- 获取第一次的数据
function ScrollViewBase:start()
self.isRuning = true
self.getDataFunc(function(listArr)
self:updateLevelList(listArr)
end)
end
local getChildText
getChildText = function(node)
if node then
for i, v in pairs(node:getChildren()) do
if v.getTexteure then
local texture = v:getTexteure()
print("texture", texture, texture:getName())
end
getChildText(v)
end
end
end
function ScrollViewBase:onCreateCell()
local bar = self.createCell()
-- getChildText(bar)
return bar
end
function ScrollViewBase:setScrollBarEnabled(isVis)
self.scrollView:setScrollBarEnabled(isVis)
end
function ScrollViewBase:getScrollView( ... )
return self.scrollView
end
ScrollViewBase.getSV = ScrollViewBase.getScrollView
function ScrollViewBase:getShowCellRange()
local yDis = self.scrollView:getInnerContainerPosition().y
local _width, _height = self.cellWidth, self.cellHeight
local oneWidth = _width
local oneHeigth = _height
local size1 = self.scrollView:getInnerContainerSize()
local size2 = self.scrollView:getContentSize()
-- 最上面的坐标是
local maxH = size1.height - size2.height
local tempy = math.abs(yDis)
-- 查看下向上滚动了多少像素
local suby = maxH - tempy
-- 计算当前最上面的值
local topNodeIndex = math.ceil(suby / (oneHeigth+self.subHeight))
local downIndex = math.ceil((suby+size2.height)/(oneHeigth+self.subHeight))
return topNodeIndex, downIndex
end
function ScrollViewBase:initScrollView(tempView)
local size = tempView:getContentSize()
local px, py = tempView:getPosition()
local parent = tempView:getParent()
tempView:removeSelf()
local scrollView = ccui.ScrollView:create()
parent:addChild(scrollView)
scrollView:setPosition(px, py)
scrollView:setScrollBarEnabled(true)
scrollView:setContentSize(size)
-- scrollView:setInnerContainerSize()
self.scrollView = scrollView
self.scrollView:setClippingType(1)
local touch = true
scrollView:addEventListener(function ( target, selector )
local yDis = scrollView:getInnerContainerPosition().y
-- 最上面的坐标是
if yDis < 0 then
local topNodeIndex, downIndex = self:getShowCellRange()
-- 判断上限
local topLine = topNodeIndex - 2
topLine = topLine <= 0 and 0 or topLine
-- 隐藏上面的
for i = 1, topLine do
self:cellToPool(self.scrollView:getChildByTag(i))
end
-- 这里需要初始化
for i = topLine + 1, topNodeIndex do
self:initCellByIndex(i)
end
local allCount = #self.listArr
-- 判断下线
local downLine = downIndex + 2
if downLine > allCount then
downLine = allCount + 1
end
for i = downLine, allCount do
self:cellToPool(self.scrollView:getChildByTag(i))
end
-- 这里需要初始化
for i = downIndex + 1, downLine do
self:initCellByIndex(i)
end
-- 不管怎么样,界面上的都是正常初始化的
for i = topNodeIndex, downIndex do
self:initCellByIndex(i)
end
end
if yDis >= 0 then
if touch == true then
touch = false
scrollView:runAction(cc.Sequence:create(
cc.DelayTime:create(0.5),
cc.CallFunc:create(function()
touch = true
end)
))
if self.autoGetNextData then
self.scrollView:stopScroll()
if self.nextData then
local data = clone(self.nextData)
self.nextData = nil
self:updateLevelList( data )
else
if not self.isUpdata then
self.isUpdata = true
self.getDataFunc(function(listArr)
self:updateLevelList(listArr)
self.isUpdata = false
end)
end
end
end
end
end
end)
end
function ScrollViewBase:clean()
self.page_num = 1
self.isRuning = false
self.listArr = {}
-- self.scrollView:removeAllChildren()
self:allCellToPool()
self.scrollView:jumpToTop()
-- self.scrollView:jumpToDestination()
end
-- 把所有的节点缓存起来
function ScrollViewBase:allCellToPool()
for i, v in pairs(self.scrollView:getChildren()) do
self:cellToPool(v)
end
end
-- 把所有的节点缓存起来
function ScrollViewBase:cellToPool(cell)
if cell then
cell:setVisible(false)
cell:setTag(-1)
self.cellpool[#self.cellpool+1] = cell
end
end
function ScrollViewBase:getOneCell()
if #self.cellpool == 0 then
local cell = self:onCreateCell()
self.scrollView:addChild(cell)
return cell
end
local cell = self.cellpool[#self.cellpool]
self.cellpool[#self.cellpool] = nil
cell:setVisible(true)
return cell
end
function ScrollViewBase:updateLevelList(lvListData)
lvListData = lvListData or {}
local num = #lvListData
if self.page_num == 1 then
-- self.scrollView:removeAllChildren()
self:allCellToPool()
-- self.scrollView:jumpToTop()
self.scrollView:stopScroll()
end
if num > 0 then
-- 直接更新数据
for i = 1, #lvListData do
self.listArr[#self.listArr+1] = lvListData[i]
end
self.page_num = self.page_num + 1
local _width, _height = self.cellWidth, self.cellHeight
local oneHeigth = _height
-- 横向排列
local allNum = #self.listArr
-- 重置滑动框大小
self:resetInnerContainerSize()
if self.page_num > 2 then
self.scrollView:runAction(cc.Sequence:create(
cc.DelayTime:create(0.01),
cc.CallFunc:create(function()
self.scrollView:stopScroll() -- 必须加上这一行,接下来的设置滚动位置才会生效(经大量测试滚动中去设置滚动位置不会生效)
if num > 2 then
self.scrollView:setInnerContainerPosition(cc.p(0, - num*oneHeigth+50))
end
end)
))
end
-- 计算下当前所处的位置,并且计算出来需要显示的节点
local topNodeIndex, downIndex = self:getShowCellRange()
-- 初始化cell
for i = topNodeIndex-2 , downIndex +2 do
if i > 0 and i <= #self.listArr then
local bar = self.scrollView:getChildByTag(i)
if not bar then
bar = self:getOneCell()
bar:setTag(i)
self.updateCell(bar, self.listArr[i])
end
end
end
self:resetPosition()
end
-- 不再往后获取
if num == 0 then
self.autoGetNextData = false
end
if self.autoGetNextData then
-- 依次往后面获取
self.scrollView:runAction(cc.Sequence:create(
cc.DelayTime:create(0.1),
cc.CallFunc:create(function()
if not self.isUpdata then
self.isNextData = true
self.isUpdata = true
self.getDataFunc(function(jdata)
self.nextData = jdata
self.isUpdata = false
end)
end
end)
))
end
end
function ScrollViewBase:initCellByIndex(index)
if index <= 0 or index > #self.listArr then
return
end
local _width, _height = self.cellWidth, self.cellHeight
local oneWidth = _width
local oneHeigth = _height
local size = self.scrollView:getInnerContainerSize()
local height = size.height
local bar = self.scrollView:getChildByTag(index)
if not bar then
bar = self:getOneCell()
bar:setTag(index)
self.updateCell(bar, self.listArr[index])
local rowIndex = index % self.row == 0 and self.row or index % self.row
local colIndex = math.ceil(index / self.row)
local x = (oneWidth + self.row_sub_width)* (rowIndex-1)
local y = height - colIndex * oneHeigth - self.subHeight * (colIndex-1)
bar:setPosition(x, y)
end
end
function ScrollViewBase:resetPosition( ... )
-- 初始化cell位置
local _width, _height = self.cellWidth, self.cellHeight
local oneWidth = _width
local oneHeigth = _height
local size = self.scrollView:getInnerContainerSize()
local height = size.height
for i = 1 , #self.listArr do
local bar = self.scrollView:getChildByTag(i)
if bar then
local rowIndex = i % self.row == 0 and self.row or i % self.row
local colIndex = math.ceil(i / self.row)
local x = (oneWidth + self.row_sub_width)* (rowIndex-1)
local y = height - colIndex * oneHeigth - self.subHeight * (colIndex-1)
bar:setPosition(x, y)
end
end
end
-- 重置滑动框大小。 确保节点都能在滑动范围之内
function ScrollViewBase:resetInnerContainerSize( ... )
-- 初始化cell位置
local scrollViewSize = AM.getNodeContentSize(self.scrollView)
local _width, _height = self.cellWidth, self.cellHeight
local oneHeigth = _height
local oneWidth = _width
-- 横向排列
local allNum = #self.listArr
local col_num = math.ceil(#self.listArr / self.row)
local height = col_num*oneHeigth + (col_num - 1) * self.subHeight
if height + self.height_add > scrollViewSize.height then
self.scrollView:setInnerContainerSize( cc.size( scrollViewSize.width , height + self.height_add ) )
if self.autohideBar then
self.scrollView:setScrollBarEnabled(true)
end
else
self.scrollView:setInnerContainerSize( cc.size( scrollViewSize.width , scrollViewSize.height) )
height = scrollViewSize.height
if self.autohideBar then
self.scrollView:setScrollBarEnabled(false)
end
end
end
-- 是否为空
function ScrollViewBase:isEmptyList()
return #self.listArr == 0
end
function ScrollViewBase:setCellSize(width, height)
if type(width) == "table" and height == nil then
self.cellWidth = width.width
self.cellHeight = width.height
else
self.cellWidth = width
self.cellHeight = height
end
end
function ScrollViewBase:setGetDataFunc(func)
if type(func) == "function" then
self.getDataFunc = func
end
end
function ScrollViewBase:setUpdateCellFunc(func)
if type(func) == "function" then
self.updateCell = func
end
end
function ScrollViewBase:setCreateCell(func)
if type(func) == "function" then
self.createCell = func
end
end
function ScrollViewBase:setPageNum(page_size)
if page_size then
self.page_size = page_size
end
end
function ScrollViewBase:setVisible(vis)
self.scrollView:setVisible(vis)
end
function ScrollViewBase:setSubHeight(_height)
if _height then
self.subHeight = _height
end
end
function ScrollViewBase:setSubWidth(_width)
if _width then
self.row_sub_width = _width
end
end
function ScrollViewBase:setRowNum(num)
if num then
self.row = num
end
end
-- 设置额外增加的值
function ScrollViewBase:setAddHeight(num)
if num then
self.height_add = num
end
end
function ScrollViewBase:onExit( ... )
end
return ScrollViewBase
cocos2dx滑动框重用/自动往后面加载
最新推荐文章于 2023-08-27 00:54:38 发布