Skip to content

Instantly share code, notes, and snippets.

@hsienwei
Last active August 31, 2016 03:31
Show Gist options
  • Save hsienwei/3d6937d893e94cbc64a0812477376f1e to your computer and use it in GitHub Desktop.
Save hsienwei/3d6937d893e94cbc64a0812477376f1e to your computer and use it in GitHub Desktop.
TableViewUtilEx<FrameHeros> m_TableUtil;
m_TableUtil.m_ScrollView = (ScrollView*)pObj;
m_TableUtil.m_CellWidget = dynamic_cast<Widget*>(_node->getChildByName("pal_hero"));;
m_TableUtil.m_PaddingX = 1;
m_TableUtil.m_PaddingY = 1;
m_TableUtil.m_CellSpaceX = 1;
m_TableUtil.m_CellSpaceY = 1;
m_TableUtil.m_Delegate = this;
m_TableUtil.m_Direction = m_TableUtil.VERTICAL;
m_TableUtil.calculateBaseCount();
m_TableUtil.init();
void FrameHeros::update( float delta )
{
m_TableUtil.ResetItem();
}
int FrameHeros::GetItemCount()
{
return nowitem;
}
bool FrameHeros::OnItemShow(Node *node, int idx)
{
CreateUnit(dynamic_cast<Widget*>(node), idx);
return false; // true: 繼續加下一個, false: 停止加下一個, 下一個frame再加.
}
void FrameHeros::update( float delta )
{
m_TableUtil.ResetItem();
}
/*class TableDelegate
{
public:
int GetItemCount(){return 0;}
bool OnItemShow( Node *Item, int Index){};
};*/
template<class TableDelegateT>
class TableViewUtilEx
{
public:
enum Direction
{
VERTICAL = 0,
HORIZONTAL,
};
TableViewUtilEx()
: m_ScrollView(nullptr)
, m_CellWidget(nullptr)
, m_CellPath()
, m_BaseCount(0)
, m_PaddingX(0)
, m_PaddingY(0)
, m_CellSpaceX(0)
, m_CellSpaceY(0)
, m_Direction(VERTICAL)
, m_Delegate( nullptr )
, m_RangeMin(0)
, m_RangeMax(-1)
, m_ItemSizeWidth(-1)
, m_ItemSizeHeight(-1)
{
m_FreeItemNode.clear();
}
void init()
{
while(m_ScrollView->getChildrenCount() > 0)
{
Node* Child = m_ScrollView->getChildren().at(0);
Child->setTag(-1);
m_FreeItemNode.pushBack(Child);
Child->removeFromParent();
}
if(m_Delegate == nullptr) return;
m_ScrollView->jumpToPercentVertical(0);
calculateBaseCount();
ScrollViewContentFit(m_Delegate->GetItemCount());
ResetItem();
}
void Clear()
{
if(NULL != m_CellWidget)
{
m_CellWidget = NULL;
}
if(NULL != m_ScrollView)
{
m_ScrollView->removeAllChildren();
}
m_FreeItemNode.clear();
}
cocos2d::Size GetCellSize()
{
if( m_CellWidget != nullptr )
{
return m_CellWidget->getContentSize();
}
return cocos2d::Size(m_ItemSizeWidth, m_ItemSizeHeight);
}
void GetScroolViewRange( int &Start, int &End )
{
cocos2d::Size CellSize = GetCellSize();
cocos2d::ui::Layout *Layout = m_ScrollView->getInnerContainer();
Vec2 LayoutPos = Layout->getPosition();
if(m_Direction == VERTICAL )
{
float UpY = LayoutPos.y - m_ScrollView->getContentSize().height + m_ScrollView->getInnerContainerSize().height;
int UpRow = (UpY - m_PaddingY) / (CellSize.height + m_CellSpaceY );
int StartIdx = UpRow * m_BaseCount;
float DownY = LayoutPos.y + m_ScrollView->getInnerContainerSize().height ;
int DownRow = (DownY - m_PaddingY) / (CellSize.height + m_CellSpaceY );
int EndIdx = (DownRow + 1) * m_BaseCount - 1;
// cocos2d::log("%f:%d:%d", LayoutPos.y, UpRow, DownRow);
Start = StartIdx;
End = EndIdx;
}
else
{
float LeftX = -LayoutPos.x;
int LeftColumn = (LeftX - m_PaddingX) / (CellSize.width + m_CellSpaceX );
int StartIdx = LeftColumn * m_BaseCount;
float RightX = -LayoutPos.x + m_ScrollView->getContentSize().width;
int RightColumn = (RightX - m_PaddingX) / (CellSize.width + m_CellSpaceX );
int EndIdx = (RightColumn + 1) * m_BaseCount - 1;
// cocos2d::log("%f:%d:%d", LayoutPos.x, LeftColumn, RightColumn);
Start = StartIdx;
End = EndIdx;
}
if( Start < 0) Start = 0;
if( End < 0) End = 0;
}
void ResetItem()
{
if(m_Delegate == nullptr) return;
if(m_CellWidget == nullptr) return;
int StartIdx, EndIdx;
GetScroolViewRange( StartIdx, EndIdx );
int WorkStartIdx = min(m_RangeMin, StartIdx);
int WorkEndIdx = max(m_RangeMax, EndIdx);
int ListCount = m_Delegate->GetItemCount();
if(ListCount == 0)
{
return;
}
bool AddFlag = true;
for( int i = WorkStartIdx; i<= WorkEndIdx; ++i)
{
Vec2 ItemPos = GetCellPosition(i);
Node *Child = m_ScrollView->getChildByTag(i);
if( i <= EndIdx && i >= StartIdx && i < ListCount)
{
if( !AddFlag ) continue;
if( Child )
{
Child->setPosition( ItemPos );
//AddFlag = m_Delegate->OnItemShow(Child, i);
}
else
{
Node *FreeNode = GetFreeItem();
if(FreeNode != nullptr)
{
Vec2 ItemPos = GetCellPosition(i);
m_ScrollView->addChild(FreeNode);
m_FreeItemNode.popBack();
FreeNode->setPosition( ItemPos );
FreeNode->setTag(i);
AddFlag = m_Delegate->OnItemShow(FreeNode, i);
}
}
}
else
{
if( Child )
{
m_FreeItemNode.pushBack(Child);
Child->setTag(-1);
Child->removeFromParent();
}
}
}
m_RangeMin = StartIdx;
m_RangeMax = EndIdx;
// cocos2d::log("free count:%d || scrollview child count: %d", m_FreeItemNode.size(), m_ScrollView->getChildrenCount());
}
Node* GetFreeItem()
{
Node* FreeItem = nullptr;
if(m_FreeItemNode.size() == 0)
{
if( m_CellWidget == nullptr )
{
m_FreeItemNode.pushBack( CSLoader::createNode(m_CellPath) );
}
else
{
m_FreeItemNode.pushBack(m_CellWidget->clone());
}
}
FreeItem = m_FreeItemNode.back();
return FreeItem;
}
void calculateBaseCount()
{
cocos2d::Size scrollSize = m_ScrollView->getContentSize();
cocos2d::Size cellSize = GetCellSize();
m_BaseCount = 1;
if(m_Direction == VERTICAL )
{
float calculateWidth = scrollSize.width - m_PaddingX *2 ;
m_BaseCount = calculateWidth / (cellSize.width);
if(1 < m_BaseCount)
{
m_CellSpaceX = (scrollSize.width - m_PaddingX *2 - cellSize.width * m_BaseCount) / (m_BaseCount - 1);
}
else
{
m_CellSpaceX = scrollSize.width - m_PaddingX *2 - cellSize.width * m_BaseCount;
}
}
else
{
float calculateHeight = scrollSize.height - m_PaddingY *2 ;
m_BaseCount = calculateHeight / (cellSize.height);
if(1 < m_BaseCount)
{
m_CellSpaceY = (scrollSize.height - m_PaddingY *2 - cellSize.height * m_BaseCount) / (m_BaseCount - 1);
}
else
{
m_CellSpaceY = scrollSize.height - m_PaddingY *2 - cellSize.height * m_BaseCount;
}
}
}
void ScrollViewContentFit(int cellCount)
{
cocos2d::Size cellSize = GetCellSize();
if(m_Direction == VERTICAL )
{
int row = cellCount / m_BaseCount ;
if( cellCount % m_BaseCount > 0)
{
row++;
}
float scrollViewExpendHeight = m_PaddingY * 2 + cellSize.height * row + m_CellSpaceY * (row -1);
m_ScrollView->setInnerContainerSize(cocos2d::Size(m_ScrollView->getContentSize().width, scrollViewExpendHeight));
}
else
{
int column = cellCount / m_BaseCount;
if( cellCount % m_BaseCount > 0)
{
column++;
}
float scrollViewExpendWidth = m_PaddingX * 2 + cellSize.width * column + m_CellSpaceX * (column -1);
m_ScrollView->setInnerContainerSize(cocos2d::Size(scrollViewExpendWidth, m_ScrollView->getContentSize().height));
}
}
Vec2 GetCellPosition(int idx)
{
cocos2d::Size cellSize = GetCellSize();
Vec2 rtn;
if(0 >= m_BaseCount)
{
return rtn;
}
if(m_Direction == VERTICAL )
{
rtn.x = idx % m_BaseCount * cellSize.width + (idx % m_BaseCount) * m_CellSpaceX + m_PaddingX + cellSize.width/2;
rtn.y = m_ScrollView->getInnerContainerSize().height - idx / m_BaseCount * cellSize.height - ((idx / m_BaseCount)) * m_CellSpaceY - m_PaddingY -cellSize.height/2;
}
else
{
rtn.y = m_ScrollView->getContentSize().height - idx % m_BaseCount * cellSize.height - ((idx % m_BaseCount) - 1) * m_CellSpaceY - m_PaddingY - cellSize.height/2;
rtn.x = idx / m_BaseCount * cellSize.width + (idx / m_BaseCount) * m_CellSpaceX + m_PaddingX +cellSize.width/2;
}
return rtn;
}
TableDelegateT *m_Delegate;
cocos2d::ui::ScrollView *m_ScrollView;
cocos2d::ui::Widget *m_CellWidget;
int m_BaseCount;
float m_PaddingX;
float m_PaddingY;
float m_CellSpaceX;
float m_CellSpaceY;
int m_Direction;
int m_RangeMin, m_RangeMax;
float m_ItemSizeWidth, m_ItemSizeHeight;
std::string m_CellPath;
cocos2d::Vector<Node*> m_FreeItemNode;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment