使用事例

class testScene:public CCLayer,public extension::CCScrollViewDelegate //可以自写触摸回调
{
    extension::CCScrollView *scrollView;
public:
    virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view);
    virtual void scrollViewDidZoom(cocos2d::extension::CCScrollView* view);
public:
    virtual bool init();
    CREATE_FUNC(testScene);
    static CCScene* scene();
    
    //virtual void registerWithTouchDispatcher();
    virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch,CCEvent *pEvent);
    virtual void adjustScrollView();
    virtual void onEnter();
};



bool testScene::init()

{


   if ( !CCLayer::init() )

    {

        return false;

    }

    CCScrollView* scrollView = CCScrollView::create();

    CCLayer *continerLayer = CCLayer::create();

    

    continerLayer->setAnchorPoint(CCPointZero);

    continerLayer->setPosition(CCPointZero);

   

    scrollView->setAnchorPoint(CCPointZero);

    scrollView->setPosition(CCPointZero);

    

    scrollView->setViewSize(CCSizeMake(900, 600));  //显示的区域(在窗口裁剪一块显示滚动layer) "this->"CCLayer::setContentSize(size);

    

    CCSprite* pSprite = CCSprite::create("HelloWorld.png");

    pSprite->setAnchorPoint(CCPointZero);

    //pSprite->setContentSize(ccp(900,600));//并不能让图片放大到屏幕大小对于sprite这个函数无意义(仅在最开始根据图片大小设置一下contentsize并且不随scale变化) getcontentsize得到精灵图片大小

参考->         boundingBox getContentSize         

    continerLayer->addChild(pSprite, 0,2);

     

    //scrollView->setContentSize(CCSizeMake(1000, 600));

    scrollView->setContainer(continerLayer);

       continerLayer->setContentSize(CCSizeMake(1000600)); //与下一句等效  滑动层的总大小 即可滑动范围

    //continerLayer->setPosition(100,0);

    scrollView->setContentOffsetInDuration(ccp(100,0),1);//设置偏移量(同上句) 并在1秒内移动到该偏移量位置  //这个偏移量其实就是continerLayer左下点相对于可视区域的左下点的坐标

 

   ///scrollView->setZoomScaleInDuration(2,-1);//小于1时相当于调用setZoomScale 因为初始化时   m_fMinScale = m_fMaxScale = 1.0f;所以此句无效 会崩。。

  // scrollView->setBounceable(false); //是否反弹

       this->addChild(scrollView);

    

scrollView->setDelegate(this);//触摸回调


    this->addChild(scrollView);


    return true;

}






#ifndef __CCSCROLLVIEW_H__

#define __CCSCROLLVIEW_H__


#include "cocos2d.h"

#include "ExtensionMacros.h"


NS_CC_EXT_BEGIN


/**

 * @addtogroup GUI

 * @{

 */


typedef enum {

kCCScrollViewDirectionNone = -1,//无法滑动

    kCCScrollViewDirectionHorizontal = 0,//水平滑动

    kCCScrollViewDirectionVertical, //垂直滑动

    kCCScrollViewDirectionBoth  //自由滑动

} CCScrollViewDirection;


class CCScrollView;


class CCScrollViewDelegate//监听滑动 组合方式(而非继承)由CCScrollView使用

{

public:

    virtual ~CCScrollViewDelegate() {}

    virtual void scrollViewDidScroll(CCScrollView* view) = 0;// 滑动时调用

    virtual void scrollViewDidZoom(CCScrollView* view) = 0;//缩放时调用

};



/**

 * ScrollView support for cocos2d for iphone.

 * It provides scroll view functionalities to cocos2d projects natively.

 */

class CCScrollView : public CCLayer

{

public:

    CCScrollView();

    virtual ~CCScrollView();


    virtual void registerWithTouchDispatcher();//在触摸调度器中注册 滚动层

/

void CCScrollView::registerWithTouchDispatcher()

{

    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, CCLayer::getTouchPriority(), false);

}

/

    static CCScrollView* create(CCSize size, CCNode* container = NULL);  //创建滚动层 1、可视大小  2、父节点

   

    static CCScrollView* create();

   

    bool init();

