【转载】cocos2dx基础篇(16)——滚动视图CCScrollView

【唠叨】

    本节要讲讲滚动视图CCScrollView,相信玩过手游的同学们应该对它不会陌生吧。

    例如:愤怒的小鸟的游戏场景里大大的地图,手机的屏幕肯定无法完全显示的,所以需要通过触摸滚动才能显示大地图的其他区域;排行榜中上下滑动来查看其他玩家的排名;以及手机上主界面左右滑动来切换界面等等。

    如下图为屏幕滚动,切换手机的界面。

wKioL1P7LHGh4r-zAAEl3irSbeQ272.gif

【致谢】

    http://blog.csdn.net/paea_gulang/article/details/10283601

【Demo下载】

    https://github.com/shahdza/Cocos_LearningTest/tree/master/demo_%E6%BB%9A%E5%8A%A8%E8%A7%86%E5%9B%BECCScrollView 

【3.x】

    (1)去掉 “CC”

    (2)滚动方向

        > CCScrollViewDirection 改为强枚举 ScrollView::Direction

1
2
3
4
5
//
    HORIZONTAL     //只能横向滚动
    VERTICAL       //只能纵向滚动
    BOTH           //横向纵向都能滚动,默认方式
//

    (3)其他变化不大。


【CCScrollView】

    滚动视图类CCScrollView继承于CCLayer,故它会忽略锚点的设置,其锚点始终为(0,0)。 而我们知道CCLayer继承了触控事件CCTouch相关的函数。而CCScrollView也继承了触控函数,并将屏幕触控事件的四个函数 ccTouchesBegan、ccTouchesMoved、ccTouchesEnded、ccTouchesCancelled进行了重写并实现了 有关触摸移动相关的操作(其内部的实现代码自己看cocos2dx的源码)。这也就是为什么滚动视图CCScrollView的屏幕可以进行上下左右滚动 的原因了。

    值得注意的是:既 然CCScrollView也是一个CCLayer图层,我们都知道触控滚动的不是CCLayer图层,而是添加在图层上的那些对象。比如 CCSprite精灵、以及图层上的CCLayer等等。为了方便实现CCScrollView的滚动效果,cocos2dx引擎规定在使用 CCScrollView时,需要在它的上面添加一个用于触控滚动的容器Container,一般容器都选用CCLayer类或其扩展类(如CCLayerColor等)。而触控事件的四个函数也是针对容器Container进行操作的。

    也就是说CCScrollView实现的视图滚动,在真正意义上说是对容器Container进行滚动。

    接下来就来讲讲它的使用方法吧!

1、引入头文件和命名空间

1
2
3
4
//
    #include "cocos-ext.h"
    using namespace cocos2d::extension;
//

2、创建方式

    说明:有两种创建方式。对于默认的创建方式create(),会自动创建CCLayer作为滚动视图的容器,且滚动视图的可视区域的大小默认为200*200。而第二种则是可以自定义选择哪个CCLayer作为容器。

    值得注意的是:创建滚动视图之后,对于添加子节点操作scrollView->addChild(sp),实际上是将sp添加到容器container中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//
class CCScrollView : public CCLayer
 
/**
 *     2种创建方式
 */
 
    //会自动创建CCLayer作为容器
    static CCScrollView* create();
 
    //size:     滚动视图的可视区域大小
    //container:自定义滚动视图的CCLayer容器
    static CCScrollView* create(CCSize size, CCNode* container = NULL);
 
 
    //举例
    CCLayer* scrollLayer = CCLayer::create();
    CCScrollView* scrollView = CCScrollView::create(CCSizeMake(150, 100), scrollLayer);
//

3、常用操作

    设置容器、尺寸大小、容器的偏移量、允许滚动的方向、放缩、以及其他属性的判断。

    注意:因为容器与滚动视图的锚点均为(0,0)。所以容器的偏移量,指容器左下角坐标相对滚动视图左下角坐标的偏移。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//
