quick(3.2) UIListView扩展
前言
listview列表,在游戏中非常常见,比如道具列表,玩家列表,排行榜等等。每个版本可能使用方法可能有些差别,但是大同小异,原理和用途都是那几种,设置方向,间隔等。
这里是quick-lua3.3版本的使用和简单介绍.
UIListView 继承自 UIScrollView ,掌握 UIScrollView 用法和源码是非常有必要滴
使用及几个用法
初始化listView
1.例子
self.listView = cc.ui.UIListView.new({
direction = cc.ui.UIScrollView.DIRECTION_VERTICAL,
alignment = cc.ui.UIListView.ALIGNMENT_VCENTER,
viewRect = cc.rect(0,0,bg:getContentSize().width - 28, bg:getContentSize().height-88),
})
2.参数
- direction 列表控件的滚动方向,默认为垂直方向 - alignment listViewItem中content的对齐方式,默认为垂直居中 - viewRect 列表控件的显示区域 - scrollbarImgH 水平方向的滚动条 - scrollbarImgV 垂直方向的滚动条 - bgColor 背景色,nil表示无背景色 - bgStartColor 渐变背景开始色,nil表示无背景色 - bgEndColor 渐变背景结束色,nil表示无背景色 - bg 背景图 - bgScale9 背景图是否可缩放 - capInsets 缩放区域
(1)direction
UIScrollView.DIRECTION_BOTH = 0 UIScrollView.DIRECTION_VERTICAL = 1 --垂直 UIScrollView.DIRECTION_HORIZONTAL = 2
(2)alignment
UIListView.ALIGNMENT_LEFT = 0 UIListView.ALIGNMENT_RIGHT = 1 UIListView.ALIGNMENT_VCENTER = 2 UIListView.ALIGNMENT_TOP = 3 UIListView.ALIGNMENT_BOTTOM = 4 UIListView.ALIGNMENT_HCENTER = 5
item 、设置间隔:
1.使用:
local margin = {top = 0,bottom = 5,left = 0,right = 0}
local listItem = self.listView:newItem(node)
listItem:setMargin(margin) --设置间隔 (如果是玩家自己的话,就放大一点)
listItem:setItemSize(node:getContentSize().width, node:getContentSize().height)
setMargin原理
2.在设置itemsize时处理margin_
function UIListViewItem:setItemSize(w, h, bNoMargin)
if not bNoMargin then
if UIScrollView.DIRECTION_VERTICAL == self.lvDirection_ then
h = h + self.margin_.top + self.margin_.bottom
else
w = w + self.margin_.left + self.margin_.right
end
end
-- print("UIListViewItem - setItemSize w:" .. w .. " h:" .. h)
local oldSize = {width = self.width, height = self.height}
local newSize = {width = w, height = h}
self.width = w or 0
self.height = h or 0
self:setContentSize(w, h)
local bg = self:getChildByTag(UIListViewItem.BG_TAG)
if bg then
bg:setContentSize(w, h)
bg:setPosition(cc.p(w/2, h/2))
end
self.listener(self, newSize, oldSize)
end
注:设置间隔可以直接
listItem:setItemSize(node:getContentSize().width, node:getContentSize().height + XXXXX)
直接加也可以
UIListView.lua函数
framework/cc/ui/文件夹下
--------------------------------
-- @module UIListView
--[[--
quick 列表控件
]]
local UIScrollView = import(".UIScrollView")
local UIListView = class("UIListView", UIScrollView)
local UIListViewItem = import(".UIListViewItem")
UIListView.DELEGATE = "ListView_delegate"
UIListView.TOUCH_DELEGATE = "ListView_Touch_delegate"
UIListView.CELL_TAG = "Cell"
UIListView.CELL_SIZE_TAG = "CellSize"
UIListView.COUNT_TAG = "Count"
UIListView.CLICKED_TAG = "Clicked"
UIListView.UNLOAD_CELL_TAG = "UnloadCell"
UIListView.BG_ZORDER = -1
UIListView.CONTENT_ZORDER = 10
UIListView.ALIGNMENT_LEFT = 0
UIListView.ALIGNMENT_RIGHT = 1
UIListView.ALIGNMENT_VCENTER = 2
UIListView.ALIGNMENT_TOP = 3
UIListView.ALIGNMENT_BOTTOM = 4
UIListView.ALIGNMENT_HCENTER = 5
-- start --
--------------------------------
-- UIListView构建函数
-- @function [parent=#UIListView] new
-- @param table params 参数表
--[[--
UIListView构建函数
可用参数有:
- direction 列表控件的滚动方向,默认为垂直方向
- alignment listViewItem中content的对齐方式,默认为垂直居中
- viewRect 列表控件的显示区域
- scrollbarImgH 水平方向的滚动条
- scrollbarImgV 垂直方向的滚动条
- bgColor 背景色,nil表示无背景色
- bgStartColor 渐变背景开始色,nil表示无背景色
- bgEndColor 渐变背景结束色,nil表示无背景色
- bg 背景图
- bgScale9 背景图是否可缩放
- capInsets 缩放区域
]]
-- end --
function UIListView:ctor(params)
UIListView.super.ctor(self, params)
self.items_ = {}
self.direction = params.direction or UIScrollView.DIRECTION_VERTICAL
self.alignment = params.alignment or UIListView.ALIGNMENT_VCENTER
self.bAsyncLoad = params.async or false
self.container = cc.Node:create()
-- self.padding_ = params.padding or {left = 0, right = 0, top = 0, bottom = 0}
-- params.viewRect.x = params.viewRect.x + self.padding_.left
-- params.viewRect.y = params.viewRect.y + self.padding_.bottom
-- params.viewRect.width = params.viewRect.width - self.padding_.left - self.padding_.right
-- params.viewRect.height = params.viewRect.height - self.padding_.bottom - self.padding_.top
self:setDirection(params.direction)
self:setViewRect(params.viewRect)
self:addScrollNode(self.container)
self:onScroll(handler(self, self.scrollListener))
self.size = {}
self.itemsFree_ = {}
self.delegate_ = {}
self.redundancyViewVal = 0 --异步的视图两个方向上的冗余大小,横向代表宽,竖向代表高
end
function UIListView:onCleanup()
self:releaseAllFreeItems_()
end
-- start --
--------------------------------
-- 列表控件触摸注册函数
-- @function [parent=#UIListView] onTouch
-- @param function listener 触摸临听函数
-- @return UIListView#UIListView self 自身
-- end --
function UIListView:onTouch(listener)
self.touchListener_ = listener
return self
end
-- start --
--------------------------------
-- 列表控件设置所有listItem中content的对齐方式
-- @function [parent=#UIListView] setAlignment
-- @param number align 对
-- @return UIListView#UIListView self 自身
-- end --
function UIListView:setAlignment(align)
self.alignment = align
end
-- start --
--------------------------------
-- 创建一个新的listViewItem项
-- @function [parent=#UIListView] newItem
-- @param node item 要放到listViewItem中的内容content
-- @return UIListViewItem#UIListViewItem
-- end --
function UIListView:newItem(item)
item = UIListViewItem.new(item)
item:setDirction(self.direction)
item:onSizeChange(handler(self, self.itemSizeChangeListener))
return item
end
-- start --
--------------------------------
-- 设置显示区域
-- @function [parent=#UIListView] setViewRect
-- @return UIListView#UIListView self
-- end --
function UIListView:setViewRect(viewRect)
if UIScrollView.DIRECTION_VERTICAL == self.direction then
self.redundancyViewVal = viewRect.height
else
self.redundancyViewVal = viewRect.width
end
UIListView.super.setViewRect(self, viewRect)
end
function UIListView:itemSizeChangeListener(listItem, newSize, oldSize)
local pos = self:getItemPos(listItem)
if not pos then
return
end
local itemW, itemH = newSize.width - oldSize.width, newSize.height - oldSize.height
if UIScrollView.DIRECTION_VERTICAL == self.direction then
itemW = 0
else
itemH = 0
end
local content = listItem:getContent()
transition.moveBy(content,
{x = itemW/2, y = itemH/2, time = 0.2})
self.size.width = self.size.width + itemW
self.size.height = self.size.height + itemH
if UIScrollView.DIRECTION_VERTICAL == self.direction then
transition.moveBy(self.container,
{x = -itemW, y = -itemH, time = 0.2})
self:moveItems(1, pos - 1, itemW, itemH, true)
else
self:moveItems(pos + 1, table.nums(self.items_), itemW, itemH, true)
end
end
function UIListView:scrollListener(event)
if "clicked" == event.name then
local nodePoint = self.container:convertToNodeSpace(cc.p(event.x, event.y))
local pos
local idx
if self.bAsyncLoad then
local itemRect
for i,v in ipairs(self.items_) do
local posX, posY = v:getPosition()
local itemW, itemH = v:getItemSize()
itemRect = cc.rect(posX, posY, itemW, itemH)
if cc.rectContainsPoint(itemRect, nodePoint) then
idx = v.idx_
pos = i
break
end
end
else
nodePoint.x = nodePoint.x - self.viewRect_.x
nodePoint.y = nodePoint.y - self.viewRect_.y
local width, height = 0, self.size.height
local itemW, itemH = 0, 0
if UIScrollView.DIRECTION_VERTICAL == self.direction then
for i,v in ipairs(self.items_) do
itemW, itemH = v:getItemSize()
if nodePoint.y < height and nodePoint.y > height - itemH then
pos = i
idx = pos
nodePoint.y = nodePoint.y - (height - itemH)
break
end
height = height - itemH
end
else
for i,v in ipairs(self.items_) do
itemW, itemH = v:getItemSize()
if nodePoint.x > width and nodePoint.x < width + itemW then
pos = i
idx = pos
break
end
width = width + itemW
end
end
end
self:notifyListener_{name = "clicked",
listView = self, itemPos = idx, item = self.items_[pos],
point = nodePoint}
else
event.scrollView = nil
event.listView = self
self:notifyListener_(event)
end
end
-- start --
--------------------------------
-- 在列表项中添加一项
-- @function [parent=#UIListView] addItem
-- @param node listItem 要添加的项
-- @param integer pos 要添加的位置,默认添加到最后
-- @return UIListView#UIListView
-- end --
function UIListView:addItem(listItem, pos)
self:modifyItemSizeIf_(listItem)
if pos then
table.insert(self.items_, pos, listItem)
else
table.insert(self.items_, listItem)
end
self.container:addChild(listItem)
return self
end
-- start --
--------------------------------
-- 在列表项中移除一项
-- @function [parent=#UIListView] removeItem
-- @param node listItem 要移除的项
-- @param boolean bAni 是否要显示移除动画
-- @return UIListView#UIListView
-- end --
function UIListView:removeItem(listItem, bAni)
assert(not self.bAsyncLoad, "UIListView:removeItem() - syncload not support remove")
local itemW, itemH = listItem:getItemSize()
self.container:removeChild(listItem)
local pos = self:getItemPos(listItem)
if pos then
table.remove(self.items_, pos)
end
if UIScrollView.DIRECTION_VERTICAL == self.direction then
itemW = 0
else
itemH = 0
end
self.size.width = self.size.width - itemW
self.size.height = self.size.height - itemH
if 0 == table.nums(self.items_) then
return
end
if UIScrollView.DIRECTION_VERTICAL == self.direction then
self:moveItems(1, pos - 1, -itemW, -itemH, bAni)
else
self:moveItems(pos, table.nums(self.items_), -itemW, -itemH, bAni)
end
return self
end
-- start --
--------------------------------
-- 移除所有的项
-- @function [parent=#UIListView] removeAllItems
-- @return integer#integer
-- end --
function UIListView:removeAllItems()
self.container:removeAllChildren()
self.items_ = {}
return self
end
-- start --
--------------------------------
-- 取某项在列表控件中的位置
-- @function [parent=#UIListView] getItemPos
-- @param node listItem 列表项
-- @return integer#integer
-- end --
function UIListView:getItemPos(listItem)
for i,v in ipairs(self.items_) do
if v == listItem then
return i
end
end
end
-- start --
--------------------------------
-- 判断某项是否在列表控件的显示区域中
-- @function [parent=#UIListView] isItemInViewRect
-- @param integer pos 列表项位置
-- @return boolean#boolean
-- end --
function UIListView:isItemInViewRect(pos)
local item
if "number" == type(pos) then
item = self.items_[pos]
elseif "userdata" == type(pos) then
item = pos
end
if not item then
return
end
local bound = item:getBoundingBox()
local nodePoint = self.container:convertToWorldSpace(
cc.p(bound.x, bound.y))
bound.x = nodePoint.x
bound.y = nodePoint.y
return cc.rectIntersectsRect(self.viewRect_, bound)
end
-- start --
--------------------------------
-- 加载列表
-- @function [parent=#UIListView] reload
-- @return UIListView#UIListView
-- end --
function UIListView:reload()
if self.bAsyncLoad then
self:asyncLoad_()
else
self:layout_()
end
return self
end
-- start --
--------------------------------
-- 取一个空闲项出来,如果没有返回空
-- @function [parent=#UIListView] dequeueItem
-- @return UIListViewItem#UIListViewItem item
-- @see UIListViewItem
-- end --
function UIListView:dequeueItem()
if #self.itemsFree_ < 1 then
return
end
local item
item = table.remove(self.itemsFree_, 1)
--标识从free中取出,在loadOneItem_中调用release
--这里直接调用release,item会被释放掉
item.bFromFreeQueue_ = true
return item
end
function UIListView:layout_()
local width, height = 0, 0
local itemW, itemH = 0, 0
local margin
-- calcate whole width height
if UIScrollView.DIRECTION_VERTICAL == self.direction then
width = self.viewRect_.width
for i,v in ipairs(self.items_) do
itemW, itemH = v:getItemSize()
itemW = itemW or 0
itemH = itemH or 0
height = height + itemH
end
else
height = self.viewRect_.height
for i,v in ipairs(self.items_) do
itemW, itemH = v:getItemSize()
itemW = itemW or 0
itemH = itemH or 0
width = width + itemW
end
end
self:setActualRect({x = self.viewRect_.x,
y = self.viewRect_.y,
width = width,
height = height})
self.size.width = width
self.size.height = height
local tempWidth, tempHeight = width, height
if UIScrollView.DIRECTION_VERTICAL == self.direction then
itemW, itemH = 0, 0
local content
for i,v in ipairs(self.items_) do
itemW, itemH = v:getItemSize()
itemW = itemW or 0
itemH = itemH or 0
tempHeight = tempHeight - itemH
content = v:getContent()
content:setAnchorPoint(0.5, 0.5)
-- content:setPosition(itemW/2, itemH/2)
self:setPositionByAlignment_(content, itemW, itemH, v:getMargin())
v:setPosition(self.viewRect_.x,
self.viewRect_.y + tempHeight)
end
else
itemW, itemH = 0, 0
tempWidth = 0
for i,v in ipairs(self.items_) do
itemW, itemH = v:getItemSize()
itemW = itemW or 0
itemH = itemH or 0
content = v:getContent()
content:setAnchorPoint(0.5, 0.5)
-- content:setPosition(itemW/2, itemH/2)
self:setPositionByAlignment_(content, itemW, itemH, v:getMargin())
v:setPosition(self.viewRect_.x + tempWidth, self.viewRect_.y)
tempWidth = tempWidth + itemW
end
end
self.container:setPosition(0, self.viewRect_.height - self.size.height)
end
function UIListView:notifyItem(point)
local count = self.listener[UIListView.DELEGATE](self, UIListView.COUNT_TAG)
local temp = (self.direction == UIListView.DIRECTION_VERTICAL and self.container:getContentSize().height) or 0
local w,h = 0, 0
local tag = 0
for i = 1, count do
w,h = self.listener[UIListView.DELEGATE](self, UIListView.CELL_SIZE_TAG, i)
if self.direction == UIListView.DIRECTION_VERTICAL then
temp = temp - h
if point.y > temp then
point.y = point.y - temp
tag = i
break
end
else
temp = temp + w
if point.x < temp then
point.x = point.x + w - temp
tag = i
break
end
end
end
if 0 == tag then
printInfo("UIListView - didn't found item")
return
end
local item = self.container:getChildByTag(tag)
self.listener[UIListView.DELEGATE](self, UIListView.CLICKED_TAG, tag, point)
end
function UIListView:moveItems(beginIdx, endIdx, x, y, bAni)
if 0 == endIdx then
self:elasticScroll()
end
local posX, posY = 0, 0
local moveByParams = {x = x, y = y, time = 0.2}
for i=beginIdx, endIdx do
if bAni then
if i == beginIdx then
moveByParams.onComplete = function()
self:elasticScroll()
end
else
moveByParams.onComplete = nil
end
transition.moveBy(self.items_[i], moveByParams)
else
posX, posY = self.items_[i]:getPosition()
self.items_[i]:setPosition(posX + x, posY + y)
if i == beginIdx then
self:elasticScroll()
end
end
end
end
function UIListView:notifyListener_(event)
if not self.touchListener_ then
return
end
self.touchListener_(event)
end
function UIListView:modifyItemSizeIf_(item)
local w, h = item:getItemSize()
if UIScrollView.DIRECTION_VERTICAL == self.direction then
if w ~= self.viewRect_.width then
item:setItemSize(self.viewRect_.width, h, true)
end
else
if h ~= self.viewRect_.height then
item:setItemSize(w, self.viewRect_.height, true)
end
end
end
function UIListView:update_(dt)
UIListView.super.update_(self, dt)
self:checkItemsInStatus_()
if self.bAsyncLoad then
self:increaseOrReduceItem_()
end
end
function UIListView:checkItemsInStatus_()
if not self.itemInStatus_ then
self.itemInStatus_ = {}
end
local rectIntersectsRect = function(rectParent, rect)
-- dump(rectParent, "parent:")
-- dump(rect, "rect:")
local nIntersects -- 0:no intersects,1:have intersects,2,have intersects and include totally
local bIn = rectParent.x <= rect.x and
rectParent.x + rectParent.width >= rect.x + rect.width and
rectParent.y <= rect.y and
rectParent.y + rectParent.height >= rect.y + rect.height
if bIn then
nIntersects = 2
else
local bNotIn = rectParent.x > rect.x + rect.width or
rectParent.x + rectParent.width < rect.x or
rectParent.y > rect.y + rect.height or
rectParent.y + rectParent.height < rect.y
if bNotIn then
nIntersects = 0
else
nIntersects = 1
end
end
return nIntersects
end
local newStatus = {}
local bound
local nodePoint
for i,v in ipairs(self.items_) do
bound = v:getBoundingBox()
nodePoint = self.container:convertToWorldSpace(cc.p(bound.x, bound.y))
bound.x = nodePoint.x
bound.y = nodePoint.y
newStatus[i] =
rectIntersectsRect(self.viewRect_, bound)
end
-- dump(self.itemInStatus_, "status:")
-- dump(newStatus, "newStatus:")
for i,v in ipairs(newStatus) do
if self.itemInStatus_[i] and self.itemInStatus_[i] ~= v then
-- print("statsus:" .. self.itemInStatus_[i] .. " v:" .. v)
local params = {listView = self,
itemPos = i,
item = self.items_[i]}
if 0 == v then
params.name = "itemDisappear"
elseif 1 == v then
params.name = "itemAppearChange"
elseif 2 == v then
params.name = "itemAppear"
end
self:notifyListener_(params)
else
-- print("status same:" .. self.itemInStatus_[i])
end
end
self.itemInStatus_ = newStatus
-- dump(self.itemInStatus_, "status:")
-- print("itemStaus:" .. #self.itemInStatus_)
end
--[[--
动态调整item,是否需要加载新item,移除旧item
私有函数
]]
function UIListView:increaseOrReduceItem_()
if 0 == #self.items_ then
print("ERROR items count is 0")
return
end
local getContainerCascadeBoundingBox = function ()
local boundingBox
for i, item in ipairs(self.items_) do
local w,h = item:getItemSize()
local x,y = item:getPosition()
local anchor = item:getAnchorPoint()
x = x - anchor.x * w
y = y - anchor.y * h
if boundingBox then
boundingBox = cc.rectUnion(boundingBox, cc.rect(x, y, w, h))
else
boundingBox = cc.rect(x, y, w, h)
end
end
local point = self.container:convertToWorldSpace(cc.p(boundingBox.x, boundingBox.y))
boundingBox.x = point.x
boundingBox.y = point.y
return boundingBox
end
local count = self.delegate_[UIListView.DELEGATE](self, UIListView.COUNT_TAG)
local nNeedAdjust = 2 --作为是否还需要再增加或减少item的标志,2表示上下两个方向或左右都需要调整
local cascadeBound = getContainerCascadeBoundingBox()
local item
local itemW, itemH
-- print("child count:" .. self.container:getChildrenCount())
-- dump(cascadeBound, "increaseOrReduceItem_ cascadeBound:")
-- dump(self.viewRect_, "increaseOrReduceItem_ viewRect:")
if UIScrollView.DIRECTION_VERTICAL == self.direction then
--ahead part of view
local disH = cascadeBound.y + cascadeBound.height - self.viewRect_.y - self.viewRect_.height
local tempIdx
item = self.items_[1]
if not item then
print("increaseOrReduceItem_ item is nil, all item count:" .. #self.items_)
return
end
tempIdx = item.idx_
-- print(string.format("befor disH:%d, view val:%d", disH, self.redundancyViewVal))
if disH > self.redundancyViewVal then
itemW, itemH = item:getItemSize()
if cascadeBound.height - itemH > self.viewRect_.height
and disH - itemH > self.redundancyViewVal then
self:unloadOneItem_(tempIdx)
else
nNeedAdjust = nNeedAdjust - 1
end
else
item = nil
tempIdx = tempIdx - 1
if tempIdx > 0 then
local localPoint = self.container:convertToNodeSpace(cc.p(cascadeBound.x, cascadeBound.y + cascadeBound.height))
item = self:loadOneItem_(localPoint, tempIdx, true)
end
if nil == item then
nNeedAdjust = nNeedAdjust - 1
end
end
--part after view
disH = self.viewRect_.y - cascadeBound.y
item = self.items_[#self.items_]
if not item then
return
end
tempIdx = item.idx_
-- print(string.format("after disH:%d, view val:%d", disH, self.redundancyViewVal))
if disH > self.redundancyViewVal then
itemW, itemH = item:getItemSize()
if cascadeBound.height - itemH > self.viewRect_.height
and disH - itemH > self.redundancyViewVal then
self:unloadOneItem_(tempIdx)
else
nNeedAdjust = nNeedAdjust - 1
end
else
item = nil
tempIdx = tempIdx + 1
if tempIdx <= count then
local localPoint = self.container:convertToNodeSpace(cc.p(cascadeBound.x, cascadeBound.y))
item = self:loadOneItem_(localPoint, tempIdx)
end
if nil == item then
nNeedAdjust = nNeedAdjust - 1
end
end
else
--left part of view
local disW = self.viewRect_.x - cascadeBound.x
item = self.items_[1]
local tempIdx = item.idx_
if disW > self.redundancyViewVal then
itemW, itemH = item:getItemSize()
if cascadeBound.width - itemW > self.viewRect_.width
and disW - itemW > self.redundancyViewVal then
self:unloadOneItem_(tempIdx)
else
nNeedAdjust = nNeedAdjust - 1
end
else
item = nil
tempIdx = tempIdx - 1
if tempIdx > 0 then
local localPoint = self.container:convertToNodeSpace(cc.p(cascadeBound.x, cascadeBound.y))
item = self:loadOneItem_(localPoint, tempIdx, true)
end
if nil == item then
nNeedAdjust = nNeedAdjust - 1
end
end
--right part of view
disW = cascadeBound.x + cascadeBound.width - self.viewRect_.x - self.viewRect_.width
item = self.items_[#self.items_]
tempIdx = item.idx_
if disW > self.redundancyViewVal then
itemW, itemH = item:getItemSize()
if cascadeBound.width - itemW > self.viewRect_.width
and disW - itemW > self.redundancyViewVal then
self:unloadOneItem_(tempIdx)
else
nNeedAdjust = nNeedAdjust - 1
end
else
item = nil
tempIdx = tempIdx + 1
if tempIdx <= count then
local localPoint = self.container:convertToNodeSpace(cc.p(cascadeBound.x + cascadeBound.width, cascadeBound.y))
item = self:loadOneItem_(localPoint, tempIdx)
end
if nil == item then
nNeedAdjust = nNeedAdjust - 1
end
end
end
-- print("increaseOrReduceItem_() adjust:" .. nNeedAdjust)
-- print("increaseOrReduceItem_() item count:" .. #self.items_)
if nNeedAdjust > 0 then
return self:increaseOrReduceItem_()
end
end
--[[--
异步加载列表数据
@return UIListView
]]
function UIListView:asyncLoad_()
self:removeAllItems()
self.container:setPosition(0, 0)
self.container:setContentSize(cc.size(0, 0))
local count = self.delegate_[UIListView.DELEGATE](self, UIListView.COUNT_TAG)
self.items_ = {}
local itemW, itemH = 0, 0
local item
local containerW, containerH = 0, 0
local posX, posY = 0, 0
for i=1,count do
item, itemW, itemH = self:loadOneItem_(cc.p(posX, posY), i)
if UIScrollView.DIRECTION_VERTICAL == self.direction then
posY = posY - itemH
containerH = containerH + itemH
else
posX = posX + itemW
containerW = containerW + itemW
end
-- 初始布局,最多保证可隐藏的区域大于显示区域就可以了
if containerW > self.viewRect_.width + self.redundancyViewVal
or containerH > self.viewRect_.height + self.redundancyViewVal then
break
end
end
-- self.container:setPosition(self.viewRect_.x, self.viewRect_.y)
if UIScrollView.DIRECTION_VERTICAL == self.direction then
self.container:setPosition(self.viewRect_.x,
self.viewRect_.y + self.viewRect_.height)
else
self.container:setPosition(self.viewRect_.x, self.viewRect_.y)
end
return self
end
-- start --
--------------------------------
-- 设置delegate函数
-- @function [parent=#UIListView] setDelegate
-- @return UIListView#UIListView
-- end --
function UIListView:setDelegate(delegate)
self.delegate_[UIListView.DELEGATE] = delegate
end
--[[--
调整item中content的布局,
私有函数
]]
function UIListView:setPositionByAlignment_(content, w, h, margin)
local size = content:getContentSize()
if 0 == margin.left and 0 == margin.right and 0 == margin.top and 0 == margin.bottom then
if UIScrollView.DIRECTION_VERTICAL == self.direction then
if UIListView.ALIGNMENT_LEFT == self.alignment then
content:setPosition(size.width/2, h/2)
elseif UIListView.ALIGNMENT_RIGHT == self.alignment then
content:setPosition(w - size.width/2, h/2)
else
content:setPosition(w/2, h/2)
end
else
if UIListView.ALIGNMENT_TOP == self.alignment then
content:setPosition(w/2, h - size.height/2)
elseif UIListView.ALIGNMENT_RIGHT == self.alignment then
content:setPosition(w/2, size.height/2)
else
content:setPosition(w/2, h/2)
end
end
else
local posX, posY
if 0 ~= margin.right then
posX = w - margin.right - size.width/2
else
posX = size.width/2 + margin.left
end
if 0 ~= margin.top then
posY = h - margin.top - size.height/2
else
posY = size.height/2 + margin.bottom
end
content:setPosition(posX, posY)
end
end
--[[--
加载一个数据项
私有函数
@param table originPoint 数据项要加载的起始位置
@param number idx 要加载数据的序号
@param boolean bBefore 是否加在已有项的前面
@return UIListViewItem item
]]
function UIListView:loadOneItem_(originPoint, idx, bBefore)
-- print("UIListView loadOneItem idx:" .. idx)
-- dump(originPoint, "originPoint:")
local itemW, itemH = 0, 0
local item
local containerW, containerH = 0, 0
local posX, posY = originPoint.x, originPoint.y
local content
item = self.delegate_[UIListView.DELEGATE](self, UIListView.CELL_TAG, idx)
if nil == item then
print("ERROR! UIListView load nil item")
return
end
item.idx_ = idx
itemW, itemH = item:getItemSize()
if UIScrollView.DIRECTION_VERTICAL == self.direction then
itemW = itemW or 0
itemH = itemH or 0
if bBefore then
posY = posY
else
posY = posY - itemH
end
content = item:getContent()
content:setAnchorPoint(0.5, 0.5)
self:setPositionByAlignment_(content, itemW, itemH, item:getMargin())
item:setPosition(0, posY)
containerH = containerH + itemH
else
itemW = itemW or 0
itemH = itemH or 0
if bBefore then
posX = posX - itemW
end
content = item:getContent()
content:setAnchorPoint(0.5, 0.5)
self:setPositionByAlignment_(content, itemW, itemH, item:getMargin())
item:setPosition(posX, 0)
containerW = containerW + itemW
end
if bBefore then
table.insert(self.items_, 1, item)
else
table.insert(self.items_, item)
end
self.container:addChild(item)
if item.bFromFreeQueue_ then
item.bFromFreeQueue_ = nil
item:release()
end
-- local cascadeBound = self.container:getCascadeBoundingBox()
-- dump(cascadeBound, "cascadeBound:")
return item, itemW, itemH
end
--[[--
移除一个数据项
私有函数
]]
function UIListView:unloadOneItem_(idx)
-- print("UIListView unloadOneItem idx:" .. idx)
local item = self.items_[1]
if nil == item then
return
end
if item.idx_ > idx then
return
end
local unloadIdx = idx - item.idx_ + 1
item = self.items_[unloadIdx]
if nil == item then
return
end
table.remove(self.items_, unloadIdx)
self:addFreeItem_(item)
-- item:removeFromParent(false)
self.container:removeChild(item, false)
self.delegate_[UIListView.DELEGATE](self, UIListView.UNLOAD_CELL_TAG, idx)
end
--[[--
加一个空项到空闲列表中
私有函数
]]
function UIListView:addFreeItem_(item)
item:retain()
table.insert(self.itemsFree_, item)
end
--[[--
释放所有的空闲列表项
私有函数
]]
function UIListView:releaseAllFreeItems_()
for i,v in ipairs(self.itemsFree_) do
v:release()
end
self.itemsFree_ = {}
end
return UIListView


浙公网安备 33010602011771号