//

bool CCScrollView::init()

{

    return this->initWithViewSize(CCSizeMake(200, 200), NULL);

}

/


    bool initWithViewSize(CCSize size, CCNode* container = NULL);

//

bool CCScrollView::initWithViewSize(CCSize size, CCNode *container/* = NULL*/)

{

    if (CCLayer::init())

    {

        m_pContainer = container;

        

        if (!this->m_pContainer)

        {

            m_pContainer = CCLayer::create();

            this->m_pContainer->ignoreAnchorPointForPosition(false);

            this->m_pContainer->setAnchorPoint(ccp(0.0f, 0.0f));

        }


        this->setViewSize(size);


        setTouchEnabled(true);

        m_pTouches = new CCArray();

        m_pDelegate = NULL;

        m_bBounceable = true;

        m_bClippingToBounds = true;

        //m_pContainer->setContentSize(CCSizeZero);

        m_eDirection  = kCCScrollViewDirectionBoth;

        m_pContainer->setPosition(ccp(0.0f, 0.0f));

        m_fTouchLength = 0.0f;

        

        this->addChild(m_pContainer);

        m_fMinScale = m_fMaxScale = 1.0f;

        return true;

    }

    return false;

}


/



    void setContentOffset(CCPoint offset, bool animated = false);//设置滚动内容偏移量

void CCScrollView::setContentOffset(CCPoint offset, bool animated/* = false*/)

{

    if (animated)

    { //animate scrolling

        this->setContentOffsetInDuration(offset, BOUNCE_DURATION);

    } 

    else

    { //set the container position directly

        if (!m_bBounceable)

        {

            const CCPoint minOffset = this->minContainerOffset();

            const CCPoint maxOffset = this->maxContainerOffset();

            

            offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x));

            offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y));

        }

        m_pContainer->setPosition(offset);

        if (m_pDelegate != NULL)

        {

            m_pDelegate->scrollViewDidScroll(this);   

        }

    }

}

/

    CCPoint getContentOffset();


    void setContentOffsetInDuration(CCPoint offset, float dt);//

///

void CCScrollView::setContentOffsetInDuration(CCPoint offset, float dt)

{

    CCFiniteTimeAction *scroll, *expire;

    

    scroll = CCMoveTo::create(dt, offset);

    expire = CCCallFuncN::create(this, callfuncN_selector(CCScrollView::stoppedAnimatedScroll));

    m_pContainer->runAction(CCSequence::create(scroll, expire, NULL));

    this->schedule(schedule_selector(CCScrollView::performedAnimatedScroll));

}


//


    void setZoomScale(float s);//

void CCScrollView::setZoomScale(float s)

{

    if (m_pContainer->getScale() != s)

    {

        CCPoint oldCenter, newCenter;

        CCPoint center;

        

        if (m_fTouchLength == 0.0f) 

        {

            center = ccp(m_tViewSize.width*0.5f, m_tViewSize.height*0.5f);

            center = this->convertToWorldSpace(center);

        }

        else

        {

            center = m_tTouchPoint;

        }

        

        oldCenter = m_pContainer->convertToNodeSpace(center);

        m_pContainer->setScale(MAX(m_fMinScale, MIN(m_fMaxScale, s)));

        newCenter = m_pContainer->convertToWorldSpace(oldCenter);

        

        const CCPoint offset = ccpSub(center, newCenter);

        if (m_pDelegate != NULL)

        {

            m_pDelegate->scrollViewDidZoom(this);

        }

        this->setContentOffset(ccpAdd(m_pContainer->getPosition(),offset));

    }

}


//

    /*** Sets a new scale and does that for a predefined(预定义) duration. */

    void setZoomScale(float s, bool animated);//


    float getZoomScale();//


    /*** Sets a new scale for container in a given duration.*/

    void setZoomScaleInDuration(float s, float dt);

//

void CCScrollView::setZoomScaleInDuration(float s, float dt)

