实现一个一个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;
}