cocos2dx滑动框重用/自动往后面加载


--[[
** 重用版本 使用对象池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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值