{

    if (dt > 0)

    {

        if (m_pContainer->getScale() != s)

        {

            CCActionTween *scaleAction;

            scaleAction = CCActionTween::create(dt, "zoomScale", m_pContainer->getScale(), s);

            this->runAction(scaleAction);

        }

    }

    else

    {

        this->setZoomScale(s);

    }

}


    /*** Returns the current container's minimum offset. You may want this while you animate scrolling by yourself*/

    CCPoint minContainerOffset();

    /*** Returns the current container's maximum offset. You may want this while you animate scrolling by yourself*/

    CCPoint maxContainerOffset(); 

    /**

     * Determines(确定) if(是否) a given node's bounding(边框) box is in visible bounds

     */

    bool isNodeVisible(CCNode * node);  //

///

bool CCScrollView::isNodeVisible(CCNode* node)

{

    const CCPoint offset = this->getContentOffset();    //这个偏移量其实就是起始点

    const CCSize  size   = this->getViewSize();

    const float   scale  = this->getZoomScale();

    

    CCRect viewRect;

    

    viewRect = CCRectMake(-offset.x/scale, -offset.y/scale, size.width/scale, size.height/scale); 

    

    return viewRect.intersectsRect(node->boundingBox()); //是否相交

}

    /**

     * Provided(提供) to make scroll view compatible(兼容) with SWLayer's pause method

     */

    void pause(CCObject* sender);

///

void CCScrollView::pause(CCObject* sender)

{

    m_pContainer->pauseSchedulerAndActions();

    CCObject* pObj = NULL;

    CCArray* pChildren = m_pContainer->getChildren();

    CCARRAY_FOREACH(pChildren, pObj)

    {

        CCNode* pChild = (CCNode*)pObj;

        pChild->pauseSchedulerAndActions();

    }

}

/


    void resume(CCObject* sender);



    bool isDragging() {return m_bDragging;} //Dragging 拖曳用的

    bool isTouchMoved() { return m_bTouchMoved; }

    bool isBounceable() { return m_bBounceable; }//反弹

    void setBounceable(bool bBounceable) { m_bBounceable = bBounceable; }


//可视大小

    CCSize getViewSize() { return m_tViewSize; }  //

    void setViewSize(CCSize size);


    CCNode * getContainer();//

    void setContainer(CCNode * pContainer);



    CCScrollViewDirection getDirection() { return m_eDirection; }  //可滑动方向设置

    virtual void setDirection(CCScrollViewDirection eDirection) { m_eDirection = eDirection; }


    CCScrollViewDelegate* getDelegate() { return m_pDelegate; }

    void setDelegate(CCScrollViewDelegate* pDelegate) { m_pDelegate = pDelegate; } //设置滑动协议来监听滑动


    /** override functions */   //重写触摸回调

    // optional

    virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

//

bool CCScrollView::ccTouchBegan(CCTouch* touch, CCEvent* event)

{

    if (!this->isVisible())

    {

        return false;

    }

    

    CCRect frame = getViewRect();

    //dispatcher does not know about clipping. reject touches outside visible bounds.

    if (m_pTouches->count() > 2 ||

        m_bTouchMoved          ||

        !frame.containsPoint(m_pContainer->convertToWorldSpace(m_pContainer->convertTouchToNodeSpace(touch))))

    {

        return false;

    }

    if (!m_pTouches->containsObject(touch))

    {

        m_pTouches->addObject(touch);

    }

    if (m_pTouches->count() == 1)

    { // scrolling

        m_tTouchPoint     = this->convertTouchToNodeSpace(touch);

        m_bTouchMoved     = false;

        m_bDragging     = true; //dragging started

        m_tScrollDistance = ccp(0.0f, 0.0f);

        m_fTouchLength    = 0.0f;

    }

    else if (m_pTouches->count() == 2)

    {

        m_tTouchPoint  = ccpMidpoint(this->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(0)),

                                   this->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(1)));

        m_fTouchLength = ccpDistance(m_pContainer->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(0)),

                                   m_pContainer->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(1)));

        m_bDragging  = false;

    } 

    return true;

}



/

    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);

void CCScrollView::ccTouchMoved(CCTouch* touch, CCEvent* event)

