基于cocoStudio的UIListView的可以左右滑动翻页的ListView

//WidgetSlideListView.h

class WidgetEaseInListView : public cocos2d::gui::UIListView
{
public:
	static WidgetEaseInListView* create(cocos2d::gui::UIListView* pAnthor=NULL);
	void doEaseIn(bool bRight2Left=true);

protected:
	virtual void copySpecialProperties(cocos2d::gui::Widget* model);

protected:
	virtual void onEaseInOver();
	virtual void startEaseIn(bool bRight2Left);
	virtual void tick(float delta);

protected:
	bool m_bRight2Left;
};

class SlideListViewDataSource
{
public:
	virtual size_t getTotalItemNum() = 0;
	virtual size_t getEveryPageItemNum() = 0;
	virtual cocos2d::gui::UIWidget* getWidgetAt(size_t nIdx) = 0;
	virtual void onPageTurnOver(size_t nCurrentPage){}
};

class WidgetSlideListView : public WidgetEaseInListView
{
	enum SlideDir
	{
		eSlideDir_None = 0,
		eSlideDir_Horizon_Left,
		eSlideDir_Horizon_Right,
		eSlideDir_Virtical
	};

protected:
	WidgetSlideListView();
	virtual ~WidgetSlideListView();

public:
	static WidgetSlideListView* create(SlideListViewDataSource* pDelegate,cocos2d::gui::UIListView* pAnthor=NULL);

public:
	void		setDelegate(SlideListViewDataSource* pDelegate){ m_pDelegate = pDelegate; }
	void		reloadData();
	size_t		getCurrentPage()const{ return m_nCurrentPage; }
	void		turnToPage(unsigned int nPage);

protected:
	virtual bool init();
	virtual void handleMoveLogic(const cocos2d::CCPoint &touchPoint);
	virtual void handleReleaseLogic(const cocos2d::CCPoint &touchPoint);    
	void		scheduleTurnPage(float t);


protected:
	SlideListViewDataSource* m_pDelegate;
	size_t		m_nCurrentPage;
	SlideDir	m_eSlideDir;
	cocos2d::CCPoint		m_BackPos;
};

  

//WidgetSlideListView.cpp

#include "../include/WidgetSlideListView.h"

USING_NS_CC;
USING_NS_CC_EXT;
using namespace cocos2d::gui;

WidgetEaseInListView* WidgetEaseInListView::create(UIListView* pAnthor/*=NULL*/)
{
	WidgetEaseInListView* pRet = new WidgetEaseInListView();
	if (pRet && pRet->init())
	{
		pRet->autorelease();
		if (pAnthor)
		{
			pRet->copyProperties(pAnthor);
		}

		return pRet;
	}
	else
	{
		delete pRet;
		pRet = NULL;
		return NULL;
	}
}

void WidgetEaseInListView::copySpecialProperties(cocos2d::gui::Widget* model)
{
	UIListView::copySpecialProperties(model);

	setDirection(SCROLLVIEW_DIR_VERTICAL);
	setBounceEnabled(true);
	setTouchEnabled(true);
}

void WidgetEaseInListView::tick(float delta)
{
	startEaseIn(m_bRight2Left);
}

void WidgetEaseInListView::doEaseIn(bool bRight2Left)
{
	stopAllActions();
	for (unsigned int i=0; i<getItems()->count(); i++)
	{
		UIWidget* pWidget = getItem(i);
		pWidget->setVisible(false);
	}
	m_bRight2Left = bRight2Left;
	scheduleOnce(schedule_selector(WidgetEaseInListView::tick),0);
}

void WidgetEaseInListView::startEaseIn(bool bRight2Left)
{
	setTouchEnabled(false);

	static const float fDelay = 0.1f;
	static const float fMoveTime = 0.4f;

	CCArray* pActSeq = CCArray::create();

	float fVisibleHeight = 0.0f;
	float fTotalHeight = getSize().height;
	CCArray* pArr = getItems();
	int nSlidCount =0;
	for (unsigned int i=0; i<pArr->count(); i++)
	{
		UIWidget* pWidget = getItem(i);
		pWidget->setVisible(true);

		fVisibleHeight+=pWidget->getSize().height;
		if (fVisibleHeight<fTotalHeight+pWidget->getSize().height)
		{
			float fOffset = (bRight2Left?1:-1)*pWidget->getContentSize().width;
			CCPoint startPos = ccpAdd(pWidget->getPosition(),ccp(fOffset,0));
			//CCPoint startPos = ccp(pWidget->getContentSize().width/2+fOffset,pWidget->getPosition().y);
			pWidget->setPosition(startPos);
			CCSequence* pAct = CCSequence::createWithTwoActions(CCDelayTime::create(fDelay*i),CCEaseBackOut::create(CCMoveBy::create(fMoveTime,ccp(-fOffset,0))));
			pActSeq->addObject(CCTargetedAction::create(pWidget,pAct) );

			nSlidCount++;
		}
	}
	CCSequence* pAct = CCSequence::createWithTwoActions(CCDelayTime::create(fDelay*nSlidCount),CCCallFunc::create(this,callfunc_selector(WidgetEaseInListView::onEaseInOver)));
	pActSeq->addObject(pAct);

	runAction(CCSpawn::create(pActSeq));
}

