首页 > 技术文章 > CCScrollView练习

yu-chao 2014-04-06 23:18 原文

MyScrollItem是CCScrollView容器内项的接口,MyScrollView主要处理添加子节点和事件的处理,MyScrollViewTestItem是对MyScrollItem实现的测试项,MyScrollViewTest测试类

/*MyScrollView.h*/
#ifndef _MY_SCROLL_VIEW_
#define _MY_SCROLL_VIEW_
#include "cocos2d.h"
#include "CCScrollView.h"
#include "ExtensionMacros.h"
using namespace cocos2d;
USING_NS_CC_EXT;
class MyScrollItem : public CCNode
{
public:
    bool isSelected(CCTouch* pTouch);
    void touched();
    virtual bool init(CCSize size);
    virtual void selected()=0;
};
class MyScrollView  : public CCLayer,public CCScrollViewDelegate
{
private:
    CCScrollView* m_pScrollView;
    CCNode* m_pContainer;
    CCSize m_itemSize;
    bool m_isScrolling;
public:
    MyScrollView();
    static MyScrollView* create(CCPoint pos,CCSize viewSize,CCScrollViewDirection dir);
    bool init(CCPoint pos,CCSize viewSize,CCScrollViewDirection dir);
    void addItem(MyScrollItem* item);
    virtual void registerWithTouchDispatcher();
    virtual bool ccTouchBegan(CCTouch* pTouch,CCEvent* pEvent);
    virtual void ccTouchMoved(CCTouch* pTouch,CCEvent* pEvent);
    virtual void ccTouchEnded(CCTouch* pTouch,CCEvent* pEvent);
    virtual void scrollViewDidScroll(CCScrollView* view);
    virtual void scrollViewDidZoom(CCScrollView* view);
    virtual void draw();
};
#endif

/*MyScrollView.cpp*/

#include "cocos2d.h"
#include "CCScrollView.h"
#include "MyScrollView.h"
#include <stdio.h>
using namespace cocos2d;
using namespace cocos2d::extension;

bool MyScrollItem::isSelected(CCTouch* pTouch)
{
    CCPoint touch = this->convertTouchToNodeSpace(pTouch);
    CCSize size = this->boundingBox().size;   // boundingBox()返回的是当前节点经过缩放旋转后在本地坐标的矩形
    return CCRect(0,0,size.width,size.height).containsPoint(touch);
}
bool MyScrollItem::init(CCSize size)
{
    if(!CCNode::init()) return false;
    this->setContentSize(size);
    return true;
}
void MyScrollItem::touched()
{
    this->stopAllActions();
    CCScaleTo* scaleTo1 = CCScaleTo::create(0.1f,0.9f);
    CCScaleTo* scaleTo2 = CCScaleTo::create(0.1f,1.0f);
    this->runAction(CCSequence::create(scaleTo1,scaleTo2,NULL));
}


MyScrollView::MyScrollView(){}
MyScrollView* MyScrollView::create(CCPoint pos,CCSize viewSize,CCScrollViewDirection dir)
{
    MyScrollView* scrollview = new MyScrollView();
    if(scrollview && scrollview->init(pos,viewSize,dir))
    {
        scrollview->autorelease();
        return scrollview;
    }
    return NULL;
}

