Cocos2d-x学习CCScrollView

使用时注意是调用 setContainer 函数添加滚动内容,不能用addChild

参考:http://blog.csdn.net/onerain88/article/details/7775569

http://music.573114.com/Blog/Html/D96C/550230.html

http://blog.csdn.net/toss156/article/details/7884207

 

 

cocos2d-x 2.0版本之后提供了许多控件,其中就包括ScrollView,之前总结过一个简单的ScrollView,但是问题很多,比如必须是全屏,不能是一块区域,而cocos2d-x 2.0中提供的CCScrollView中,是可以设定区域的,CCScrollView做了区域的裁剪

  1. <SPAN style="FONT-SIZE: 16px">glScissor((GLint)screenPos.x, (GLint)screenPos.y, (GLsizei)(m_tViewSize.width*s), (GLsizei)(m_tViewSize.height*s));</SPAN>  
glScissor((GLint)screenPos.x, (GLint)screenPos.y, (GLsizei)(m_tViewSize.width*s), (GLsizei)(m_tViewSize.height*s));


但是遗憾的是tests中并没有给出CCScrollView的用法,查了一些cocos2d-iphone的资料,基本用法可以实现了,简单的总结一下!


1.用途和效果

ScrollView一般用在游戏的关卡选择这种类似的场景(比如愤怒的小鸟和割绳子的关卡选择),当然,也可以用在道具店等等一些选择菜单的场景。




滑动,浏览不同关卡菜单;点击不同的菜单精灵,处理不同的事件。


2.实现

(1) 首先需要一个创建一个CCScrollView的对象和一个“Container”(可以是CCLayer或者CCNode的对象,用来存放CCScrollView中的内容),我这里放置了两个精灵菜单选项

  1. <SPAN style="FONT-SIZE: 16px">// CCScrollView  
  2.     scrollView = CCScrollView::create();  
  3.     CCLayer *layer = CCLayer::create();  
  4.       
  5.     CCSprite *sprite1 = CCSprite::create("HelloWorld.png");  
  6.     CCSprite *sprite2 = CCSprite::create("HelloWorld.png");  
  7.       
  8.     layer->setAnchorPoint(CCPointZero);  
  9.     layer->setPosition(CCPointZero);  
  10.       
  11.     // Menu   
  12.     CCMenuItemSprite *menuItem1 = CCMenuItemSprite::create(sprite1, sprite1, this, menu_selector(HelloWorld::menu1Callback));  
  13.     menuItem1->setPosition(ccpAdd(CCPointZero, ccp(size.width / 2, size.height / 2)));  
  14.     menuItem1->setScale(0.4f);  
  15.     CCMenuItemSprite *menuItem2 = CCMenuItemSprite::create(sprite2, sprite2, this, menu_selector(HelloWorld::menu2Callback));  
  16.     menuItem2->setPosition(ccpAdd(ccp(480, 0), ccp(size.width / 2, size.height / 2)));  
  17.     menuItem2->setScale(0.4f);  
  18.     CCMenu *menu = CCMenu::create(menuItem1, menuItem2, NULL);  
  19.       
  20.     menu->setPosition(CCPointZero);  
  21.     layer->addChild(menu);</SPAN>  
// CCScrollView
    scrollView = CCScrollView::create();
    CCLayer *layer = CCLayer::create();
    
    CCSprite *sprite1 = CCSprite::create("HelloWorld.png");
    CCSprite *sprite2 = CCSprite::create("HelloWorld.png");
    
    layer->setAnchorPoint(CCPointZero);
    layer->setPosition(CCPointZero);
    
    // Menu
    CCMenuItemSprite *menuItem1 = CCMenuItemSprite::create(sprite1, sprite1, this, menu_selector(HelloWorld::menu1Callback));
    menuItem1->setPosition(ccpAdd(CCPointZero, ccp(size.width / 2, size.height / 2)));
    menuItem1->setScale(0.4f);
    CCMenuItemSprite *menuItem2 = CCMenuItemSprite::create(sprite2, sprite2, this, menu_selector(HelloWorld::menu2Callback));
    menuItem2->setPosition(ccpAdd(ccp(480, 0), ccp(size.width / 2, size.height / 2)));
    menuItem2->setScale(0.4f);
    CCMenu *menu = CCMenu::create(menuItem1, menuItem2, NULL);
    
    menu->setPosition(CCPointZero);
    layer->addChild(menu);

