直接上代码,根据cocos2d-x 扩展库中的代码改编的。
- //
- // MScrollView.h
- // Test ScrollView
- //
- // Created by Za aa on 13-4-25.
- //
- //
- #ifndef _MScrollView_h
- #define _MScrollView_h
- #include "cocos2d.h"
- using namespace cocos2d;
- //触摸误差
- const int TOUCH_DELTA = 5;
- //设置图片修正时的移动速度
- const float MOVE_SPEED = 1000;
- class MScrollView : public cocos2d::CCLayerColor
- {
- public:
- MScrollView();
- ~MScrollView();
- virtual bool init();
- //复写绘图函数,每帧调用,添加了区域剔除
- void visit();
- //CREATE_FUNC(MScrollView);
- //自定义--------
- //从多个精灵创建
- static MScrollView * CreateWithSprite(float gap,CCSprite * p_w_picpathSprite,...);
- //修改剔除区域
- void setClipSize(float width,float height);
- //修改响应区域
- void setTouchRect(CCRect touchRect){m_touchRect = touchRect;};
- //根据间距初始化子层精灵
- bool initGapForChild(float gap);
- //修正动画的函数
- void RAnimation(CCPoint pt);
- //拖动精灵,跟随手指移动改变位置
- void draySprite(float delta);
- //滚动到某一页的函数
- void gotoPageAnimation(float page);
- //页面滚动动画,moveto 动画
- void ScrollAnimation(CCPoint offset,float time) ;
- //updata,用于如果拖动就停止moveto 动作
- void MoveToAnimation(float dt );
- // 添加一个回调函数,用于停止动画
- void StopMoveToAnimation();
- //重写触屏相关函数----
- virtual void registerWithTouchDispatcher();
- virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
- virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
- virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
- virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
- private:
- //是否按下后移动
- bool m_dragging;
- //按下的点
- CCPoint m_touchDownPoint;
- //抬起点
- CCPoint m_touchUpPoint;
- //当前的触电
- CCPoint m_touchCurPoint;
- //子层容器,用于滚动显示
- CCLayer * m_Container;
- //保存所有精灵
- CCArray * m_spriteArray;
- //总页数
- int m_page;
- //当前页数
- int m_curpage;
- //偏移动画的时间
- float m_time;
- //显示区域
- // CCRect m_view;
- //显示区域,区域外的将被剪切
- CCSize m_clipSize;
- //接收事件的区域
- CCRect m_touchRect;
- //点击后的回调函数
- SEL_CallFunc m_fun;
- };
- #endif
- //
- // MScrollView.cpp
- // Test ScrollView
- //
- // Created by Za aa on 13-4-25.
- //
- //
- #include "MScrollView.h"
- MScrollView::MScrollView()
- {
- }
- MScrollView::~MScrollView()
- {
- //清空数组
- m_spriteArray->release();
- }
- MScrollView * MScrollView::CreateWithSprite(float gap,CCSprite *p_w_picpathSprite, ...)
- {
- MScrollView * pRet = new MScrollView();
- if (pRet && pRet->init())
- {
- //创建array,用于保存所有sprite
- pRet->m_spriteArray= CCArray::create();
- CC_SAFE_RETAIN(pRet->m_spriteArray);
- //-----------------------------------------------
- //将省略的sprite添加进m_spriteArray 和 mscrollview中
- //----------------------------------------------
- //定义一个params变量,实际是一个指针,用于定位可变行参变量
- va_list params;
- //执行本宏后,params指向第一个可变信参,p_w_picpathSprite为最后一个确定行参
- va_start(params, p_w_picpathSprite);
- //定义一个ccsprite 接收参数
- CCSprite * pNow = p_w_picpathSprite;
- while (true)
- {
- if (pNow)
- {
- //添加进数组和层-----
- pRet->m_spriteArray->addObject(pNow);
- pRet->m_Container->addChild(pNow);
- //去下一个值
- pNow = va_arg(params, CCSprite *);
- }
- else
- {
- break;
- }
- }
- //清空
- va_end(params);
- //排列ccprite
- pRet->initGapForChild(gap);
- ////////////添加完成////////
- pRet->autorelease();
- return pRet;
- } \
- else
- {
- delete pRet;
- pRet = NULL;
- return NULL;
- }
- }
- bool MScrollView::init()
- {
- //////////////////////////////
- // 1. super init first
- // if ( !CCLayerColor::init() )
- if ( !CCLayerColor::CCLayerColor::initWithColor(ccc4(0xff,0x00,0x00,0x80), 100, 100))
- {
- return false;
- }
- //开启触屏响应
- this->setTouchEnabled(true);
- //添加显示容器
- m_Container = CCLayer::create();
- m_Container->setAnchorPoint(ccp(0.0f,0.0f));
- m_Container->setPosition(ccp(0.0f, 0.0f));
- this->addChild(m_Container);
- //修改响应区域,默认是全屏
- CCSize screen = CCDirector::sharedDirector()->getWinSize();
- setTouchRect(CCRectMake(0, 0, screen.width, screen.height));
- //修改显示区域,默认为全屏
- this->setContentSize(screen);
- //修改剪切区域,默认为全屏
- setClipSize(screen.width,screen.height);
- //默认回调函数为空
- m_fun =NULL;
- return true;
- }
- void MScrollView::visit()
- {
- if (!m_bIsVisible)
- {
- return;
- }
- kmGLPushMatrix();
- if (m_pGrid && m_pGrid->isActive())
- {
- m_pGrid->beforeDraw();
- this->transformAncestors();
- }
- this->transform();
- //默认情况下,剪裁是禁用的
- glEnable(GL_SCISSOR_TEST);//启用剪裁测试
- float s = this->getScale();//当前layer缩放的倍数
- s *= CCDirector::sharedDirector()->getContentScaleFactor();//获取缩放倍率
- CCPoint screenPos = this->convertToWorldSpace(this->getParent()->getPosition());
- //默认不设置Scissor的大小是整个视图的大小
- glScissor((GLint)screenPos.x, (GLint)screenPos.y, (GLsizei)(m_clipSize.width*s), (GLsizei)(m_clipSize.height*s));
- //子节点处理
- if(m_pChildren)
- {
- ccArray *arrayData = m_pChildren->data;
- unsigned int i=0;
- for( ; i < arrayData->num; i++ )
- {
- CCNode *child = (CCNode*)arrayData->arr[i];
- if ( child->getZOrder() < 0 )
- {
- child->visit();
- }
- else
- {
- break;
- }
- }
- this->draw();
- for( ; i < arrayData->num; i++ )
- {
- CCNode* child = (CCNode*)arrayData->arr[i];
- child->visit();
- }
- } else
- {
- this->draw();
- }
- glDisable(GL_SCISSOR_TEST);//禁用剪裁测试
- if ( m_pGrid && m_pGrid->isActive())
- {
- m_pGrid->afterDraw(this);
- }
- kmGLPopMatrix();
- //
- }
- void MScrollView::setClipSize(float width,float height)
- {
- m_clipSize = CCSizeMake(width,height);
- }
- //TODO: 载显示容器中排列精灵
- bool MScrollView::initGapForChild(float gap)
- {
- //用于判读是否有元素
- if (m_spriteArray==NULL) return false;
- ///////////修改各个元素的位置
- //初始化当前页
- m_curpage = 0;
- //初始化总页数
- m_page = m_spriteArray->count();
- CCSprite * sp = (CCSprite *)m_spriteArray->objectAtIndex(0);
- float spwidth = sp->boundingBox().size.width/2.0f;
- float spheight = sp->boundingBox().size.height/2.0f;
- //获取一个中心点
- CCPoint pt = ccp(this->boundingBox().size.width/2.0f-spwidth,
- this->boundingBox().size.height/2.0f-spheight);
- float tY=pt.y;
- sp->setAnchorPoint(ccp(0,0));
- sp->setPosition(pt);
- for (int i = 1 ; i<m_page; i++)
- {
- spwidth = sp->boundingBox().size.width;
- pt =ccp(sp->getPositionX()+spwidth+gap,tY);
- sp = (CCSprite *)m_spriteArray->objectAtIndex(i);
- sp->setAnchorPoint(ccp(0,0));
- sp->setPosition(pt);
- }
- }
- //TODO: 滚动修正
- void MScrollView::RAnimation(CCPoint pt)
- {
- int _page = m_curpage;
- //判断移动的方向
- float f =pt.x;
- if(f>0)
- {
- // 向左移动
- CCLog("zuo ");
- _page ++;
- }
- else
- {
- //向→移动
- CCLog("you");
- _page --;
- }
- if ( !(_page>m_page-1 || _page<0))
- {
- m_curpage = _page;
- }
- CCLog("_page is : %d",_page);
- CCLog(" page is : %d",m_page);
- CCLog(" curpage is : %d",m_curpage);
- gotoPageAnimation(m_curpage);
- }
- //TODO: 拖动精灵,跟随手指移动改变位置
- void MScrollView::draySprite(float delta)
- {
- this->m_Container->setPosition(ccpAdd(this->m_Container->getPosition(), ccp(delta,0)));
- }
- //TODO: 滚动到某一页的动画
- void MScrollView::gotoPageAnimation(float page)
- {
- if (m_page == 0 ) return;
- //获得当前页的精灵
- CCSprite * sp = (CCSprite *)this->m_spriteArray->objectAtIndex(page);
- //多移动一小段距离让sprite载正中间
- float _width = sp->boundingBox().size.width * 0.5f;
- _width = m_clipSize.width * 0.5f - _width;
- //获取要到达的点
- CCPoint gotoPoint =ccp(-sp->getPositionX()+_width,this->m_Container->getPositionY());
- //计算移动到点的时间
- float _length = ccpDistance(gotoPoint,m_Container->getPosition());
- float _time = _length / MOVE_SPEED;
- //滚动到指定点
- ScrollAnimation(gotoPoint,_time);
- }
- //页面滚动动画,moveto 动画
- void MScrollView::ScrollAnimation(CCPoint offset,float time)
- {
- //如果是拖动就停止这个动作
- if (m_dragging)
- {
- this->unschedule(schedule_selector(MScrollView::MoveToAnimation));
- return;
- }
- ///////////////
- //创建移动动画
- //////////////
- CCFiniteTimeAction * scroll,*expire;
- scroll = CCMoveTo::create(time,offset);
- //添加一个回调函数
- expire = CCCallFuncN::create(this, callfuncN_selector(MScrollView::StopMoveToAnimation));
- //运行moveto动画
- m_Container->runAction(CCSequence::create(scroll, expire, NULL));
- //开启拖动判读
- this->schedule(schedule_selector(MScrollView::MoveToAnimation));
- }
- //updata,用于如果拖动就停止moveto 动作
- void MScrollView:: MoveToAnimation(float dt )
- {
- if (m_dragging)
- {
- this->m_Container->unscheduleAllSelectors();
- return;
- }
- }
- // // 添加一个回调函数,用于停止动画
- void MScrollView:: StopMoveToAnimation()
- {
- // this->unschedule(schedule_selector(MoveToAnimation));
- this->m_Container->unscheduleAllSelectors();
- }
- //消息注册
- void MScrollView::registerWithTouchDispatcher()
- {
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
- }
- bool MScrollView::ccTouchBegan(cocos2d::CCTouch *touch, cocos2d::CCEvent *event)
- {
- if (!this->isVisible()) {return false;}
- //记录按下的点
- m_touchDownPoint = CCDirector::sharedDirector()->convertToGL(touch->locationInView());
- if (!m_touchRect.containsPoint(m_touchDownPoint)){return false;}
- m_dragging = true;
- CCLog("CCtouchBegan");
- //
- return true;
- }
- void MScrollView::ccTouchMoved(CCTouch* touch, CCEvent* event)
- {
- CCLog("ccTouchMoved");
- if (!this->isVisible()){return;}
- m_touchCurPoint = CCDirector::sharedDirector()->convertToGL(touch->locationInView());
- if (!m_touchRect.containsPoint(m_touchCurPoint))
- {
- m_dragging = false;
- return ;
- }
- //如果不是按下后移动
- if(m_dragging)
- {
- CCPoint moveDelta = ccpSub(m_touchCurPoint, m_touchDownPoint);
- draySprite(moveDelta.x);
- m_dragging = false;
- }
- else
- {
- draySprite(touch->getDelta().x);
- }
- // CCLog("ccTouchMoved,x is %f::y is %f",x,y);
- }
- void MScrollView::ccTouchEnded(CCTouch* touch, CCEvent* event)
- {
- if (!this->isVisible()){return;}
- m_touchUpPoint = CCDirector::sharedDirector()->convertToGL(touch->locationInView());
- if (!m_touchRect.containsPoint(m_touchUpPoint)){ m_dragging = false;return ;}
- //判定是点击还是滑动,如果是点击执行点击函数,如果是滑动执行调整动画
- float off = ccpDistance(m_touchDownPoint,m_touchUpPoint);
- if (off < TOUCH_DELTA)
- {
- //触发点击事件
- m_fun;
- CCLog("touchclick");
- }
- else
- {
- // 滑动纠正
- //触发滑动动画
- RAnimation(ccpSub(m_touchDownPoint,m_touchUpPoint));
- }
- }
- void MScrollView::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)
- {
- }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。