实现一个一个ITEM的拖动效果的控件 TTSliderControl
实现代码如下:
#include <iostream> #include "cocos2d.h" #include "cocos-ext.h" USING_NS_CC; USING_NS_CC_EXT; #include "ClientDefine.h" #include "vector" #include "string" using namespace std; typedef struct _SLIDER_INIT_STRUCT { CCSize m_sliderSize;//控件的尺寸 vector<CCNode *> m_nodes; //滚动的节点 int m_curCenterIndex;//当前最中间的节点下标,从0开始 }SLIDER_INIT_STRUCT; class TTSliderControl :public CCLayer { public: TTSliderControl(); ~TTSliderControl(); //实现裁剪 void visit(void); CREATE_FUNC(TTSliderControl) virtual bool init(); virtual void onEnter(); virtual void onExit(); virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent); //判断是否是点击在有效区域 bool isTouchInvalidated(CCTouch* touch); void initWithStruct(CCObject * pObj); //将某个index的node 移动到中间 void moveNodeToCenter(int index); //微调 将 node移动 offset void moveNodeOffset(float offset); //判断UI当前中间的index是哪个 int getCurCenterIndexInUI(); public : SLIDER_INIT_STRUCT m_initS; //里面的index是最终的数据 int m_curIndex; //这个index是 当前的数据 public: CC_SYNTHESIZE(SEL_CallFuncO, m_changeIndexSelector, ChangeIndexSelector); CC_SYNTHESIZE(CCNode *, m_target, Target); };
#include "TTSliderControl.h" TTSliderControl::TTSliderControl() { m_target = NULL; m_changeIndexSelector = NULL; m_curIndex = -1; } TTSliderControl::~TTSliderControl() { } //实现裁剪 void TTSliderControl:: visit(void) { glEnable(GL_SCISSOR_TEST); CCPoint selfPos = this->getPosition(); CCSize selfContentSize = this->getContentSize(); CCLOG("selfPos = %d,%d, selfContentSize =%d,%d ", selfPos.x, selfPos.y ,selfContentSize.width, selfContentSize.height ); float scaleX = CCEGLView::sharedOpenGLView()->getScaleX(); float scaleY = CCEGLView::sharedOpenGLView()->getScaleY(); CCRect viewPortRect = CCEGLView::sharedOpenGLView()->getViewPortRect(); glScissor(selfPos.x *scaleX + viewPortRect.origin.x , selfPos.y * scaleY + viewPortRect.origin.y , selfContentSize.width*scaleX, selfContentSize.height*scaleY); CCNode::visit();//显示父类的内容 glDisable(GL_SCISSOR_TEST); } bool TTSliderControl::init() { //自己响应touch事件 CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128 -1, true); return true; } void TTSliderControl::onEnter() { CCLayer::onEnter(); } void TTSliderControl::onExit() { CCLayer::onExit(); CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); } bool TTSliderControl::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { if (isTouchInvalidated(pTouch)) { return true; } else { return false; } } void TTSliderControl::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) { CCPoint prePos = CCDirector::sharedDirector()->convertToGL( pTouch->getPreviousLocationInView() ) ; prePos = convertToNodeSpace(prePos); CCPoint curPos = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView() ); curPos = convertToNodeSpace(curPos); CCPoint offsetPos = ccpSub(curPos, prePos); if (offsetPos.x ) { moveNodeOffset(offsetPos.x); } } void TTSliderControl::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { //CCPoint endPos = convertTouchToNodeSpace(pTouch); //判断当前 是哪个node在中间,然后滑动到这个node中心 int curIndexUI = getCurCenterIndexInUI(); if (curIndexUI != -1) { moveNodeToCenter(curIndexUI); } } void TTSliderControl::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) { } //判断是否是点击在有效区域 bool TTSliderControl:: isTouchInvalidated(CCTouch* touch) { CCPoint touchLocation = touch->getLocation(); CCPoint localLocation = this->convertToNodeSpace(touchLocation); CCRect rc = CCRectMake( 0, 0, this->getContentSize().width, this->getContentSize().height ); if (rc.containsPoint(localLocation)) { return true; } else { return false; } } void TTSliderControl:: initWithStruct(CCObject * pObj) { if (pObj == NULL) { return ; } m_initS = * (SLIDER_INIT_STRUCT *)pObj; //判断节点个数,如果为空,那么直接返回 if (m_initS.m_nodes.size() == 0 ) { return ; } //让 centerIndx在合理的范围内 if (m_initS.m_curCenterIndex < 0 ) { m_initS.m_curCenterIndex = 0; } if (m_initS.m_curCenterIndex >= m_initS.m_nodes.size() ) { m_initS.m_curCenterIndex = m_initS.m_nodes.size() -1 ; } //设置 控件 的尺寸 this->setContentSize(m_initS.m_sliderSize); //将 nodes都添加到 this for ( int i = 0 ; i< m_initS.m_nodes.size() ; i ++) { CCNode * tempNode = m_initS.m_nodes.at(i); if (tempNode) { this->addChild(tempNode,2); } } //根据 centerIndex设置各个child node 的位置 moveNodeToCenter(m_initS.m_curCenterIndex); } //将某个index的node 移动到中间 void TTSliderControl:: moveNodeToCenter(int index) { //让 centerIndex在合理的范围内 if (index < 0 ) { return ; } if (index >= m_initS.m_nodes.size() ) { return ; } m_initS.m_curCenterIndex = index; //遍历 整个 m_nodes CCNode * centerSliderUnit = NULL; for (int i = 0 ; i < m_initS.m_nodes.size() ; i ++) { CCNode * sliderUnit = (CCNode *) m_initS.m_nodes.at(i); //默认 node的锚点为 (0,0) CCPoint newPoint; CCLOG("node size = %f,%f", sliderUnit->getContentSize().width ,sliderUnit->getContentSize().height ); newPoint.x = (i - m_initS.m_curCenterIndex) * sliderUnit->getContentSize().width ; newPoint.y = (this->getContentSize().height - sliderUnit->getContentSize().height ) * 0.5f; CCMoveTo * moveto = CCMoveTo::create(0.25f, newPoint); sliderUnit->runAction(moveto); } //如果是改变了index if (m_curIndex != m_initS.m_curCenterIndex) { if (m_target && m_changeIndexSelector) { (m_target->*m_changeIndexSelector)(this); } } m_curIndex = m_initS.m_curCenterIndex; } //微调 将 node移动 offset void TTSliderControl:: moveNodeOffset(float offset) { //如果当前没有node,直接返回 if (m_initS.m_nodes.size() == 0 ) { return ; } //如果,已经到最左边,不再能够往左移动,直接返回 CCNode * rightMostUnit = (CCNode *) m_initS.m_nodes.at(m_initS.m_nodes.size() -1); if (rightMostUnit->getPosition().x <= 0 && offset < 0 ) { return ; } //如果,已经到了最右边,不再能够往右移动,直接返回 CCNode * leftMostUnit = (CCNode *) m_initS.m_nodes.at(0); if (leftMostUnit->getPosition().x >= 0 && offset > 0) { return ; } //遍历,所有的node都移动 int counter = m_initS.m_nodes.size(); for ( int i = 0 ; i < counter; i ++) { CCNode * tempNode = (CCNode *) m_initS.m_nodes.at(i); CCPoint oldPoint = tempNode->getPosition(); CCPoint newPoint = oldPoint; newPoint.x = oldPoint.x + offset; tempNode->setPosition(newPoint); } } //判断UI当前中间的index是哪个 int TTSliderControl:: getCurCenterIndexInUI() { //如果当前没有node,那么直接返回-1 if (m_initS.m_nodes.size() == 0) { return -1; } //遍历 int counter = m_initS.m_nodes.size(); for ( int i = 0 ; i<counter; i ++) { CCNode * tempNode = m_initS.m_nodes.at(i); CCPoint pos = tempNode->getPosition(); CCSize size = tempNode->getContentSize(); if ( (pos.x - size.width *0.5f) <= 0 && (pos.x + size.width * 0.5f) >= 0 ) { return i; } } return -1; }