转自http://blog.csdn.net/ac_huang/article/details/37740515
ScrollView在3.0里面依然存在于extensions下面,看他的继承关系,他最终也是继承node,我们在来看看他的头文件应该怎么包含
1. 在头文件中添加 #include "cocos-ext.h" 在添加使用域 USING_NS_CC_EXT;
2. 添加多继承public ScrollViewDelegate,如下:
- classHelloWorld:publicLayerColor,publicScrollViewDelegate
我们转到ScrollViewDelegate里面,发现这是一个抽象基类,里面有两个纯虚函数,我们需要自己实现
-
-
- *@luaNA
- */
- virtualvoidscrollViewDidScroll(ScrollView*view)=0;
- /**
- *@jsNA
- *@luaNA
- */
- voidscrollViewDidZoom(ScrollView*view)=0;
所以我们还需要在自己的类中添加这两行代码
//scrollview滚动的时候会调用
- voidscrollViewDidScroll(extension::ScrollView*view);
- //scrollview缩放的时候会调用
- voidscrollViewDidZoom(extension::ScrollView*view);
我们为了达到用鼠标点击图片移动时,出现缩小放大效果且能像相册一样切换图片,那么我们还需要添加触摸事件
boolonTouchBegan(Touch*touch,Event*pEvent);
- voidonTouchMoved(Touch*touch,Event*pEvent);
- voidonTouchEnded(Touch*touch,Event*pEvent);
下面直接看看在头文件中代码
#ifndef__HELLOWORLD_SCENE_H__
- #define__HELLOWORLD_SCENE_H__
-
- #include"cocos2d.h"
- #if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
- #include"extensions/cocos-ext.h"
- #else
- #include"cocos-ext.h"
- #endif
-
- #include"cocostudio/CocoStudio.h"
- #include"CocosGUI.h"
- USING_NS_CC;
- USING_NS_CC_EXT;
- usingnamespacecocostudio;
- namespaceui;
- #definePHOTO_COUNT11
- publicScrollViewDelegate
- {
- public:
- //there'sno'id'incpp,sowerecommendreturningtheclassinstancepointer
- staticcocos2d::Scene*createScene();
- //Here'sadifference.Method'init'incocos2d-xreturnsbool,insteadofreturning'id'incocos2d-iphone
- virtualboolinit();
- //aselectorcallback
- voidmenuCloseCallback(cocos2d::Ref*pSender);
- voidscrollViewDidZoom(extension::ScrollView*view);
- //添加触摸
- voidaddListener();
- //添加粒子系统test
- voidaddParticle();
- //implementthe"staticcreate()"methodmanually
- CREATE_FUNC(HelloWorld);
- //骨骼动画
- Armature*m_armature;
- //添加UI
- voidaddUI();
- //添加场景(区别是我自定义的函数)
- voidaddMyScene();
- private:
- //根据手势滑动的距离和方向滚动图层
- voidadjustScrollView(floatoffset);
- //voidsetback();
- //存放所有图片
- Vector<Sprite*>m_spVec;
- //当前的ScrollView
- extension::ScrollView*m_scrollView;
- //touchBegen时的触摸位置
- Pointm_touchPoint;
- //当前是第几张图片
- intm_currentPage;
- };
- #endif//__HELLOWORLD_SCENE_H__
上面有很多不是我们这相例子里面的,不过不影响
在来看看源文件里面
boolHelloWorld::init()
- //////////////////////////////
- //1.superinitfirst
- if(!LayerColor::initWithColor(Color4B(120,120,255)))
- returnfalse;
- }
- autovisibleSize=Director::getInstance()->getVisibleSize();
- autoorigin=Director::getInstance()->getVisibleOrigin();
- /*autoscrollLayer=LayerColor::create(Color4B(0,255));
- scrollLayer->setContentSize(Size(640,480));
- scrollLayer->setAnchorPoint(Point(0.5,0.5));
- scrollLayer->setPosition(Point(visibleSize.width/2-320,visibleSize.height/2-240));
- this->addChild(scrollLayer);*/
- m_scrollView=extension::ScrollView::create(Size(visibleSize.width,visibleSize.height));
- charspriteName[15];
- Layer*photoLayer=Layer::create();
- for(inti=1;i<=PHOTO_COUNT;++i)
- memset(spriteName,sizeof(spriteName));
- sprintf(spriteName,"XJ%d.jpg",i);
- autosprite=Sprite::create(spriteName);
- sprite->setPosition(Point(visibleSize.width*(i*1.0-0.5),visibleSize.height*0.5));
- //缩小一倍
- //sprite->setScale(0.5);
- photoLayer->addChild(sprite);
- m_spVec.pushBack(sprite);
- }
- //设置layer到滚动层容器中
- m_scrollView->setContainer(photoLayer);
- //重新设置滚动层的大小,这点很重要。
- m_scrollView->setContentSize(Size(PHOTO_COUNT*visibleSize.width,0); background-color:inherit">//设置代理
- m_scrollView->setDelegate(this);
- m_scrollView->setPosition(Point::ZERO);
- //我们只在水平方向上滚动。
- m_scrollView->setDirection(extension::ScrollView::Direction::HORIZONTAL);
- m_scrollView->setContentOffset(Point(0,0));
- this->addChild(m_scrollView);
- m_currentPage=0;
- //注册触摸,和2.x的不同了,还有一种lambda表达式的写法
- /************************************************************************
- *lambda表达式的写法
- *autolistener1=EventListenerTouchOneByOne::create();
- *listener1->onTouchBegan=[](Touch*touch,Event*event)
- *{
- *//dosomething
- *};
- *listener1->onTouchMoved=[](Touch*touch,0); background-color:inherit">*listener1->onTouchEnded=[=](Touch*touch,0); background-color:inherit">*_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
- ************************************************************************/
- autolistener=EventListenerTouchOneByOne::create();
- //设置是否想下传递触摸
- listener->setSwallowTouches(true);
- listener->onTouchBegan=CC_CALLBACK_2(HelloWorld::onTouchBegan,248)"> listener->onTouchMoved=CC_CALLBACK_2(HelloWorld::onTouchMoved,153); font-weight:bold; background-color:inherit">this);
- listener->onTouchEnded=CC_CALLBACK_2(HelloWorld::onTouchEnded,0); background-color:inherit">//将触摸监听添加到eventDispacher中去
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,0); background-color:inherit">//注册触摸结束
- true;
- }
我们在也不需要使用setTouchEnabled这个函数了,你会发现你用了以后,编译时会提示这个函数已经被否决了,可以用setEnable();代替看看如何。
对于上面的触摸我们要重点说说,说完了在继续分析 ScrollView!!!
一、触摸监听listener的创建方式有两种,
1、EventListenerTouchOneByOne 2、EventListenerTouchAllAtOnce, 顾名思义EventListenerTouchOneByOne的意思单点触摸,EventListenerTouchAllAtOnce是多点触摸 而不需要再用设置Delegate的方式来做了。 3.0触摸机制还有个不同的地方,只要是放在最上面的那个精灵,那它的触摸优先级就最高。 我们用的按钮Menu 就是用这种方式设置触摸优先级的。
二、listener的调试优先级 我们进入addEventListenerWithSceneGraphPriority的定义中看一下,有下面这一行代码:
listener->setFixedPriority(0);
它将精灵的触摸优先级设置成0,从这里我们可以引申出两个问题,一个就是当我们要给精灵设置触摸优先级时,
因为0已经被“官府”征用了,另一个问题就是:如果自己想设置精灵的触摸优先级,那应该怎么做呢? 下面是提供的另外一种添加listener的方法:
copy
_eventDispatcher->addEventListenerWithFixedPriority(listener1,fixedPriority);
在第二个参数里设置触摸优先级,这样就可以了。
三、多个目标如何添加触摸监听 如果多个精灵都想实现拖动的功能,那么这些精灵都可以使用listener1这一个触摸监听, 例如我们有三个精灵,sprite,sprite2,sprite3,他们调用listener1的方式:
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,sprite1);
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(),sprite2);
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(),sprite3);
当我们进入到clone函数里面,你会发现他实现了复制触摸函数,也就是clone是专门用来这么干这的
EventListenerTouchOneByOne*EventListenerTouchOneByOne::clone()
- autoret=newEventListenerTouchOneByOne();
- if
(ret&&ret->init())
{
ret->autorelease();
ret->onTouchBegan=onTouchBegan;
ret->onTouchMoved=onTouchMoved;
ret->onTouchEnded=onTouchEnded;
ret->onTouchCancelled=onTouchCancelled;
ret->_claimedTouches=_claimedTouches;
ret->_needSwallow=_needSwallow;
else
CC_SAFE_DELETE(ret);
returnret;
}
四、 删除触摸监听
如果想移除sprite的触摸移动,可以这么做:
_eventDispatcher->removeEventListeners(EventListener::Type::TOUCH_ONE_BY_ONE);
看完了新版 touch 我们继续看scrollView中的委托方法,实现效果是对象在某个坐标范围内移动时会有缩放效果。
copy
void HelloWorld::scrollViewDidScroll(extension::ScrollView*view)
//往右移动x坐标为正,往左移为负
autooffPos=view->getContentOffset();
//log("offsetpos%f%f",offPos.x,offPos.y);
for(autosp:m_spVec)
//获得当前对象的X坐标(不管怎么滚动,这个坐标都是不变的)
autopointX=sp->getPositionX();
//将精灵的X坐标+偏移X坐标
floatoffX=pointX+offPos.x;
//我的屏幕大小设置为了480*640,我的图片为320*480,我让图片居中显示(Point(160,320)--->Point(320,320))
//图片与图片之间的间隔是一个屏幕(480),我移动图片时不想让他缩放的太小,即只在80-240之间缩放,由于要对称,所以
//相应的240-400也会产生和80-240之间相同的缩放比例,这样后一种需要用480-offx
if(offX>80&&offX<=240)
floatscaleX=offX/240;
sp->setScale(scaleX);
//log("scaleX1%f",scaleX);
elseif(offX>240&&offX<=400)
floatscaleX=(480-offX)/240;
//log("scaleX2%f",0); background-color:inherit">//对于在80-400之外的,我们保持同一缩放比例
sp->setScale(80*1.0/240);
}
我们应该知道,对象放到滚动层上,那么不管对象在scrollView上如何移动,它获得的坐标都是不会变的(如sp->getPosition()是不变的数值),这种情况下,如果我们想实现对象在某个坐标范围内会有缩放效果,那么只是去获取对象的坐标肯定是行不通的,所以肯定要找一个时刻在变化的”参照物”来利用下,该找什么呢?没错,就是scrollView的偏移坐标(scrollView->getContentOffset())!只要scrollView移动一下,那么它的 偏移量也随之改变。我这里就是利用对象的坐标与scrollView的偏移坐标之间不可告人的秘密,从而实现当前的目的。
实现了缩放,怎么去实现图片切换了,我们需要在触摸结束后,来切换ScrollView的偏移来达到切换效果
copy
bool HelloWorld::onTouchBegan(Touch*touch,Event*pEvent)
m_touchPoint=Director::getInstance()->convertToGL(touch->getLocationInView());
log("beginx=%f,y=%f",m_touchPoint.x,m_touchPoint.y);
}
获得一个触摸初始值,将来与结束值对比来做出一些约束
copy
void HelloWorld::onTouchEnded(Touch*touch,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> PointendPoint=Director::getInstance()->convertToGL(touch->getLocationInView());
floatdistance=endPoint.x-m_touchPoint.x;
log("endx=%f,endPoint.x,endPoint.y);
//当我们移动的距离太小了,默认为不移动,也可以防止不小心碰了一下就切换了
if(fabs(distance)<=240)
log("thisis1");
adjustScrollView(0);
if(fabs(distance)>240)
log("thisis2");
adjustScrollView(distance);
}
去看看adjustScrollView里面实现了什么?
copy
<spanstyle="font-family:Arial;font-size:14px;">voidHelloWorld::adjustScrollView(floatoffset)
- if
(offset<0)
++m_currentPage;
if(offset>0)
--m_currentPage;
if(m_currentPage<0)
if(m_currentPage>=PHOTO_COUNT)
m_currentPage=1;
autovisibleSize=Director::getInstance()->getVisibleSize();
//注意这里为负的visibleSize.width,我开始写成正的,一直不出效果
PointcurPoint(-visibleSize.width*m_currentPage,0);
this->m_scrollView->setContentOffset(curPoint);
//setback
}</span><spanstyle="font-family:SimSun;font-size:14px;">
</span>
此程序依然存在一些bug,比如一下子滑动了很远的距离,那样图片的切换就会变得杂乱无章,这个依然可以在 触摸结束里面使用distance 来限制,留给以后去完善吧!!
下面看看效果:
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|