(2) 设置CCScrollView的显示区域

为了使ScrollView显示更灵活,CCScrollView提供了一个显示区域的设置方法,我这里设置显示区域480x320,总的大小为960x320(假设有两屏需要显示)

  1. <SPAN style="FONT-SIZE: 16px">    layer->setContentSize(CCSizeMake(960, 320));  
  2.     scrollView->setContentSize(CCSizeMake(480, 320));  
  3.     scrollView->setContainer(layer);</SPAN>  
    layer->setContentSize(CCSizeMake(960, 320));
    scrollView->setContentSize(CCSizeMake(480, 320));
    scrollView->setContainer(layer);
这里用layer作为(1)中的container

(3) 补充,其实到这里就基本实现了CCScrollView最基本的用法,如果需要监听滑动的事件,可以继承CCScrollViewDelegate委托,实现以下两个方法

  1. <SPAN style="FONT-SIZE: 16px">public:  
  2.     void scrollViewDidScroll(CCScrollView* view);  
  3.     void scrollViewDidZoom(CCScrollView* view);</SPAN>  
public:
    void scrollViewDidScroll(CCScrollView* view);
    void scrollViewDidZoom(CCScrollView* view);


3.校对

这里会有一个问题,那就是当滑动结束时,经常是在两页之间,也就是图2的情况,这种体验不太好,我简单看了一下CCScrollView的源码,发现并没有相关的设置,想必是作者考虑到无法定义每页的大小尺寸,所以没有提供吧!所以,如果需要,我们要额外加一段校对的代码

所以在HelloWorld这层,继承了触摸事件的响应方法,并在ccTouchEnded()方法中校对

  1. <SPAN style="FONT-SIZE: 16px">void HelloWorld::adjustScrollView()  
  2. {  
  3.     // 关闭CCScrollView中的自调整   
  4.     scrollView->unscheduleAllSelectors();  
  5.       
  6.     int x = scrollView->getContentOffset().x;  
  7.     int offset = (int) x % 480;  
  8.     // 调整位置   
  9.     CCPoint adjustPos;  
  10.     // 调整动画时间   
  11.     float adjustAnimDelay;  
  12.       
  13.     if (offset < -240) {  
  14.         // 计算下一页位置,时间   
  15.         adjustPos = ccpSub(scrollView->getContentOffset(), ccp(480 + offset, 0));  
  16.         adjustAnimDelay = (float) (480 + offset) / ADJUST_ANIM_VELOCITY;  
  17.     }  
  18.     else {  
  19.         // 计算当前页位置,时间   
  20.         adjustPos = ccpSub(scrollView->getContentOffset(), ccp(offset, 0));  
  21.         // 这里要取绝对值,否则在第一页往左翻动的时,保证adjustAnimDelay为正数  
  22.         adjustAnimDelay = (float) abs(offset) / ADJUST_ANIM_VELOCITY;  
  23.     }  
  24.       
  25.     // 调整位置   
  26.     scrollView->setContentOffsetInDuration(adjustPos, adjustAnimDelay);  
  27. }</SPAN>  
