本文共 9986 字,大约阅读时间需要 33 分钟。
转自:
聊天输入框 (单行输入框 ,多行可自己扩展)
实现功能:
1.普通输入
2.设置输入框显示最大宽度(PT值,cocos2d-x坐标值)
3.设置输入框允许的最大字符数量(字符Unicode)
4.输入框自动缩进(当输入字符串数量超过显示框最大宽度时,会自动向左缩进,显示最新字符串
输入框实现代码
头文件:
- #ifndefCursorInputDemo_CursorTextField_h
- #defineCursorInputDemo_CursorTextField_h
-
- #include"cocos2d.h"
-
- USING_NS_CC;
-
- classCursorTextField:publicCCTextFieldTTF,publicCCTextFieldDelegate,publicCCTouchDelegate
- {
- private:
-
- CCPointm_beginPos;
-
- CCSprite*m_pCursorSprite;
-
- CCAction*m_pCursorAction;
-
- CCPointm_cursorPos;
-
- floatinputFrameWidth;
-
- floatinputMaxLength;
- intnLenCount;
- int*codeNumType;
- intcodeCur;
- intstartCur;
- intendCur;
-
- std::string*m_pInputText;
- std::stringinpuText;
- public:
- CursorTextField();
- ~CursorTextField();
-
- staticCursorTextField*textFieldWithPlaceHolder(constchar*placeholder,constchar*fontName,floatfontSize);
-
- voidonEnter();
- voidonExit();
- boolinit();
-
- voidinitCursorSprite(intnHeight);
-
-
- virtualboolonTextFieldAttachWithIME(CCTextFieldTTF*pSender);
- virtualboolonTextFieldDetachWithIME(CCTextFieldTTF*pSender);
- virtualboolonTextFieldInsertText(CCTextFieldTTF*pSender,constchar*text,intnLen);
- virtualboolonTextFieldDeleteBackward(CCTextFieldTTF*pSender,constchar*delText,intnLen);
-
-
- boolccTouchBegan(CCTouch*pTouch,CCEvent*pEvent);
- voidccTouchEnded(CCTouch*pTouch,CCEvent*pEvent);
-
-
- boolisInTextField(CCTouch*pTouch);
-
- CCRectgetRect();
-
-
- voidopenIME();
-
- voidcloseIME();
-
- constchar*getInputText();
- voidsetInpuntText(char*text);
- voidsetInputWidth(floatwidth);
- voidsetInputMaxLength(floatlength);
-
- intUtf82Unicode(LPWSTRout,intoutsize,LPSTRin,intinsize);
- };
-
- #endif
cpp文件:
- #include"CursorTextField.h"
-
- conststaticfloatDELTA=0.5f;
-
- usingnamespacecocos2d;
- usingnamespacestd;
-
- CursorTextField::CursorTextField()
- {
- CCTextFieldTTF();
-
- m_pCursorSprite=NULL;
- m_pCursorAction=NULL;
-
- m_pInputText=NULL;
- codeNumType=NULL;
- }
-
- CursorTextField::~CursorTextField()
- {
- CC_SAFE_DELETE(m_pInputText);
- CC_SAFE_DELETE_ARRAY(codeNumType);
- }
-
- voidCursorTextField::onEnter()
- {
- CCTextFieldTTF::onEnter();
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,0,false);
- this->setDelegate(this);
- }
-
- CursorTextField*CursorTextField::textFieldWithPlaceHolder(constchar*placeholder,constchar*fontName,floatfontSize)
- {
- CursorTextField*pRet=newCursorTextField();
- if(pRet&&pRet->initWithString("",fontName,fontSize))
- {
- pRet->autorelease();
- if(placeholder)
- {
- pRet->setPlaceHolder(placeholder);
- }
- pRet->init();
- pRet->initCursorSprite(fontSize);
- pRet->setHorizontalAlignment(kCCTextAlignmentLeft);
- returnpRet;
- }
- CC_SAFE_DELETE(pRet);
- returnNULL;
- }
-
- boolCursorTextField::init(){
- this->inputFrameWidth=400;
- this->inputMaxLength=38;
- this->nLenCount=0;
- this->codeNumType=newint[50];
- this->codeCur=0;
- this->startCur=0;
- this->endCur=0;
- inpuText="";
- returntrue;
- }
- voidCursorTextField::initCursorSprite(constintmHeight)
- {
-
- constintcolumn=4;
- constintnHeight=(constint)mHeight;
- intpixels[25][column];
- for(inti=0;i<nHeight;++i){
- for(intj=0;j<column;++j){
- pixels[i][j]=0xffffffff;
- }
- }
- CCTexture2D*texture=newCCTexture2D();
- texture->initWithData(pixels,kCCTexture2DPixelFormat_RGB888,1,1,CCSizeMake(column,nHeight));
- m_pCursorSprite=CCSprite::createWithTexture(texture);
- CCSizewinSize=getContentSize();
- m_cursorPos=ccp(0,winSize.height/2);
- m_pCursorSprite->setPosition(m_cursorPos);
- this->addChild(m_pCursorSprite);
- m_pCursorSprite->setVisible(false);
- m_pCursorAction=CCRepeatForever::create((CCActionInterval*)CCSequence::create(CCFadeOut::create(0.25f),CCFadeIn::create(0.25f),NULL));
- m_pCursorSprite->runAction(m_pCursorAction);
- m_pInputText=newstd::string();
- }
-
- boolCursorTextField::ccTouchBegan(cocos2d::CCTouch*pTouch,cocos2d::CCEvent*pEvent)
- {
- m_beginPos=pTouch->getLocation();
- returntrue;
- }
-
- CCRectCursorTextField::getRect()
- {
- CCSizesize=getContentSize();
- returnCCRectMake(0,-size.height/2,inputFrameWidth,size.height);
- }
-
-
- constchar*CursorTextField::getInputText(){
- constchar*text=m_pInputText->c_str();
- returntext;
- }
-
-
- voidCursorTextField::setInpuntText(char*text){
- *m_pInputText="";
- setString(text);
- m_pCursorSprite->setPositionX(0);
- CC_SAFE_DELETE_ARRAY(codeNumType);
- codeNumType=newint[50];
- codeCur=0;
- startCur=0;
- endCur=0;
- inpuText="";
- }
-
-
- voidCursorTextField::setInputWidth(floatwidth){
- this->inputFrameWidth=width;
- }
-
-
- voidCursorTextField::setInputMaxLength(floatlength){
- this->inputMaxLength=length;
- }
-
-
- boolCursorTextField::isInTextField(cocos2d::CCTouch*pTouch)
- {
- returngetRect().containsPoint(convertTouchToNodeSpaceAR(pTouch));
- }
-
- voidCursorTextField::ccTouchEnded(cocos2d::CCTouch*pTouch,cocos2d::CCEvent*pEvent)
- {
- CCPointendPos=pTouch->getLocation();
-
- if(::abs(endPos.x-m_beginPos.x)>DELTA||
- ::abs(endPos.y-m_beginPos.y))
- {
-
- m_beginPos.x=m_beginPos.y=-1;
- return;
- }
-
-
- isInTextField(pTouch)?openIME():closeIME();
- }
-
-
- boolCursorTextField::onTextFieldAttachWithIME(cocos2d::CCTextFieldTTF*pSender)
- {
- if(m_pInputText->empty()){
- returnfalse;
- }
- m_pCursorSprite->setPositionX(getContentSize().width);
- returnfalse;
- }
-
-
-
-
-
- boolCursorTextField::onTextFieldInsertText(cocos2d::CCTextFieldTTF*pSender,constchar*text,intnLen)
- {
- std::stringsText=m_pInputText->c_str();
- wchar_t*wText=newwchar_t[200];
- chart[200];
- memset(t,0,200);
- strcpy(t,sText.c_str());
-
- intcou=Utf82Unicode(wText,200,t,sText.length());
-
- if(cou>=inputMaxLength)returntrue;
-
- if(text[0]=='\n')
- returntrue;
-
- m_pInputText->append(text);
-
-
- CCLabelTTF*ttf=CCLabelTTF::create(text,"Verdana-Bold",26);
- floatteWidth=ttf->getContentSize().width;
- CCLOG("anycodelength---%f",teWidth);
-
-
- inpuText.append(text);
-
- codeNumType[codeCur++]=nLen;
- std::string*localText=m_pInputText;
- setString(m_pInputText->c_str());
-
- if(getContentSize().width>inputFrameWidth){
-
- setString(inpuText.c_str());
- while(getContentSize().width>inputFrameWidth){
- intnnLen=nLen;
- if(codeNumType[startCur]==1){
- nnLen=1;
- }
- if(codeNumType[startCur]==3){
- nnLen=3;
- }
- startCur++;
- nLenCount+=nnLen;
- floatgap=localText->size()-nLenCount;
- inpuText=localText->substr(nLenCount,gap);
- setString(inpuText.c_str());
- floatcoWidth=getContentSize().width;
- }
- }
- else{
-
- nLenCount=0;
- startCur=0;
- setString(m_pInputText->c_str());
- }
-
- m_pCursorSprite->setPositionX(getContentSize().width);
- CC_SAFE_DELETE_ARRAY(wText);
- returntrue;
- }
-
-
-
-
-
-
- boolCursorTextField::onTextFieldDeleteBackward(cocos2d::CCTextFieldTTF*pSender,constchar*delText,intnLen)
- {
-
- m_pInputText->resize(m_pInputText->size()-nLen);
-
- codeNumType[codeCur--]=0;
- std::string*localText=m_pInputText;
- setString(m_pInputText->c_str());
- if(getContentSize().width>inputFrameWidth){
-
- while(getContentSize().width>inputFrameWidth){
- intnnLen=nLen;
- if(codeNumType[startCur-1]==1){
- nnLen=1;
- }
- if(codeNumType[startCur-1]==3){
- nnLen=3;
- }
- nLenCount-=nnLen;
- startCur--;
- if(startCur<=0)
- startCur=0;
- if(nLenCount<=0)
- nLenCount=0;
- floatgap=localText->size()-nLenCount;
- conststd::stringtext=localText->substr(nLenCount,gap);
- setString(text.c_str());
- inpuText=text;
- }
- }
- else{
- nLenCount=0;
- startCur=0;
- setString(m_pInputText->c_str());
- }
-
- m_pCursorSprite->setPositionX(getContentSize().width);
- if(m_pInputText->empty()){
- m_pCursorSprite->setPositionX(0);
- }
-
- returntrue;
- }
-
- boolCursorTextField::onTextFieldDetachWithIME(cocos2d::CCTextFieldTTF*pSender)
- {
- returnfalse;
- }
-
- voidCursorTextField::openIME()
- {
- m_pCursorSprite->setVisible(true);
- this->attachWithIME();
- }
-
- voidCursorTextField::closeIME()
- {
- m_pCursorSprite->setVisible(false);
- this->detachWithIME();
- }
-
- voidCursorTextField::onExit()
- {
- CCTextFieldTTF::onExit();
- CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
- }
- intCursorTextField::Utf82Unicode(LPWSTRout,intoutsize,LPSTRin,intinsize)
- {
-
-
- if(out==NULL||in==NULL||insize<0)
- {
- return-1;
- }
- inttypeCount=0;
- inttotalNum=0;
- char*p=in;
- for(inti=0;i<insize;i++)
- {
- if(*p>=0x00&&*p<=0x7f)
- {
- p++;
- totalNum+=1;
- }
- elseif((*p&(0xe0))==0xc0)
- {
- p++;
- p++;
- totalNum+=1;
- }
- elseif((*p&(0xf0))==0xe0)
- {
- p++;
- p++;
- p++;
- totalNum+=1;
- }
- }
- if(outsize<totalNum)
- {
- return-1;
- }
-
- intresultsize=0;
-
- p=in;
- char*tmp=(char*)out;
- while(*p)
- {
- if(*p>=0x00&&*p<=0x7f)
- {
- *tmp=*p;
- tmp++;
-
- tmp++;
- resultsize+=1;
- }
- elseif((*p&0xe0)==0xc0)
- {
- wchar_tt=0;
- chart1=0;
- chart2=0;
-
- t1=*p&(0x1f);
- p++;
- t2=*p&(0x3f);
-
- *tmp=t2|((t1&(0x03))<<6);
- tmp++;
- *tmp=t1>>2;
- tmp++;
- resultsize+=1;
- }
- elseif((*p&(0xf0))==0xe0)
- {
- wchar_tt=0;
- wchar_tt1=0;
- wchar_tt2=0;
- wchar_tt3=0;
- t1=*p&(0x1f);
- p++;
- t2=*p&(0x3f);
- p++;
- t3=*p&(0x3f);
-
- *tmp=((t2&(0x03))<<6)|t3;
- tmp++;
- *tmp=(t1<<4)|(t2>>2);
- tmp++;
- resultsize+=1;
- }
- p++;
- }
- /*不考虑结束符,如果考虑则打开此段!
- *tmp='/0';
- tmp++;
- *tmp='/0';
- resultsize+=2;
- */
- returnresultsize;
- }
上面代码是通是UTF-8转Unicode来获取字符数量。当输入字符数量过多时,可能字节大小会超过声明的char数组大小,导致出现越界情况,程序崩溃。
解决方法一:根据限定字符数量,将char数组大小声明为最大数量,来避免越界情况出生
解决方法二:定义一个私有变量unicodeCount(名字随意取)来记录输入字符的总数量。由于onTextFieldInsertText,onTextFieldDeleteBackward这两个方法都是在我们输入一个完整字符或者减去一个完整字符时调用一次,所以将unicodeCount++放入onTextFieldInsertText,将unicodeCount--放入onTextFieldDeleteBackward中,可以完成输入字符数量的保存。这样就可以免去UTF-8转Unicode的操作,完全避免越界情况产生,也提高了效率
效率方面尚未优化,请参考自行优化,只提供一个解决思路
接下来将会写一篇光于cocos2d-普通文本显示框,不支持富文本,主要提供自动换行解决思路,以解决当前CCLabelTTF自动换行Bug的替代方案
转载地址:http://gtmvn.baihongyu.com/