{

    if (!this->isVisible())

    {

        return;

    }

    if (m_pTouches->containsObject(touch))

    {

        if (m_pTouches->count() == 1 && m_bDragging)

        { // scrolling

            CCPoint moveDistance, newPoint, maxInset, minInset;

            CCRect  frame;

            float newX, newY;

            

            frame = getViewRect();

            newPoint     = this->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(0));

            moveDistance = ccpSub(newPoint, m_tTouchPoint);

            

            float dis = 0.0f;

            if (m_eDirection == kCCScrollViewDirectionVertical)

            {

                dis = moveDistance.y;

            }

            else if (m_eDirection == kCCScrollViewDirectionHorizontal)

            {

                dis = moveDistance.x;

            }

            else

            {

                dis = sqrtf(moveDistance.x*moveDistance.x + moveDistance.y*moveDistance.y);

            }

            if (!m_bTouchMoved && fabs(convertDistanceFromPointToInch(dis)) < MOVE_INCH )

            {

                //CCLOG("Invalid movement, distance = [%f, %f], disInch = %f", moveDistance.x, moveDistance.y);

                return;

            }

            

            if (!m_bTouchMoved)

            {

                moveDistance = CCPointZero;

            }

            

            m_tTouchPoint = newPoint;

            m_bTouchMoved = true;

            

            if (frame.containsPoint(this->convertToWorldSpace(newPoint)))

            {

                switch (m_eDirection)

                {

                    case kCCScrollViewDirectionVertical:

                        moveDistance = ccp(0.0f, moveDistance.y);

                        break;

                    case kCCScrollViewDirectionHorizontal:

                        moveDistance = ccp(moveDistance.x, 0.0f);

                        break;

                    default:

                        break;

                }

                

                maxInset = m_fMaxInset;

                minInset = m_fMinInset;

                newX     = m_pContainer->getPosition().x + moveDistance.x;

                newY     = m_pContainer->getPosition().y + moveDistance.y;

                m_tScrollDistance = moveDistance;

                this->setContentOffset(ccp(newX, newY));

            }

        }

        else if (m_pTouches->count() == 2 && !m_bDragging)

        {

            const float len = ccpDistance(m_pContainer->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(0)),

                                            m_pContainer->convertTouchToNodeSpace((CCTouch*)m_pTouches->objectAtIndex(1)));

            this->setZoomScale(this->getZoomScale()*len/m_fTouchLength);

        }

    }

}

/

    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

/

void CCScrollView::ccTouchEnded(CCTouch* touch, CCEvent* event)

{

    if (!this->isVisible())

    {

        return;

    }

    if (m_pTouches->containsObject(touch))

    {

        if (m_pTouches->count() == 1 && m_bTouchMoved)

        {

           this->schedule(schedule_selector(CCScrollView::deaccelerateScrolling));

        }

        m_pTouches->removeObject(touch);

    } 

    if (m_pTouches->count() == 0)

    {

        m_bDragging = false;    

        m_bTouchMoved = false;

    }

}

/

    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);


    virtual void setContentSize(const CCSize & size); //设置ContentSize

    virtual const CCSize& getContentSize() const;


void updateInset();

void CCScrollView::updateInset()

{

if (this->getContainer() != NULL)

{

m_fMaxInset = this->maxContainerOffset();

m_fMaxInset = ccp(m_fMaxInset.x + m_tViewSize.width * INSET_RATIO,

m_fMaxInset.y + m_tViewSize.height * INSET_RATIO);

m_fMinInset = this->minContainerOffset();

m_fMinInset = ccp(m_fMinInset.x - m_tViewSize.width * INSET_RATIO,

m_fMinInset.y - m_tViewSize.height * INSET_RATIO);

}

}

/


    /**

     * Determines whether it clips(修剪) its children or not.

     */

    bool isClippingToBounds() { return m_bClippingToBounds; }

    void setClippingToBounds(bool bClippingToBounds) { m_bClippingToBounds = bClippingToBounds; }


    virtual void visit();

    virtual void addChild(CCNode * child, int zOrder, int tag);

    virtual void addChild(CCNode * child, int zOrder);

    virtual void addChild(CCNode * child);

    void setTouchEnabled(bool e);

