• cocos2d-x CCSrollView 源代码,可循环的SrollView代码



    项目须要。写一个类似于iPhone上面时钟选择的可拉动式循环选择列表,通过集成CCScrollView并更改部分代码。实现了该功能。

    假设想充分了解代码,请先阅读源码分析http://blog.csdn.net/u011225840/article/details/30033501

    不考虑重构,这是我写的第一版代码,仅仅考虑了功能性。

    过两天有时间后。我会将该部分代码重构,希望大家作对照~


    #include "cocos2d.h"
    #include "cocos-ext.h"
    
    using namespace cocos2d;
    using namespace cocos2d::extension;
    
    #define SCROLL_DEACCEL_RATE  0.95f
    #define SCROLL_DEACCEL_DIST  1.0f
    enum MovingDirection
    {
    	Left = 1,
    	Right = 2,
    	Up,
    	Down
    };
    
    enum Direction
    {
    	CycleDirectionHorizontal=1,
    	CycleDirectionVertical
    
    };
    
    enum Child	
    {
    	kLeft = 1,
    	kMiddle,
    	kRight
    };
    class CCCycleScrollView: public CCScrollView
    {
    public:
    	CCCycleScrollView();
    	virtual ~CCCycleScrollView();
    
    
    	static CCCycleScrollView* create(const char* spriteFile,Direction direction = CycleDirectionHorizontal);
    
    	bool initWithViewSize(const char* spriteFile ,Direction direction = CycleDirectionHorizontal);
    
    	bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    	void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    	void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    protected:
    	//调整三个sprite的位置
    	void adjustSprite();
    
    	
    	void deaccelerateScrolling(float dt);
    
    	void relocateContainer();
    
    	CCPoint findEndPoint();
    	//有三个一样的sprite来支持循环显示
    	CCSprite* m_sprite1;
    	CCSprite* m_sprite2;
    	CCSprite* m_sprite3;
    
    	//每一个sprite的size
    	CCSize m_spriteSize;
    
    	//上一次触碰点的坐标。用于推断当前移动的方向
    	CCPoint m_lastPoint;
    	//当前触碰点的坐标
    	CCPoint m_nowPoint;
    
    	//当前偏移相应的位置
    	float m_nowPositionNum;
    	//上一次移动后的移动位数
    	int m_lastPositionNum;
    	//上一次正向移动是否移动过
    	bool m_lastPositiveDone;
    	//上一次反向移动是否移动过
    	bool m_lastNegtiveDone;
    	//正在移动的方向
    	MovingDirection m_moving;
    
    	//滚动的限定方向
    	Direction m_direction;
    
    	
    
    	//temp
    	CCLabelTTF* temp1;
    	CCLabelTTF* temp2;
    	CCLabelTTF* temp3;
    	CCLabelTTF* temp4;
    	CCLabelTTF* temp5;
    	CCLabelTTF* temp6;
    	CCLabelTTF* temp7;
    	CCLabelTTF* temp8;
    	CCLabelTTF* temp9;
    
    	void updateTemp();
    
    };
    
    


    #include "CCCycleScrollView.h"
    
    CCCycleScrollView::CCCycleScrollView():
    	m_sprite1(NULL),
    	m_sprite2(NULL),
    	m_sprite3(NULL),
    	m_lastPoint(ccp(0.0f,0.0f)),
    	m_nowPoint(ccp(0.0f,0.0f)),
    	m_lastPositionNum(0),
    	m_lastPositiveDone(false),
    	m_lastNegtiveDone(false)
    {
    
    }
    
    CCCycleScrollView::~CCCycleScrollView()
    {
    
    }
    
    bool CCCycleScrollView::initWithViewSize(const char* spriteFile ,Direction d )
    {
    	if (CCLayer::init())
    	{
    		m_sprite1 = CCSprite::create(spriteFile);
    		m_sprite1->ignoreAnchorPointForPosition(false);
    		m_sprite1->setAnchorPoint(ccp(0.0f,0.0f));
    		CCSize spriteSize = m_sprite1->getContentSize();
    
    		temp1 = CCLabelTTF::create();
    		temp1->setContentSize(CCSizeMake(160,320));
    		temp1->setFontSize(80);
    		temp1->setAnchorPoint(ccp(0.5f,0.0f));
    		temp1->setString("10");
    		temp1->setPosition(ccp(80.0f,0.0f));
    		temp1->setTag(kLeft);
    		m_sprite1->addChild(temp1);
    
    		 temp2 = CCLabelTTF::create();
    		temp2->setContentSize(CCSizeMake(160,320));
    		temp2->setFontSize(80);
    		temp2->setAnchorPoint(ccp(0.5f,0.0f));
    		temp2->setString("11");
    		temp2->setPosition(ccp(240.f,0.0f));
    		temp2->setTag(kMiddle);
    		m_sprite1->addChild(temp2);
    
    		temp3 = CCLabelTTF::create();
    		temp3->setContentSize(CCSizeMake(160,320));
    		temp3->setFontSize(80);
    		temp3->setAnchorPoint(ccp(0.5f,0.0f));
    		temp3->setString("12");
    		temp3->setPosition(ccp(400.0f,0.0f));
    		temp3->setTag(kRight);
    		m_sprite1->addChild(temp3);
    
    
    		m_sprite2 = CCSprite::create(spriteFile);
    		m_sprite2->ignoreAnchorPointForPosition(false);
    		m_sprite2->setAnchorPoint(ccp(0.0f,0.0f));
    		
    		 temp4 = CCLabelTTF::create();
    		temp4->setContentSize(CCSizeMake(160,320));
    		temp4->setFontSize(80);
    		temp4->setAnchorPoint(ccp(0.5f,0.0f));
    		temp4->setString("1");
    		temp4->setPosition(ccp(80.0f,0.0f));
    		temp4->setTag(kLeft);
    		m_sprite2->addChild(temp4);
    
    		 temp5 = CCLabelTTF::create();
    		temp5->setContentSize(CCSizeMake(160,320));
    		temp5->setFontSize(80);
    		temp5->setAnchorPoint(ccp(0.5f,0.0f));
    		temp5->setString("2");
    		temp5->setPosition(ccp(240.0f,0.0f));
    		temp5->setTag(kMiddle);
    		m_sprite2->addChild(temp5);
    
    		 temp6 = CCLabelTTF::create();
    		temp6->setContentSize(CCSizeMake(160,320));
    		temp6->setFontSize(80);
    		temp6->setAnchorPoint(ccp(0.5f,0.0f));
    		temp6->setString("3");
    		temp6->setPosition(ccp(400.0f,0.0f));
    		temp6->setTag(kRight);
    		m_sprite2->addChild(temp6);
    
    		m_sprite3 = CCSprite::create(spriteFile);
    		m_sprite3->ignoreAnchorPointForPosition(false);
    		m_sprite3->setAnchorPoint(ccp(0.0f,0.0f));
    		
    		 temp7 = CCLabelTTF::create();
    		temp7->setContentSize(CCSizeMake(160,320));
    		temp7->setFontSize(80);
    		temp7->setAnchorPoint(ccp(0.5f,0.0f));
    		temp7->setString("4");
    		temp7->setPosition(ccp(80.f,0.0f));
    		temp7->setTag(kLeft);
    		m_sprite3->addChild(temp7);
    
    		 temp8 = CCLabelTTF::create();
    		temp8->setContentSize(CCSizeMake(160,320));
    		temp8->setFontSize(80);
    		temp8->setAnchorPoint(ccp(0.5f,0.0f));
    		temp8->setString("5");
    		temp8->setPosition(ccp(240.0f,0.0f));
    		temp8->setTag(kMiddle);
    		m_sprite3->addChild(temp8);
    
    		 temp9 = CCLabelTTF::create();
    		temp9->setContentSize(CCSizeMake(160,320));
    		temp9->setFontSize(80);
    		temp9->setAnchorPoint(ccp(0.5f,0.0f));
    		temp9->setString("6");
    		temp9->setPosition(ccp(400.0f,0.0f));
    		temp9->setTag(kRight);
    		m_sprite3->addChild(temp9);
    
    		if (d==CycleDirectionHorizontal)
    		{
    			m_sprite1->setPosition(ccp(-spriteSize.width,0.0f));
    			m_sprite2->setPosition(ccp(0.0f,0.0f));
    			m_sprite3->setPosition(ccp(spriteSize.width,0.0f));
    			m_eDirection  = kCCScrollViewDirectionHorizontal;
    		}
    		else if(d==CycleDirectionVertical)
    		{
    			m_sprite1->setPosition(ccp(0.0f,-spriteSize.height));
    			m_sprite2->setPosition(ccp(0.0f,0.0f));
    			m_sprite3->setPosition(ccp(0.0f,spriteSize.height));
    			m_eDirection = kCCScrollViewDirectionVertical;
    		}
    		
    		
    
    		
    
    		if (!this->m_pContainer)
    		{
    			m_pContainer = CCLayer::create();
    			this->m_pContainer->ignoreAnchorPointForPosition(false);
    			this->m_pContainer->setAnchorPoint(ccp(0.0f, 0.0f));
    			this->m_pContainer->addChild(m_sprite1);
    			this->m_pContainer->addChild(m_sprite2);
    			this->m_pContainer->addChild(m_sprite3);
    		}
    
    		this->setViewSize(CCSizeMake(spriteSize.width,spriteSize.height));
    
    		setTouchEnabled(true);
    		m_pTouches = new CCArray();
    		m_pDelegate = NULL;
    		m_bBounceable = true;
    		m_bClippingToBounds = true;
    		//m_pContainer->setContentSize(CCSizeZero);
    		
    		m_pContainer->setPosition(ccp(0.0f, 0.0f));
    		m_fTouchLength = 0.0f;
    
    		this->addChild(m_pContainer);
    		//setContentOffset(ccp(-spriteSize.width,0));
    		/*
    		m_fMaxInset = ccp(spriteSize.width*300,0);
    		m_fMinInset = ccp(-spriteSize.width*300,0);
    		m_bBounceable = true;
    		*/
    
    		m_fMinScale = m_fMaxScale = 1.0f;
    		m_spriteSize = spriteSize;
    		m_direction = d;
    		return true;
    	}
    	return false;
    }
    
    CCCycleScrollView* CCCycleScrollView::create( const char* spriteFile ,Direction d)
    {
    	CCCycleScrollView* pRet = new CCCycleScrollView();
    	if (pRet && pRet->initWithViewSize(spriteFile,d))
    	{
    		pRet->autorelease();
    	}
    	else
    	{
    		CC_SAFE_DELETE(pRet);
    	}
    	return pRet;
    }
    
    void CCCycleScrollView::ccTouchEnded( CCTouch *pTouch, CCEvent *pEvent )
    {
    	
    	if (!this->isVisible())
    	{
    		return;
    	}
    	
    	if (m_pTouches->count()==1)
    	{
    		this->schedule(schedule_selector(CCCycleScrollView::deaccelerateScrolling));
    	}
    	
    	m_pTouches->removeObject(pTouch);
    
    	//没有touch时。须要设置状态
    	if (m_pTouches->count() == 0)
    	{
    		m_bDragging = false;    
    		m_bTouchMoved = false;
    		
    	}
    	
    }
    
    void CCCycleScrollView::ccTouchMoved( CCTouch *pTouch, CCEvent *pEvent )
    {
    	CCScrollView::ccTouchMoved(pTouch,pEvent);
    
    	
    	m_nowPoint =   convertToWorldSpace(convertTouchToNodeSpace(pTouch));
    	CCLog("The last point is %f",m_lastPoint.x);
    	CCLog("The now point is %f",m_nowPoint.x);
    
    	if (m_direction==CycleDirectionHorizontal)
    	{
    
    		if (m_nowPoint.x>m_lastPoint.x)
    		{
    			m_moving = Right;
    			m_lastPoint = m_nowPoint;
    		}
    		else
    		{
    			m_moving= Left;
    			m_lastPoint = m_nowPoint;
    		}
    		m_nowPositionNum = m_pContainer->getPositionX() / m_spriteSize.width;
    		//CCLog("The nowNum is %d",nowPositionNum);
    		CCLog("The offset is %f",m_pContainer->getPositionX());
    		CCLog("The 1 is %f",m_sprite1->getPositionX());
    		CCLog("The 2 is %f",m_sprite2->getPositionX());
    		CCLog("The 3 is %f",m_sprite3->getPositionX());
    		CCLog("The move is %d",m_moving);
    	}else if (m_direction==CycleDirectionVertical)
    	{
    		if (m_nowPoint.y>m_lastPoint.y)
    		{
    			m_moving = Up;
    			m_lastPoint = m_nowPoint;
    		}
    		else
    		{
    			m_moving= Down;
    			m_lastPoint = m_nowPoint;
    		}
    		m_nowPositionNum = m_pContainer->getPositionY() / m_spriteSize.height;
    	}
    		
    
    
    
    	adjustSprite();
    	
    
    
    	
    }
    
    bool CCCycleScrollView::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent )
    {
    	bool result = CCScrollView::ccTouchBegan(pTouch,pEvent);
    	m_lastPoint = convertToWorldSpace(convertTouchToNodeSpace(pTouch));
    	CCLog("The last point is %f",m_lastPoint.x);
    	if (m_pTouches->count()>1)
    	{
    		return false;
    	}
    	return result;
    }
    
    void CCCycleScrollView::adjustSprite()
    {
    
    	//正在向右移动
    
    	if (m_direction==CycleDirectionHorizontal)
    	{
    		if (m_moving==Right)
    		{
    			if (m_nowPositionNum-m_lastPositionNum>0.5)
    			{
    				m_lastPositiveDone=true;
    				m_lastPositionNum++;
    			}
    			//
    			if (m_lastPositiveDone)
    			{
    				m_sprite3->setPosition(ccp(m_sprite3->getPositionX()-m_spriteSize.width*3,0));
    				
    				CCSprite* temp = m_sprite3;
    				m_sprite3 = m_sprite2;
    				m_sprite2 = m_sprite1;
    				m_sprite1 = temp;
    				updateTemp();
    				m_lastPositiveDone = false;
    				
    			}
    		
    		}
    		else if (m_moving==Left)
    		{
    			if (m_lastPositionNum-m_nowPositionNum>=0.5)
    			{
    				m_lastNegtiveDone=true;
    				m_lastPositionNum--;
    			}
    	
    			if (m_lastNegtiveDone)
    			{
    	
    				m_sprite1->setPosition(ccp(m_sprite1->getPositionX()+m_spriteSize.width*3,0));
    				
    				CCSprite* temp = m_sprite1;
    				m_sprite1 = m_sprite2;
    				m_sprite2 = m_sprite3;
    				m_sprite3 = temp;
    				updateTemp();
    				m_lastNegtiveDone=false;
    			}
    		}
    	}else if (m_direction==CycleDirectionVertical)
    	{
    		if (m_moving==Up)
    		{
    			if (m_nowPositionNum-m_lastPositionNum>0.5)
    			{
    				m_lastPositiveDone=true;
    				m_lastPositionNum++;
    			}
    			
    			if (m_lastPositiveDone)
    			{
    				m_sprite3->setPosition(ccp(0.0f,m_sprite3->getPositionY()-m_spriteSize.height*3));
    				CCSprite* temp = m_sprite3;
    				m_sprite3 = m_sprite2;
    				m_sprite2 = m_sprite1;
    				m_sprite1 = temp;
    				m_lastPositiveDone = false;
    				
    			}
    		
    		}
    		else if (m_moving==Down)
    		{
    			if (m_lastPositionNum-m_nowPositionNum>=0.5)
    			{
    				m_lastNegtiveDone=true;
    				m_lastPositionNum--;
    			}
    	
    			if (m_lastNegtiveDone)
    			{
    	
    				m_sprite1->setPosition(ccp(0.0f,m_sprite1->getPositionY()+m_spriteSize.height*3));
    				CCSprite* temp = m_sprite1;
    				m_sprite1 = m_sprite2;
    				m_sprite2 = m_sprite3;
    				m_sprite3 = temp;
    	
    				m_lastNegtiveDone=false;
    			}
    		}
    	}
    }
    
    void CCCycleScrollView::updateTemp()
    {
    	if (m_moving==Right)
    	{
    		int num = atoi(((CCLabelTTF*)m_sprite2->getChildByTag(kLeft))->getString());
    		if (num-1==0)
    		{
    			num=13;
    		}
    		
    		((CCLabelTTF*)m_sprite1->getChildByTag(kLeft))->setString(CCString::createWithFormat("%d",num-3)->getCString());
    		((CCLabelTTF*)m_sprite1->getChildByTag(kMiddle))->setString(CCString::createWithFormat("%d",num-2)->getCString());
    		((CCLabelTTF*)m_sprite1->getChildByTag(kRight))->setString(CCString::createWithFormat("%d",num-1)->getCString());
    	}
    	else if (m_moving==Left)
    	{
    		int num = atoi(((CCLabelTTF*)m_sprite2->getChildByTag(kRight))->getString());
    		if (num+1==13)
    		{
    			num=0;
    		}
    		((CCLabelTTF*)m_sprite3->getChildByTag(kLeft))->setString(CCString::createWithFormat("%d",num+1)->getCString());
    		((CCLabelTTF*)m_sprite3->getChildByTag(kMiddle))->setString(CCString::createWithFormat("%d",num+2)->getCString());
    		((CCLabelTTF*)m_sprite3->getChildByTag(kRight))->setString(CCString::createWithFormat("%d",num+3)->getCString());
    	}
    }
    
    void CCCycleScrollView::deaccelerateScrolling(float dt)
    {
    
    	//假设刚好在帧開始前 又有一个触摸点发生了began,造成了滚动状态,则取消并返回
        if (m_bDragging)
        {
            this->unschedule(schedule_selector(CCCycleScrollView::deaccelerateScrolling));
            return;
        }
        
    	//好玩的东西来咯
    	
        float newX, newY;
        CCPoint maxInset, minInset;
        //CCLOG("The end distance is %f",m_tScrollDistance.x);
    	//这里我不清楚为啥要出来。我用输出发如今move中。已经将此offset设置过了,不知为何还要设置,求大神解答。
        m_pContainer->setPosition(ccpAdd(m_pContainer->getPosition(), m_tScrollDistance));
        
    	
      
        newX = m_pContainer->getPosition().x;
        newY = m_pContainer->getPosition().y;
        
        m_tScrollDistance     = ccpSub(m_tScrollDistance, ccp(newX - m_pContainer->getPosition().x, newY - m_pContainer->getPosition().y));
        m_tScrollDistance     = ccpMult(m_tScrollDistance, SCROLL_DEACCEL_RATE);
        this->setContentOffset(ccp(newX,newY));
    
    	if (m_direction==CycleDirectionHorizontal)
    	{	
    		m_nowPositionNum = m_pContainer->getPositionX() / m_spriteSize.width;
    		
    	}else if (m_direction==CycleDirectionVertical)
    	{
    		m_nowPositionNum = m_pContainer->getPositionY() / m_spriteSize.height;
    	}
    
    	this->adjustSprite();
        
        if ((fabsf(m_tScrollDistance.x) <= SCROLL_DEACCEL_DIST &&
             fabsf(m_tScrollDistance.y) <= SCROLL_DEACCEL_DIST))
        {
            this->unschedule(schedule_selector(CCCycleScrollView::deaccelerateScrolling));
    		//CCLog("stop!!!!");
    		this->relocateContainer();
        }
    }
    
    void CCCycleScrollView::relocateContainer()
    {
    	
    	//调整位置
    	m_pContainer->setPosition(findEndPoint());
    	if (m_direction==CycleDirectionHorizontal)
    	{	
    		m_nowPositionNum = m_pContainer->getPositionX() / m_spriteSize.width;
    		
    
    	}else if (m_direction==CycleDirectionVertical)
    	{
    		m_nowPositionNum = m_pContainer->getPositionY() / m_spriteSize.height;
    	}
    
    	this->adjustSprite();
    	
    }
    
    cocos2d::CCPoint CCCycleScrollView::findEndPoint()
    {
    	CCPoint nowPoint;
    	nowPoint.x = m_pContainer->getPositionX();
    	
    	float interval = (nowPoint.x)/160;
    	int inter = (int)interval;
    	CCPoint newPoint;
    	if (fabsf(interval-inter)>=0.5)
    	{
    		if (inter<0)
    		{
    			newPoint.x = 160*(inter-1);
    		}
    		else
    		{
    			newPoint.x = 160*(inter+1);
    		}
    		
    	}
    	else
    	{
    		newPoint.x = 160*inter;
    	}
    	CCLog("The final offset is %f",nowPoint.x);
    	CCLog("The float is %f , the int is %d",interval,inter);
    	CCLog("The endpoint is %f",newPoint.x);
    	return ccp(newPoint.x,0.0f);
    }
    
    
    


    未重构的代码有些恶心~~

    准备将重构后的代码再贴出来,并放在github上以供大家下载測试。


  • 相关阅读:
    android: 在android studio中使用retrolambda的步骤
    Shiro基础知识03----shiro授权(编程式授权),Permission详解,授权流程(zz)
    [Android] 关于Android的问号?和@符号的用法
    20170506 《摔跤吧,爸爸》观影笔记
    Android关于log日志,华为不输出log.v,log.d(zz)
    阅读日志:协鑫一年的多晶硅料产能能够生产做少装机容量的组件?
    《周鸿祎自述》读书笔记
    使用promise 和 generator来管理工作流
    读书笔记,《刻意练习》,第三章,心理表征
    读书笔记,《刻意练习》,第四章,黄金标准
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6811217.html
Copyright © 2020-2023  润新知