/**
 *     容器相关操作
 *     setContainer , setContentSize , setContentOffset
 */
    //设置滚动视图的容器
    void setContainer(CCNode* pContainer);
    CCNode* getContainer();
 
    //设置容器Container的尺寸大小
    virtual void setContentSize(const CCSize & size);
    virtual const CCSize& getContentSize() const;
 
    //设置容器相对滚动视图的偏移量
    //animated为是否附带滑动的动作效果,还是直接设置为新的偏移量
    //默认滑动动作为0.15秒,从旧位置滑动到新位置.
    void setContentOffset(CCPoint offset, bool animated = false);
    void setContentOffsetInDuration(CCPoint offset, float dt); 
    CCPoint getContentOffset();
 
 
/**
 *     滚动视图相关操作
 *     setViewSize , setDirection , setZoomScale ,
 *     isDragging , isTouchMoved , setBounceable , setTouchEnabled
 */
    //设置滚动视图可视区域的大小
    void setViewSize(CCSize size);
    CCSize getViewSize();
 
    //设置滚动视图允许滚动的方向
    //CCScrollViewDirection:
    //      kCCScrollViewDirectionBoth              横向纵向都能滚动,默认方式
    //      kCCScrollViewDirectionHorizontal        只能横向滚动
    //      kCCScrollViewDirectionVertical          只能纵向滚动
    virtual void setDirection(CCScrollViewDirection eDirection);
    CCScrollViewDirection getDirection();
 
    //放缩滚动视图大小
    //好像有bug,建议不要使用了!
    void setZoomScale(float s);
    void setZoomScale(float s, bool animated);
    float getZoomScale();
    void setZoomScaleInDuration(float s, float dt);
 
    bool isDragging();                     //用户是否正在CCScrollView中操作
    bool isTouchMoved();                   //用户是否在CCScrollView中移动
    void setBounceable(bool bBounceable);  //是否开启弹性效果 
    bool isBounceable();                   //是否具有弹性效果
    void setTouchEnabled(bool e);          //是否开启触摸
//

4、事件委托代理接口类CCScrollViewDelegate

    CCScrollViewDelegate类主要是用来侦听CCScrollView的事件,并设置事件的回调响应函数。

    使用方法:在创建CCScrollView类的CCLayer类中,让CCLayer继承CCScrollViewDelegate,并重写如下两个事件回调响应函数。

1
2
3
4
//
    virual void scrollViewDidScroll(CCScrollView * view);   //有滚动时的响应函数
    virual void scrollViewDidZoom(CCScrollView * view);     //有缩放时的响应函数
//

5、委托代理

1
2
3
4
5
6
7
8
9
10
//
    //设置滚动视图的事件委托代理对象,一般为this
    //并且CCLayer必需要继承代理接口类CCScrollViewDelegate
    void setDelegate(CCScrollViewDelegate* pDelegate);
    CCScrollViewDelegate* getDelegate();
 
 
    //举例:
    //scrollView->setDelegate(this);
//

6、关于尺寸大小

    CCScrollView的使用过程中涉及到两个尺寸大小。

    (1)滚动视图的尺寸大小:即可视区域的大小。使用setViewSize()进行设置。

    (2)容器的尺寸大小:使用setContentSize()进行设置。

    例如设置滚动视图尺寸大小为100*100,容器的尺寸大小为1000*1000。那么每次对视图进行滚动,都只能看到容器100*100的某部分区域。

    具体图文解说可以参照cocos-孤狼大神写的:和屌丝一起学cocos2dx-CCScrollView

7、关于触摸滚动

    使用setDirection()可以设置滚动的方向。主要有三个类型:

    (1)横向纵向都能滚动    kCCScrollViewDirectionBoth              

    (2)只能横向滚动        kCCScrollViewDirectionHorizontal        

    (3)只能纵向滚动        kCCScrollViewDirectionVertical          

    另外setTouchEnabled()是用来设置是否开启触控事件的。所以若设置为false。那么即使setDirection()了,也无法滚动视图。

8、使用技巧

    (1)创建CCScrollView,和容器CCLayer;并设置滚动视图的容器为该容器。

    (2)设置容器的尺寸大小setContentSize;滚动视图(可视区域)的尺寸大小setViewSize。

    (3)将各种精灵、菜单、按钮等加入到容器中。

    (4)设置委托代理setDelegate(this),并实现回调函数。


【代码实战】

    这里例举了滚动视图CCScrollView的三种用途。

1
2
3
4
5
//
    void test1();     //测试图片滚动
    void test2();     //测试只能纵向滚动
    void test3();     //测试背包翻页
//

