cocos2dx基础篇(16)——滚动视图CCScrollView

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

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

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

wKioL1P7LHGh4r-zAAEl3irSbeQ272.gif


【致谢】

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

    http://bbs.firedragonpzy.com.cn/forum.php?mod=viewthread&tid=51

    http://codingnow.cn/cocos2d-x/1024.html




【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
#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
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
52
53
54
55
56
/**
  *     容器相关操作
  *     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
virual  void  scrollViewDidScroll(CCScrollView * view);    //有滚动时的响应函数
virual  void  scrollViewDidZoom(CCScrollView * view);      //有缩放时的响应函数


5、委托代理

1
2
3
4
5
6
7
8
//设置滚动视图的事件委托代理对象,一般为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
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
#include "cocos-ext.h"
using  namespace  cocos2d::extension;


    (3)让HelloWorld类继承滚动视图的委托代理接口类CCScrollViewDelegate,重写事件侦听函数。并在HelloWorld类中声明测试相关的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
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
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
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
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);
}


    运行结果:

        (A)背景滚动、附带弹性效果。

wKioL1P7fKXQMNuRABJI5nik47U808.gif

        

        (B)只能纵向滚动,附带弹性效果。

wKiom1P7e42SMvMqAAJPJRgzfNw274.gif


        (C)背包翻页、无法触摸滚动、通过按钮进行翻页。

wKiom1P7e42xh9vNAACstxmMFVE125.gif

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值