void WidgetEaseInListView::onEaseInOver()
{
	setTouchEnabled(true);
}


WidgetSlideListView::WidgetSlideListView()
	:m_pDelegate(NULL)
	,m_nCurrentPage(0)
	,m_eSlideDir(eSlideDir_None)
{

}

WidgetSlideListView::~WidgetSlideListView()
{

}

WidgetSlideListView* WidgetSlideListView::create(SlideListViewDataSource* pDelegate,UIListView* pAnthor/*=NULL*/)
{
	WidgetSlideListView* pRet = new WidgetSlideListView();
	if (pRet && pRet->init())
	{
		pRet->autorelease();
		pRet->setDelegate(pDelegate);
		if (pAnthor)
		{
			pRet->copyProperties(pAnthor);
		}

		return pRet;
	}
	else
	{
		delete pRet;
		pRet = NULL;
		return NULL;
	}

}

bool WidgetSlideListView::init()
{
	if (UIListView::init())
	{
		setDirection(SCROLLVIEW_DIR_VERTICAL);
		setBounceEnabled(true);
		setTouchEnabled(true);
		return true;
	}
	return false;
}

void WidgetSlideListView::reloadData()
{
	assert(m_pDelegate);
	assert(m_pDelegate->getEveryPageItemNum()>0);
	unsigned int nTotalPage = m_pDelegate->getTotalItemNum()/m_pDelegate->getEveryPageItemNum();
	nTotalPage+= m_pDelegate->getTotalItemNum()%m_pDelegate->getEveryPageItemNum()>0 ? 1 : 0;

	assert(m_nCurrentPage>=0);

	removeAllItems();
	if (m_pDelegate->getTotalItemNum()>0)
	{
		assert(m_nCurrentPage<nTotalPage);

		for (size_t i=0; i<m_pDelegate->getEveryPageItemNum(); i++)
		{
			if (m_pDelegate->getTotalItemNum()<(i+1)+m_nCurrentPage*m_pDelegate->getEveryPageItemNum())
			{
				break;
			}

			UIWidget* pChild = m_pDelegate->getWidgetAt(m_nCurrentPage*m_pDelegate->getEveryPageItemNum()+i);

			if (!pChild)
			{
				break;
			}

			pushBackCustomItem(pChild);
		}
	}
	jumpToTop();
}

void WidgetSlideListView::handleMoveLogic( const CCPoint &touchPoint )
{
	_touchMovedPoint = convertToNodeSpace(touchPoint);
	CCPoint delta = _touchMovedPoint - _touchBeganPoint;

	if (eSlideDir_None==m_eSlideDir)
	{
		m_eSlideDir = fabs(delta.x)>fabs(delta.y) ? eSlideDir_Horizon_Left : eSlideDir_Virtical;
		m_BackPos = _innerContainer->getPosition();
	}

	if (eSlideDir_Virtical==m_eSlideDir)
	{
		UIListView::handleMoveLogic(touchPoint);
	}
	else if (eSlideDir_None!=m_eSlideDir)
	{
		if (isTouchEnabled())
		{
			CCPoint pt = ccp(m_BackPos.x+delta.x,m_BackPos.y);
			_innerContainer->setPosition(pt);
		}
	}	
}

void WidgetSlideListView::handleReleaseLogic( const CCPoint &touchPoint )
{
	if (eSlideDir_Virtical==m_eSlideDir)
	{
		UIListView::handleReleaseLogic(touchPoint);
		m_eSlideDir = eSlideDir_None;
	}
	else if (eSlideDir_None!=m_eSlideDir)
	{
		if (isTouchEnabled())
		{
			CCPoint delta = _touchMovedPoint - _touchBeganPoint;

			static const float fDelatPosX = 30;
			if (delta.x<-fDelatPosX && m_pDelegate->getTotalItemNum()>(m_nCurrentPage+1)*m_pDelegate->getEveryPageItemNum())
			{
				m_eSlideDir = eSlideDir_Horizon_Left;
				scheduleOnce( schedule_selector(WidgetSlideListView::scheduleTurnPage),0);
			}
			else if (delta.x>fDelatPosX && m_nCurrentPage>0)
			{
				m_eSlideDir = eSlideDir_Horizon_Right;
				scheduleOnce( schedule_selector(WidgetSlideListView::scheduleTurnPage),0);
			}
			else
			{
				m_eSlideDir = eSlideDir_None;
				_innerContainer->setPosition(m_BackPos);
			}
		}
	}

}

void WidgetSlideListView::turnToPage(unsigned int nPage)
{
	bool bRight2Left = m_nCurrentPage<=nPage;
	m_nCurrentPage=nPage;
	reloadData();
	doEaseIn(bRight2Left);
	m_pDelegate->onPageTurnOver(m_nCurrentPage);
}

void WidgetSlideListView::scheduleTurnPage(float t)
{
	if (eSlideDir_Horizon_Left==m_eSlideDir)
	{
		turnToPage(m_nCurrentPage+1);
	}
	else if (eSlideDir_Horizon_Right==m_eSlideDir)
	{
		turnToPage(m_nCurrentPage-1);
	}

	m_eSlideDir = eSlideDir_None;
}

  

 

posted @ 2014-01-26 14:30  MrBlue  阅读(1607)  评论(0编辑  收藏  举报