效果
实现一个自定义的TableLayer,该Layer具有以下特性
1. 该TableLayer可以在create的时候可以设置表格的行数和列数
2. 该TableLayer具有一个addCell方法可以添加CCNode对象到表格
3. 该TableLayer可以自动对表格中的CCNode对象进行排列
假设行数为3,列数为3时,通过TableLayer的addCell方法添加12个宽和高相同的CCNode对象,它们的添加顺序和位置如下图所示:
可以看出表格可以不断向右扩展,而且单元格自动排序,如果把该TableLayer添加到CCScrollView的container中,就可以实现一个可滑动的自定义TableView了。
实现思路
1. TableLayer继承CCLayer
2. TableLayer通过构造函数传入表格列数、行数、单元格宽、高
3. TableLayer提供了一个addCell方法添加单元格(CCNode对象)
4. addCell方法先调用nextCell方法获取单元格的坐标(由单元格的列数和行数组成),然后调用positionByColumnAndRow方法根据单元格坐标获取该单元格的位置,最后 调用CCNode的setPosition方法设置位置并添加到TableLayer中。
如何知道单元格的位置?
1.首先需要知道单元格的所在的列和行,通过nextCell方法获取,具体逻辑下面的代码有说明。
2.然后根据单元格的宽、高,表格的高度计算单元格的的x,y坐标。
第一列为1,第一行为1
x = 单元格宽度 * (单元格所在列 - 1)+ 单元格宽度 / 2
y = 表格高度 - (单元格高度 * (单元格所在行 - 1)+ 单元格高度 / 2)(注意:cocos2d-x坐标是以左下角为原点,而这里单元格坐标是以左上角为原点)
实现代码
Lua代码:
-- 表格控件
TableLayer = class("TableLayer",function ()
return CCLayer:create()
end)
-- 创建一个TableLayer
--kCCScrollViewDirectionHorizontal -- 水平滚动
--kCCScrollViewDirectionVertical -- 竖直滚动
-- direction 方向
-- column 可视区域的列数
-- row 可视区域的行数
-- cellWidth 单元格宽度
-- cellHeight 单元格高度
function TableLayer:create(direction, column, row, cellWidth, cellHeight)
local layer = TableLayer.new()
layer:init(direction, column, row, cellWidth, cellHeight)
return layer
end
-- 根据单元格坐标计算出单元格的位置
local function positionByColumnAndRow_H(self, column, row)
local x = self.cellWidth*(column-1) + self.cellWidth/2
local y = self.height - self.cellHeight*(row-1) - self.cellHeight/2 -- 需要转换为UI坐标
-- cclog("positionByColumnAndRow column=%d row=%d x=%f y=%f", column, row, x, y)
return x,y
end
-- 单元格坐标计算逻辑
local function nextCell_H(self)
local column = self.nextColumn
local row = self.nextRow
-- 计算下一个单元格的坐标
if column < self.column then -- 在指定列内
self.nextColumn = self.nextColumn + 1
elseif column == self.column then -- 达到指定列
-- 到达指定行,换列
if row == self.row then
self.nextColumn = column + 1
self.nextRow = 1
else
-- 未到达指定行,换行
self.nextColumn = 1
self.nextRow = row + 1
end
else
-- 到达指定行,+列
if row == self.row then
self.nextColumn = column + 1
self.nextRow = 1
else
self.nextRow = row + 1
end
end
cclog("nextCell column=%d row=%d",column,row)
self.curColumn = column
return column,row
end
-- 获取下一个单元格位置
local function nextPosition_H(self)
return positionByColumnAndRow_H(self,nextCell_H(self))
end
-- 添加表格
local function addCell_H(self, cell)
cell:setAnchorPoint(ccp(0.5,0.5))
cell:setPosition(nextPosition_H(self))
self:addChild(cell)
self:setContentSize(CCSize(self.curColumn * self.cellWidth, self.height))
end
-- 根据表格坐标获取位置
local function getPosByCellCoord(self, column, row)
local x = self.cellWidth/2 + (column-1)*self.cellWidth
local y = self.cellHeight/2 + (self.curRow - row)*self.cellHeight
return x,y
end
local function addCell_V(self, cell)
cell:setAnchorPoint(ccp(0.5,0.5))
table.insert(self.cells,cell)
self.curRow = math.ceil(#self.cells/self.column)
-- 更新所有单元格位置
local column = nil
local row = nil
for i=1, #self.cells do
local temp = self.cells[i]
-- 计算单元格所在列
column = i%self.column
column = if_else(column==0,self.column,column) -- 边界判断
-- 计算单元格所在行(从最高往下)
row = math.ceil(i/self.column)
-- 更新位置
temp:setPosition(ccp(getPosByCellCoord(self, column,row)))
end
self:addChild(cell)
-- 更新大小
self:setContentSize(CCSize(self.width, self.curRow * self.cellHeight))
end
-- 初始化
function TableLayer:init(direction, column, row, cellWidth, cellHeight)
self.direction = direction
-- 列
self.column = column
-- 行
self.row = row
-- 列宽
self.cellWidth = cellWidth
-- 列高
self.cellHeight = cellHeight
-- 下一行
self.nextColumn = 1
self.curColumn = 1
-- 下一列
self.nextRow = 1
-- 表格宽高
self.width = column * cellWidth
self.height = row * cellHeight
-- 方向判断
if self.direction == kCCScrollViewDirectionHorizontal then
self.addCellFuc = addCell_H
else
self.cells = {}
self.addCellFuc = addCell_V
end
end
-- 添加单元格
function TableLayer:addCell(cell)
return self.addCellFuc(self,cell)
end
function TableLayer:getTableView()
if self.scrollView == nil then
self.scrollView = CCScrollView:create(CCSizeMake(self.column * self.cellWidth, self.row * self.cellHeight), self)
-- cclog("ViewSize width=%s height=%s,ContainerSize width=%s height=%s",self.column * self.cellWidth, self.row * self.cellHeight,self:getContentSize().width,self:getContentSize().height)
-- 设置滚动方向
self.scrollView:setDirection(self.direction)
end
return self.scrollView
end
调用示例:
local tabLayer = TableLayer:create(kCCScrollViewDirectionVertical,1,4,565,70)
tabLayer:addCell(CCSprite:create("res/ui/shop/item1.png"))
tabLayer:addCell(CCSprite:create("res/ui/shop/item2.png"))
tabLayer:addCell(CCSprite:create("res/ui/shop/item3.png"))
tabLayer:addCell(CCSprite:create("res/ui/shop/item4.png"))
tabLayer:addCell(CCSprite:create("res/ui/shop/item5.png"))
local tabView = tabLayer:getTableView()
tabView:setPosition(285,115)
layer:addChild(tabView)