private: //以下是私有的 内部调用 外部用不到所以知道即可


    void relocateContainer(bool animated);//根据max/min 偏移量重设位置

    /**

     * implements(实施 执行) auto-scrolling behavior. change SCROLL_DEACCEL_RATE as needed to choose

     * deceleration(减(速)) speed. it must be less than 1.0f.

     */

    void deaccelerateScrolling(float dt); //设置减速滚动

//

void CCScrollView::deaccelerateScrolling(float dt)

{

    if (m_bDragging)

    {

        this->unschedule(schedule_selector(CCScrollView::deaccelerateScrolling));

        return;

    }

    

    float newX, newY;

    CCPoint maxInset, minInset;

    

    m_pContainer->setPosition(ccpAdd(m_pContainer->getPosition(), m_tScrollDistance));

    

    if (m_bBounceable)

    {

        maxInset = m_fMaxInset;

        minInset = m_fMinInset;

    }

    else

    {

        maxInset = this->maxContainerOffset();

        minInset = this->minContainerOffset();

    }

    

    //check to see if offset lies within the inset bounds

    newX     = MIN(m_pContainer->getPosition().x, maxInset.x);

    newX     = MAX(newX, minInset.x);

    newY     = MIN(m_pContainer->getPosition().y, maxInset.y);

    newY     = MAX(newY, minInset.y);

    

    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 ((fabsf(m_tScrollDistance.x) <= SCROLL_DEACCEL_DIST &&

         fabsf(m_tScrollDistance.y) <= SCROLL_DEACCEL_DIST) ||

        newY > maxInset.y || newY < minInset.y ||

        newX > maxInset.x || newX < minInset.x ||

        newX == maxInset.x || newX == minInset.x ||

        newY == maxInset.y || newY == minInset.y)

    {

        this->unschedule(schedule_selector(CCScrollView::deaccelerateScrolling));

        this->relocateContainer(true);

    }

}

/

    /**

     * This method makes sure auto scrolling causes delegate to invoke(调用) its method

     */

    void performedAnimatedScroll(float dt);

    /**

     * Expire(终止) animated(活的) scroll delegate calls

     */

    void stoppedAnimatedScroll(CCNode* node);

    /**

     * clip this view so that outside of the visible bounds can be hidden.

     */

    void beforeDraw();

    /**

     * retract what's done in beforeDraw so that there's no side effect to

     * other nodes.

     */

    void afterDraw();

    /**

     * Zoom handling

     */

    void handleZoom();


protected:

    CCRect getViewRect(); //得到view区域

    

    float m_fZoomScale;//当前scale


    float m_fMinZoomScale;//min scale


    float m_fMaxZoomScale;//max scale


    CCScrollViewDelegate* m_pDelegate;//滚动条协议


    CCScrollViewDirection m_eDirection;


    bool m_bDragging;


 

    CCPoint m_tContentOffset;


    CCNode* m_pContainer;


    bool m_bTouchMoved;

    /**

     * max inset(插入) point to limit scrolling by touch

     */

    CCPoint m_fMaxInset;  //滚动触摸最大范围

    /**

     * min inset point to limit scrolling by touch

     */

    CCPoint m_fMinInset;//滚动触摸最小范围


    bool m_bBounceable;//是否反弹


    bool m_bClippingToBounds;//


    /**

     * scroll speed

     */

    CCPoint m_tScrollDistance;  //滚动速度


    CCPoint m_tTouchPoint;  //触摸点


    float m_fTouchLength;  //两指间距

    /**

     * UITouch objects to detect multitouch

     */

    CCArray* m_pTouches;


    CCSize m_tViewSize;///

    /**

     *max and min scale

     */

    float m_fMinScale, m_fMaxScale;

    /**

     * scissor rect for parent, just for restoring GL_SCISSOR_BOX

     */

    CCRect m_tParentScissorRect;//

    bool m_bScissorRestored;/

};


NS_CC_EXT_END


#endif


Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