void HelloWorld::adjustScrollView()
{
    // 关闭CCScrollView中的自调整
    scrollView->unscheduleAllSelectors();
    
    int x = scrollView->getContentOffset().x;
    int offset = (int) x % 480;
    // 调整位置
    CCPoint adjustPos;
    // 调整动画时间
    float adjustAnimDelay;
    
    if (offset < -240) {
        // 计算下一页位置,时间
        adjustPos = ccpSub(scrollView->getContentOffset(), ccp(480 + offset, 0));
        adjustAnimDelay = (float) (480 + offset) / ADJUST_ANIM_VELOCITY;
    }
    else {
        // 计算当前页位置,时间
        adjustPos = ccpSub(scrollView->getContentOffset(), ccp(offset, 0));
        // 这里要取绝对值,否则在第一页往左翻动的时,保证adjustAnimDelay为正数
        adjustAnimDelay = (float) abs(offset) / ADJUST_ANIM_VELOCITY;
    }
    
    // 调整位置
    scrollView->setContentOffsetInDuration(adjustPos, adjustAnimDelay);
}
在这里我会根据当前相对于半屏的宽度(240像素)作为判断标准,来决定滑动结束时的所在页

这里需要注意的是必须要先关闭CCScrollView的schedule方法,因为CCScrollView在最左边和最右边做了校对,但是对中间的部分没有做校对!


4.注意事项

(1) 如果需要校对这一步,HelloWorld层是需要实现触摸方法的,而触摸的优先级一定要大于CCScrollView对象(也就是说要CCScrollView对象先响应触摸事件,然后在由HelloWorld层响应),而CCScrollView默认设置的优先级是0,所以HelloWorld需要设置为大于0的值

  1. <SPAN style="FONT-SIZE: 16px">void HelloWorld::onEnter()  
  2. {  
  3.     CCLayer::onEnter();  
  4.     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, true);  
  5. }</SPAN>  
void HelloWorld::onEnter()
{
    CCLayer::onEnter();
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, true);
}

(2) 这个Demo中是有一个问题的,也就是当点着菜单项滑动的时候是无效的,因为菜单的触摸事件的优先级是最高的,所以,如果真的要做这种效果,需要考虑自己来判断触摸事件的!


Demo下载

github下载

 

bool HelloWorld::init()
{
    //
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }
    CCSize size = CCDirector::sharedDirector()->getWinSize();
//        创建一个layer作为容器
    CCLayer * containlayer = CCLayer::create();
    CCSprite * sp = CCSprite::create("HelloWorld.png");
    sp->setPosition(ccp(size.width*0.5,size.height*0.5));
    CCSprite * sp2  = CCSprite::create("Default.png");
    
    sp2->setPosition(ccp(sp->getContentSize().width, size.height*0.5));
//    往容器中添加节点
    containlayer->addChild(sp);
    containlayer->addChild(sp2);
    containlayer->setContentSize(CCSizeMake(size.width*3, size.height));
    
//    创建视图添加当前layer
    CCScrollView * sc = CCScrollView::create(CCSizeMake(size.width* 2, size.height));
    addChild(sc);
    
    sc->isDragging();//用户是否正在CCScrollView中操作
    sc->isTouchMoved();//用户是否正在CCScrollView移动操作
    sc->isBounceable();//是否开启弹性效果
    sc->setBounceable(true);//设置CCScrollView有弹性效果
    sc->setViewSize(CCSizeMake(size.width*2, size.height));
//    设置CCScrollView尺寸
    sc->setContainer(containlayer);//设置容器
    sc->getViewSize();//获取视图尺寸
    
//    务必在AppDelegate.cpp 中开启ios多点触莫的支持
    sc->setTouchEnabled(true);//开启监听多触点
    sc->setDelegate(this);//注册监听
    
    return true;
}
 void HelloWorld:: scrollViewDidScroll(CCScrollView * view)
{
    CCLOG("CCScrollView移动");
}
//    当scrollview发生缩放的时相应
 void HelloWorld:: scrollViewDidZoom(CCScrollView * view)
{
    CCLOG("CCScrollView放缩");
}

 

 

Cocos2d-x 2.0.1里面 集成了一些以前需要自己添加的控件,极大的方便作为开发者的我们。

今天给大家带来一个用CCScrollView 实现的帮主页面。

最终结果是这样的:

 

 

首先CCScrollView 在 Cocosd-x 的扩展库里面,要是使用的话,需要添加命名空间

  1. using namespace cocos2d::extension;  
  using namespace cocos2d::extension;


或者是用cocos2d-x 已经定义的宏

  1. USING_NS_CC_EXT;  