1、资源图片

    第一组:

wKioL1P7dF3BNzBAAAddWYzXKxY984.jpg

    第二组:

wKioL1P7dNmj0RMeAAAjK9teRfE282.jpg    wKiom1P7c8GDVKW8AAAjtKSDM-M911.jpg    wKioL1P7dNmh99oMAAAjKsNJ2mA727.jpg    wKioL1P7dNmgUrZWAAAj3a3fdFY451.jpg

    第三组:

wKiom1P7c4-BNhddAAATWetOdzQ115.jpg    wKioL1P7dKahSmKMAAATDlDPr7M853.jpg

wKioL1P7dKfRh-XpAAATIvbAoeQ026.jpg    wKiom1P7c4-yKualAAAU7Ih-51U755.jpg    wKiom1P7c4-CHawmAAANgkMX34Q085.jpg

2、引入头文件和命名空间

1
2
3
4
//
    #include "cocos-ext.h"
    using namespace cocos2d::extension;
//

3、继承CCScrollViewDelegate,重写事件侦听函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//
    class HelloWorld : public cocos2d::CCLayer,public CCScrollViewDelegate
    {
    public:
        virtual bool init();  
        static cocos2d::CCScene* scene();
        void menuCloseCallback(CCObject* pSender);
        CREATE_FUNC(HelloWorld);
 
        void test1(); //测试图片滚动
        void test2(); //测试只能纵向滚动
        void test3(); //测试背包翻页
 
        int pageNumber;          //背包第几页
        CCMenuItemImage* pBack;  //往前翻页
        CCMenuItemImage* pFront; //往后翻页
        void scrollImage(CCObject* sender); //test3的背包翻页
 
        void scrollViewDidScroll(CCScrollView* view); //滚动时响应的回调函数
        void scrollViewDidZoom(CCScrollView* view);   //放缩时响应的回调函数
    };
//

4、委托代理回调函数

    在控制台输出LOG。

1
2
3
4
5
6
7
8
9
10
//
    void HelloWorld::scrollViewDidScroll(CCScrollView* view) 
    {
        CCLOG("ScrollView Moved!");
    }
    void HelloWorld::scrollViewDidZoom(CCScrollView* view) 
    {
        CCLOG("ScrollView Scaled");
    }
//

5、测试图片滚动test1()

    屏幕大小:480*320。滚动视图大小:480*320。容器大小:960*600。

    开启弹性效果setBounceable。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//
    void HelloWorld::test1()
    {
        CCSize visableSize = CCSizeMake(480, 320); //屏幕大小
        CCSize mysize = CCSizeMake(960,600);       //容器大小
 
    //创建容器、设置大小
        CCLayerColor* scrollLayer = CCLayerColor::create( ccc4(255,255,255,255) );
        scrollLayer->setContentSize(mysize);
         
    //容器中的东西
        CCSprite* bg = CCSprite::create("war.png");
        bg->setPosition( ccp(960/2.0, 600/2.0) );
        scrollLayer->addChild(bg);
 
 
    //创建滚动视图CCScrollView
        CCScrollView* scrollView = CCScrollView::create();
        this->addChild(scrollView, 0, 1);
         
        //属性设置
        scrollView->setContainer(scrollLayer);  //设置容器
        scrollView->setViewSize( visableSize ); //可视区域大小
        scrollView->setBounceable(true);        //是否具有弹性
         
        //委托代理
        scrollView->setDelegate(this);
    }
//

6、测试只能纵向滚动test2()

    屏幕大小:480*320。滚动视图大小:150*100。容器大小:150*220。

    将滚动视图设置到屏幕中心位置,并设置滚动方向setDirection,只能纵向滚动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//
    void HelloWorld::test2()
    {
        CCSize visableSize = CCSizeMake(480, 320); //屏幕大小
        CCSize mysize = CCSizeMake(150,220);       //容器大小
 
    //创建容器、设置大小
        CCLayerColor* scrollLayer = CCLayerColor::create( ccc4(255,255,255,255) );
        scrollLayer->setContentSize(mysize);
 
    //容器中添加四个按钮
        for(int i = 1; i <= 4; i++) 
        {
            char file[20];
            sprintf(file, "btn%d.png", i);
            CCSprite* btn = CCSprite::create(file);
            btn->setPosition( ccp(mysize.width/2, 220 - 50*i) );
            scrollLayer->addChild(btn);
        }
 
    //创建滚动视图CCScrollView
        //可视区域大小150*100 、 容器为scrollLayer
        CCScrollView* scrollView = CCScrollView::create(CCSizeMake(150, 100), scrollLayer);
        scrollView->setPosition( visableSize/2 - ccp(150/2.0, 100/2.0) );
        this->addChild(scrollView, 0, 2);
         
        //设置为只能纵向滚动
        scrollView->setDirection(kCCScrollViewDirectionVertical);
 
        //委托代理
        scrollView->setDelegate(this);
    }
