使用时注意是调用 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
glScissor((GLint)screenPos.x, (GLint)screenPos.y, (GLsizei)(m_tViewSize.width*s), (GLsizei)(m_tViewSize.height*s));
ScrollView一般用在游戏的关卡选择这种类似的场景(比如愤怒的小鸟和割绳子的关卡选择),当然,也可以用在道具店等等一些选择菜单的场景。
滑动,浏览不同关卡菜单;点击不同的菜单精灵,处理不同的事件。
(1) 首先需要一个创建一个CCScrollView的对象和一个“Container”(可以是CCLayer或者CCNode的对象,用来存放CCScrollView中的内容),我这里放置了两个精灵菜单选项
// 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);
为了使ScrollView显示更灵活,CCScrollView提供了一个显示区域的设置方法,我这里设置显示区域480x320,总的大小为960x320(假设有两屏需要显示)
layer->setContentSize(CCSizeMake(960, 320));
scrollView->setContentSize(CCSizeMake(480, 320));
scrollView->setContainer(layer);
这里用layer作为(1)中的container
(3) 补充,其实到这里就基本实现了CCScrollView最基本的用法,如果需要监听滑动的事件,可以继承CCScrollViewDelegate委托,实现以下两个方法
public:
void scrollViewDidScroll(CCScrollView* view);
void scrollViewDidZoom(CCScrollView* view);
这里会有一个问题,那就是当滑动结束时,经常是在两页之间,也就是图2的情况,这种体验不太好,我简单看了一下CCScrollView的源码,发现并没有相关的设置,想必是作者考虑到无法定义每页的大小尺寸,所以没有提供吧!所以,如果需要,我们要额外加一段校对的代码
所以在HelloWorld这层,继承了触摸事件的响应方法,并在ccTouchEnded()方法中校对
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在最左边和最右边做了校对,但是对中间的部分没有做校对!
(1) 如果需要校对这一步,HelloWorld层是需要实现触摸方法的,而触摸的优先级一定要大于CCScrollView对象(也就是说要CCScrollView对象先响应触摸事件,然后在由HelloWorld层响应),而CCScrollView默认设置的优先级是0,所以HelloWorld需要设置为大于0的值
void HelloWorld::onEnter()
{
CCLayer::onEnter();
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, true);
}
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 的扩展库里面,要是使用的话,需要添加命名空间
using namespace cocos2d::extension;
或者是用cocos2d-x 已经定义的宏
USING_NS_CC_EXT;
然后如果我们要是用 ScrollView的话,需要实现它的Delegate,这个的话,如果是做过IOS开发的同学应该很容易理解,就像UIScrollView。
class HelpScene : public cocos2d::CCLayer ,public CCScrollViewDelegate { public: void scrollViewDidScroll(CCScrollView* view); void scrollViewDidZoom(CCScrollView* view); public: ///////////////////////////////////////////其他方法: }
添加一个CCScrollView,可以通过统一的create函数实现,
// 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