向左推进并计数的 cocos2d-x 平台的TextField(附源代码)

本文介绍了一种基于Cocos2d-x平台的TextField类的自定义实现,包括计数功能和根据输入内容动态调整显示位置的功能。详细解释了如何在输入文字时更新计数器,以及如何根据字符串长度决定文本框的显示位置,实现左对齐或右对齐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

向左推进并计数的 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);
	
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值