//

7、测试背包翻页test3()

    屏幕大小:480*320。滚动视图大小:100*80。容器大小:300*80。

    关闭触控事件setTouchEnabled(false),创建两个按钮,实现只能通过按钮进行左右翻页。

    翻页原理:通过设置容器的偏移值setContentOffset。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//
    void HelloWorld::test3()
    {
        CCSize visableSize = CCSizeMake(480, 320); //屏幕大小
        CCSize mysize = CCSizeMake(300,80);        //容器大小
 
    //创建容器、设置大小
        CCLayerColor* scrollLayer = CCLayerColor::create( ccc4(255,255,255,255) );
        scrollLayer->setContentSize(mysize);
 
    //容器中添加三个图片
        for(int i = 1; i <= 3; i++) 
        {
            char file[20];
            sprintf(file, "sp%d.png", i);
            CCSprite* sp = CCSprite::create(file);
            sp->setPosition( ccp(100*i - 50, 40) );
            scrollLayer->addChild(sp);
        }
 
    //创建滚动视图CCScrollView
        //可视区域大小100*80 、 容器为scrollLayer
        CCScrollView* scrollView = CCScrollView::create(CCSizeMake(100, 80), scrollLayer);
        scrollView->setPosition( visableSize/2 - ccp(100/2.0, 0) );
        this->addChild(scrollView, 0, 3);
 
        //属性设置
        scrollView->setTouchEnabled(false); //关闭触碰事件,无法触摸滚动
 
        //委托代理
        scrollView->setDelegate(this);
 
 
    //创建背包翻页按钮
        //前翻pBack、后翻pFront
        pBack = CCMenuItemImage::create("b1.png""b2.png""b3.png"this, menu_selector(HelloWorld::scrollImage) );
        pFront = CCMenuItemImage::create("f1.png""f2.png""f3.png"this, menu_selector(HelloWorld::scrollImage) );
        pBack->setPosition( ccp(visableSize.width/2 - 100, 60) );
        pFront->setPosition( ccp(visableSize.width/2 + 100, 60) );
        CCMenu* pMenu = CCMenu::create(pBack, pFront, NULL);
        pMenu->setPosition(CCPointZero);
        this->addChild(pMenu, 0, 100);
 
        pBack->setEnabled(false);
        pageNumber = 0; //第0页
 
    }
 
 
    //实现翻页效果scrollImage
    void HelloWorld::scrollImage(CCObject* sender)
    {
        CCScrollView* scrollView = (CCScrollView*)this->getChildByTag(3);
 
        if(sender == pBack && pBack->isEnabled() )
        {
            pageNumber = max(0, pageNumber-1); //前翻
        }
        else if( pFront->isEnabled() )
        {
            pageNumber = min(2, pageNumber+1); //后翻
        }
 
        //设置容器相对滚动视图的偏移量
        scrollView->setContentOffset(ccp(-100 * pageNumber, 0), true);
 
        pBack->setEnabled( pageNumber != 0);
        pFront->setEnabled( pageNumber != 2);
    }
//

8、运行结果

    8.1、背景滚动、附带弹性效果

wKioL1P7fKXQMNuRABJI5nik47U808.gif

        

    8.2、只能纵向滚动,附带弹性效果

wKiom1P7e42SMvMqAAJPJRgzfNw274.gif

    8.3、背包翻页、无法触摸滚动、通过按钮进行翻页

wKiom1P7e42xh9vNAACstxmMFVE125.gif

本文出自 “夏天的风” 博客,请务必保留此出处http://shahdza.blog.51cto.com/2410787/1544983

原文地址:https://www.cnblogs.com/dudu580231/p/5642445.html