bool MyScrollView::init(CCPoint pos,CCSize viewSize,CCScrollViewDirection dir)
{
    if(!CCLayer::init()) return false;
    m_pScrollView = CCScrollView::create(viewSize);
    m_pContainer = CCNode::create();
    m_pScrollView->setBounceable(false);//设置弹性效果
    m_pScrollView->setContainer(m_pContainer);//设置容器
    m_pScrollView->setTouchPriority(-1);//设置优先级
    m_pScrollView->setTouchEnabled(true);//设置可触摸
    m_pScrollView->setDirection(dir); //设置方向
    m_pScrollView->setDelegate(this); //设置代理
    
    m_pScrollView->setPosition(ccp(0,0));

    /*CCLayerColor* layer = CCLayerColor::create(ccc4(255,0,0,255),viewSize.width,viewSize.height);
    layer->setPosition(pos);
    this->addChild(layer,1,100);*/

    this->addChild(m_pScrollView);
    this->setTouchEnabled(true);
    this->setPosition(pos);
    return true;
}
void MyScrollView::registerWithTouchDispatcher()
{
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
void MyScrollView::addItem(MyScrollItem* item)
{
    CCPoint pos;
    int count = m_pContainer->getChildrenCount();
    item->ignoreAnchorPointForPosition(false);
    item->setAnchorPoint(ccp(0.5f,0.5f));
    if(count)
    {
        CCNode* endItem = m_pContainer->getChildByTag(count-1);
        pos = ccp(endItem->getPositionX()+m_itemSize.width,endItem->getPositionY());
    }
    else
    {
        if(m_itemSize.width==0 || m_itemSize.height==0) m_itemSize = item->getContentSize();
        pos = ccp(m_itemSize.width/2,m_itemSize.height/2);
    }
    item->setPosition(pos);
    m_pContainer->setContentSize(CCSizeMake(m_itemSize.width*(count+1),m_itemSize.height));
    m_pContainer->addChild(item,1,count);
}
bool MyScrollView::ccTouchBegan(CCTouch* pTouch,CCEvent* pEvent)
{
    m_isScrolling = false;
    if(m_pContainer->getChildrenCount())
    {
        CCPoint touch = m_pContainer->convertTouchToNodeSpace(pTouch);
        MyScrollItem* item = (MyScrollItem*)m_pContainer->getChildByTag(touch.x/m_itemSize.width);
        if(item && item->isSelected(pTouch))
        {
            item->touched();
            return true;
        }
    }
    return false;
}
void MyScrollView::ccTouchMoved(CCTouch* pTouch,CCEvent* pEvent)
{
    m_isScrolling = true;
}
void MyScrollView::ccTouchEnded(CCTouch* pTouch,CCEvent* pEvent)
{
    if(!m_isScrolling)
    {
        CCPoint touch = m_pContainer->convertTouchToNodeSpace(pTouch);
        MyScrollItem* item = (MyScrollItem*)m_pContainer->getChildByTag(touch.x/m_itemSize.width);
        item->selected();
    }
}
void MyScrollView::scrollViewDidScroll(CCScrollView* view)
{
    char str[256];
    sprintf(str,"pos=(%d,%d)\n",m_pContainer->getPositionX(),m_pContainer->getPositionY());
    OutputDebugString(str);
}
void MyScrollView::scrollViewDidZoom(CCScrollView* view)
{
}
void MyScrollView::draw()
{
    CCLayer::draw();
    //int count = m_pContainer->getChildrenCount();
    //m_pContainer->setPosition(ccp(0,0));
}
/*ScrollViewTest.h*/
#ifndef _SCROLLVIEW_TEST_
#define _SCROLLVIEW_TEST_
#include "cocos2d.h"
USING_NS_CC;
#include"MyScrollView.h"
class MyScrollViewTestItem : public MyScrollItem
{
public:
    static MyScrollViewTestItem* create(CCSize size);
    virtual bool init(CCSize size);
    virtual void selected();
};
class MyScrollViewTest : public CCLayer
{
public:
    CREATE_FUNC(MyScrollViewTest);
    bool init();
};
#endif
/*ScrollViewTest.cpp*/
#include "cocos2d.h"
#include "ScrollViewTest.h"
#include "MyScrollView.h"
#include <iostream>
using namespace std;
MyScrollViewTestItem* MyScrollViewTestItem::create(CCSize size)
{
    MyScrollViewTestItem* item = new MyScrollViewTestItem();
    if(item && item->init(size))
    {
        item->autorelease();
        return item;
    }
    CC_SAFE_DELETE(item);
    return NULL;
}
bool MyScrollViewTestItem::init(CCSize size)
{
    if(!MyScrollItem::init(size)) return false;
    CCSprite* sprite = CCSprite::create("1.png");
    sprite->setPosition(ccp(size.width/2,size.height/2));
    this->addChild(sprite);
    return true;
}
void MyScrollViewTestItem::selected()
{
    char str[256];
    sprintf(str,"selected tag = %d\n",this->getTag());
    OutputDebugString(str);
}
bool MyScrollViewTest::init()
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    CCSize viewSize = CCSizeMake(400,100);
    CCPoint pos = ccp(0,0);
    CCSize itemSize = CCSizeMake(100,100);
    MyScrollView* myScroll = MyScrollView::create(ccp(300,100),viewSize,kCCScrollViewDirectionHorizontal);
    for(int i=0;i<10;i++)
    {
        MyScrollViewTestItem* item = MyScrollViewTestItem::create(itemSize);
        myScroll->addItem(item);
    }
    this->addChild(myScroll);
    this->setPosition(pos);
    return true;
}
/*添加几个cocos2dx函数源码*/
void CCScrollView::addChild(CCNode * child, int zOrder, int tag)
{
    child->ignoreAnchorPointForPosition(false);
    child->setAnchorPoint(ccp(0.0f, 0.0f));
    if (m_pContainer != child) {
        m_pContainer->addChild(child, zOrder, tag);
    } else {
        CCLayer::addChild(child, zOrder, tag);
    }
}
由此可以看出CCScrollView中只有m_pContainer一个子节点,向CCScrollView中添加节点也就是向m_pContainer节点。
void CCScrollView::setContentSize(const CCSize & size)
{
    if (this->getContainer() != NULL)
    {
        this->getContainer()->setContentSize(size);
        this->updateInset();
    }
}
由此看出CCScrollView设置内容大小其实就是设置容器大小
void CCScrollView::setContainer(CCNode * pContainer)
{
    this->removeAllChildrenWithCleanup(true);
    if (!pContainer) return;
    this->m_pContainer = pContainer;
    this->m_pContainer->ignoreAnchorPointForPosition(false);
    this->m_pContainer->setAnchorPoint(ccp(0.0f, 0.0f));
    this->addChild(this->m_pContainer);
    this->setViewSize(this->m_tViewSize);
}
由此看出CCScrollView添加容器时删除了自己的其他所有子节点
void CCScrollView::setViewSize(CCSize size)
{
    m_tViewSize = size;
    CCLayer::setContentSize(size);
}
setViewSize才是设置CCScrollView本身的大小

 

推荐阅读