USING_NS_CC_EXT;

 

然后如果我们要是用 ScrollView的话,需要实现它的Delegate,这个的话,如果是做过IOS开发的同学应该很容易理解,就像UIScrollView。

  1. class HelpScene : public cocos2d::CCLayer ,public CCScrollViewDelegate  
  2. {  
  3.    public:  
  4.     void scrollViewDidScroll(CCScrollView* view);  
  5.     void scrollViewDidZoom(CCScrollView* view);  
  6.    public:  
  7.          ///其他方法:  
  8. }  
class HelpScene : public cocos2d::CCLayer ,public CCScrollViewDelegate
{
   public:
	void scrollViewDidScroll(CCScrollView* view);
	void scrollViewDidZoom(CCScrollView* view);
   public:
         ///其他方法:
}


添加一个CCScrollView,可以通过统一的create函数实现,

  1. // CCScrollView   
  2.  scrollView = CCScrollView::create();   //创建一个scrollview  
  3.  CCLayer *layer = CCLayer::create();    //创建一个层,作为滚动的内容  
  4.  char helpstr[30] = {0};  
  5.  for (int i=1;i<=6;i++)  
  6.  {  
  7.   sprintf(helpstr,"Help/Help_%02d_chs.png",i);  
  8.   CCSprite *sprite = CCSprite::create(helpstr);  
  9.   sprite->setScaleX(2.0);  
  10.   sprite->setScaleY(1.0);  
  11.   sprite->setPosition(ccp(size.width*(i-0.5),size.height/2+25));  
  12.   layer->addChild(sprite);  
  13.  }  
  14.    
  15.  layer->setAnchorPoint(CCPointZero);  
  16.  layer->setPosition(CCPointZero);  
  17.   
  18.  scrollView->setPosition(CCPointZero);  
  19.  scrollView->setContentOffset(CCPointZero);  
  20.  layer->setContentSize(CCSizeMake(480*6, 320));      //设置滚动区域的大小  
  21.  scrollView->setContentSize(CCSizeMake(480, 320));       //设置显示区域的大小       
  22.  scrollView->setContainer(layer);                            //设置需要滚动的内容  
  23.  scrollView->setTouchEnabled(false);                         //因为要自己实现触摸消息,所以这里设为false  
  24.  scrollView->setDelegate(this);  
  25.  scrollView->setDirection(CCScrollViewDirectionHorizontal);  //设置滚动的方向,有三种可以选择  
  26.   
  27.  this->addChild(scrollView);  
   // CCScrollView
	   scrollView = CCScrollView::create();	//创建一个scrollview
	   CCLayer *layer = CCLayer::create();	//创建一个层,作为滚动的内容
	   char helpstr[30] = {0};
	   for (int i=1;i<=6;i++)
	   {
		   sprintf(helpstr,"Help/Help_%02d_chs.png",i);
		   CCSprite *sprite = CCSprite::create(helpstr);
		   sprite->setScaleX(2.0);
		   sprite->setScaleY(1.0);
		   sprite->setPosition(ccp(size.width*(i-0.5),size.height/2+25));
		   layer->addChild(sprite);
	   }
	   
	   layer->setAnchorPoint(CCPointZero);
	   layer->setPosition(CCPointZero);

	   scrollView->setPosition(CCPointZero);
	   scrollView->setContentOffset(CCPointZero);
	   layer->setContentSize(CCSizeMake(480*6, 320));		//设置滚动区域的大小
	   scrollView->setContentSize(CCSizeMake(480, 320));		//设置显示区域的大小		
	   scrollView->setContainer(layer);                            //设置需要滚动的内容
	   scrollView->setTouchEnabled(false);                         //因为要自己实现触摸消息,所以这里设为false
	   scrollView->setDelegate(this);
	   scrollView->setDirection(CCScrollViewDirectionHorizontal);  //设置滚动的方向,有三种可以选择

	   this->addChild(scrollView);


 

Demo的下载地址:http://download.csdn.net/detail/toss156/4511442

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值