向左推进并计数的 cocos2d-x 平台的TextField 继承CCTextField
原理其实很简单:但输入文字时,用UTF8 解析输入的字符串,判断字符串长度,并更新计数器,判断字符串显示区域,当大于显示区域,把aglin属性设为right ,否则设为left。看效果图
由于写的代码适合我自己的功能,因此代码仅用于参考
#ifndef __ETEXTFIELD_H__
#define __ETEXTFIELD_H__
#include "cocos2d.h"
USING_NS_CC;
class ETextField:public CCTextFieldTTF,public CCTargetedTouchDelegate
{
bool m_isPassWord;
bool m_isLowSide;//是否在低位
bool m_isTouchHandled;//是否被点击到
bool m_isTouchedFun;
CCObject* m_selectorTarget;
float m_keyboardOffset;
SEL_CallFunc m_selector;
public:
ETextField():m_isLowSide(false),m_isTouchHandled(false),m_isPassWord(false),m_isTouchedFun(false),inputStringLengthLimit(-1),m_isMove(false){};//
~ETextField(){};
static ETextField * ETextFieldWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize);//?≤?¨∑Ω∑?
static ETextField * ETextFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);
//CCTARGETEDTOUCHDELEGATE
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
//CCLAYER
virtual void onEnter();
virtual void onExit();
//CCLABEL
void setDimensions(CCSize rect){m_tDimensions=rect;};
//CCTEXTFIELDTTF
virtual void setString(const char *text);
void setString(const char *label,CCTextAlignment Alignment);
//CCIMEDelegate
virtual void keyboardWillShow(CCIMEKeyboardNotificationInfo& info);
virtual void keyboardWillHide(CCIMEKeyboardNotificationInfo& info);
void parentLayerUpMove();
void parentLayerBackMove();
void setIsPassWord(bool display){m_isPassWord=display;};
void setTouchedEvent(CCObject* SelectorTarget,SEL_CallFunc selector,bool isTargeted);
void touchedEventExecut();
virtual void insertText(const char * text, int len);
size_t inputStringLengthLimit;
size_t getStringLengthLimit() const { return inputStringLengthLimit; }
void setStringLengthLimit(size_t val) { inputStringLengthLimit = val; }
//caoxinst 20120807
bool IsUpdate;
bool m_isMove; //是否移动
int FieldWidth;//设置显示文本框的宽度
CCPoint Front; //是指文本框的居左位置
CCPoint Last; //设置文本框的居右位置
int stringLen ; //字符长度 一个汉字长度为1和 一个英文字符长度为1
int len; //限制字符串长度
CCObject* pSend;
void setisMove(bool val) { m_isMove = val; stringLen = 0; len = 0; IsUpdate = false;}
void setPsend(CCObject* psend=NULL){ pSend = psend ;}
void setStringLen(int n){len = n;}
void setFieldWidth(int width){FieldWidth = width;}
void setFieldPos(CCPoint front,CCPoint last){ Front = front; Last = last;}
void FieldMove(string insertText);
void deleteBackward();
void setinput(string strs){
*m_pInputText = strs;
}
int flags ; //在win32上 由于像素的误差 进行矫正
};
#endif
#include "ETextField.h"
#include "esun/eutils/ELog.h"
#include "cayman2/Format/Format.h"
#include "cayman2/AdviceBack/AdviceBack.h"
static int _calcCharCount(const char * pszText)
{
int n = 0;
char ch = 0;
while ((ch = *pszText))
{
CC_BREAK_IF(! ch);
if (0x80 != (0xC0 & ch))
{
++n;
}
++pszText;
}
return n;
}
bool ETextField::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
return true;
}
void ETextField::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
CCPoint touch =pTouch->locationInView(pTouch->view());
touch = CCDirector::sharedDirector()->convertToGL(touch);
CCRect rect=this->boundingBox();
//CCLog("Origin:(%f,%f) Size:(%f,%f)\n",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
m_isTouchHandled=CCRect::CCRectContainsPoint(rect, touch);
if(m_isTouchHandled)
{
this->attachWithIME();
//CCLog("Touched the TEXTFIELD");
if(m_isTouchedFun==true)
touchedEventExecut();
}
else
{
this->detachWithIME();
}
}
ETextField * ETextField::ETextFieldWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment alignment, const char *fontName, float fontSize)
{
ETextField *pRet = new ETextField();
if(pRet && pRet->initWithPlaceHolder("", dimensions, alignment, fontName, fontSize))
{
pRet->autorelease();
if (placeholder)
{
pRet->setPlaceHolder(placeholder);
}
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
ETextField * ETextField::ETextFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize)
{
ETextField *pRet = new ETextField();
if(pRet && pRet->initWithString("", fontName, fontSize))
{
pRet->autorelease();
if (placeholder)
{
pRet->setPlaceHolder(placeholder);
}
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
void ETextField::onEnter()
{
CCSize size=CCDirector::sharedDirector()->getWinSize();
CCPoint myPos=this->getPosition();
CCSize mySize = this->getContentSize();
m_keyboardOffset=size.height/2+20;
if((myPos.y-mySize.height)<m_keyboardOffset)
m_isLowSide=true;
flags = 0;
CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this,-100,false);
}
void ETextField::onExit()
{
CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
this->detachWithIME();
m_isTouchedFun=false;
}
void ETextField::keyboardWillShow(CCIMEKeyboardNotificationInfo& info)
{
//CCLog("keyboardWillShow");
if(m_isLowSide&&this->m_isTouchHandled)
parentLayerUpMove();
}
void ETextField::keyboardWillHide(CCIMEKeyboardNotificationInfo& info)
{
//CCLog("keyboardWillHide");
if(m_isLowSide)
parentLayerBackMove();
}
void ETextField::parentLayerUpMove()
{
CCNode*parent= this->getParent();
if(parent)
{
parent->stopAllActions();
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCPoint myPos = this->getPosition();
CCMoveTo *move_up=CCMoveTo::actionWithDuration(0.35f,ccp(0,m_keyboardOffset-myPos.y/2));
parent->runAction(move_up);
}
}
void ETextField::parentLayerBackMove()
{
CCNode*parent= this->getParent();
if(parent)
{
parent->stopAllActions();
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCMoveTo *move_up=CCMoveTo::actionWithDuration(0.35f,ccp(0,0));
parent->runAction(move_up);
}
}
void ETextField::setString(const char *text)
{
//string str=getString();
CC_SAFE_DELETE(m_pInputText);
if (text)
{
m_pInputText = new std::string(text);
}
else
{
m_pInputText = new std::string;
}
// if there is no input text, display placeholder instead
if (! m_pInputText->length())
{
CCLabelTTF::setString(m_pPlaceHolder->c_str());
}
else if(!m_isPassWord)
{
if(!m_isMove)
CCLabelTTF::setString(m_pInputText->c_str());
//else
// FieldMove(m_pInputText);
}else
{
int len_now=m_pInputText->length();
string passWord(len_now,'*');
CCLabelTTF::setString(passWord.c_str());
}
m_nCharCount = _calcCharCount(m_pInputText->c_str());
}
void ETextField::setString( const char *label,CCTextAlignment Alignment )
{
if (CCLabelTTF::m_pString)
{
delete CCLabelTTF::m_pString;
CCLabelTTF::m_pString = NULL;
}
CCLabelTTF::m_pString = new std::string(label);
CCTexture2D *texture;
if( CCSize::CCSizeEqualToSize( CCLabelTTF::m_tDimensions, CCSizeZero ) )
{
texture = new CCTexture2D();
texture->initWithString(label, CCLabelTTF::m_pFontName->c_str(), CCLabelTTF::m_fFontSize);
}
else
{
texture = new CCTexture2D();
texture->initWithString(label, CCLabelTTF::m_tDimensions, Alignment, CCLabelTTF::m_pFontName->c_str(), CCLabelTTF::m_fFontSize);
}
this->setTexture(texture);
texture->release();
CCRect rect = CCRectZero;
rect.size = CCLabelTTF::m_pobTexture->getContentSize();
this->setTextureRect(rect);
}
void ETextField::setTouchedEvent(CCObject* SelectorTarget,
SEL_CallFunc selector,bool isTargeted)
{
m_selectorTarget=SelectorTarget;
m_selector=selector;
m_isTouchedFun=isTargeted;
}
void ETextField::touchedEventExecut()
{
if (m_selector&&m_isTouchedFun) {
(m_selectorTarget->*m_selector)();
}
}
void ETextField::deleteBackward()
{
string front = getString();
CCTextFieldTTF::deleteBackward();
if (m_isMove &&(!m_isPassWord))
{
if(stringLen >=1)
stringLen--;
string str =getString();
CCTexture2D* delet = new CCTexture2D;
delet->initWithString(str.c_str(),"",20);
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
int n = front.length() - str.length();
if( n>=3)
flags-=n/3;
if(delet->getContentSize().width - flags*10 < FieldWidth)
#else
if(delet->getContentSize().width < FieldWidth)
#endif
{
this->setPosition(Front);
CCLabelTTF::setString(str.c_str());
}else{
this->setString(str.c_str(),CCTextAlignmentRight);
}
CC_SAFE_DELETE(delet);
if(IsUpdate&& pSend){
AdviceBack* tmp =(AdviceBack*)pSend;
tmp->upDateCount();
}
}
}
void ETextField::insertText( const char * text, int len )
{
if (getStringLengthLimit()>=0)
{
string str=getString();
if(str.size()>=getStringLengthLimit())
{
return;
}
}
std::string sInsert(text, len);
// insert \n means input end
int nPos = sInsert.find('\n');
if ((int)sInsert.npos != nPos)
{
len = nPos;
sInsert.erase(nPos);
}
if (len > 0)
{
if (m_pDelegate && m_pDelegate->onTextFieldInsertText(this, sInsert.c_str(), len))
{
// delegate doesn't want insert text
return;
}
m_nCharCount += _calcCharCount(sInsert.c_str());
if(m_isMove)
FieldMove(sInsert);
else{
std::string sText(*m_pInputText);
sText.append(sInsert);
setString(sText.c_str());
}
}
if ((int)sInsert.npos == nPos) {
return;
}
// '\n' has inserted, let delegate process first
if (m_pDelegate && m_pDelegate->onTextFieldInsertText(this, "\n", 1))
{
return;
}
// if delegate hasn't process, detach with ime as default
detachWithIME();
}
void ETextField::FieldMove( string insertText)
{
int n = StringFormat::CountUTF8(insertText);
if(( stringLen+n ) > len)
return ;
else{
m_pInputText->append(insertText);
stringLen = stringLen+n;
}
//if(IsUpdate&& pSend){ //更新计数器
// AdviceBack* tmp =(AdviceBack*)pSend;
// tmp->upDateCount();
//}
CCTexture2D* test = new CCTexture2D;
test->initWithString(m_pInputText->c_str(),"",20);
int lens = test->getContentSize().width ;
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
if(insertText.length() >= 3)
{
flags+= insertText.length()/3;
}
if((lens-flags*12) > FieldWidth)
#else
if(lens > FieldWidth)
#endif
{
this->setPosition(Last);
this->setString(m_pInputText->c_str(),CCTextAlignmentRight);
}
else
this->setString(m_pInputText->c_str(),CCTextAlignmentLeft);
CC_SAFE_DELETE(test);
}