多的不说,我这个学渣,我写的代码比较搓!忍耐下吧!
CursorTextField.h
#ifndef _CursorTextField_H_ #define _CursorTextField_H_ #include "cocos2d.h" USING_NS_CC; class CursorTextField : public TextFieldTTF,public TextFieldDelegate,public IMEDelegate { private: // 点击开始位置 Point m_beginPos; // 光标精灵 Sprite * m_pCursorSprite; // 光标动画 Action *m_pCursorAction; // 光标坐标 Point m_cursorPos; //输入框长度 float inputFrameWidth; //允许输入的最大字符数Unicode float inputMaxLength; int nLenCount; int codeNumType[50]; //每个字符对应的字节数量 int codeCur; //当前第几个字符 int startCur; //行开头字符下标 int endCur; //行末尾下标 // 输入框总内容 std::string m_pInputText; std::string inpuText; //当前输入框内容 public: CursorTextField(); ~CursorTextField(); // static static CursorTextField * textFieldWithPlaceHolder(cocos2d::Node * node,const char *placeholder,const char *fontName,float fontSize); // Layer void onEnter(); void onExit(); bool init(); // 初始化光标精灵 void initCursorSprite(int nHeight); // TextFieldDelegate virtual bool onTextFieldAttachWithIME(TextFieldTTF *pSender) override; virtual bool onTextFieldDetachWithIME(TextFieldTTF * pSender) override; virtual bool onTextFieldInsertText(cocos2d::TextFieldTTF* sender,const char * text,size_t nLen) override; virtual bool onTextFieldDeleteBackward(cocos2d::TextFieldTTF* sender,const char * delText,size_t nLen) override; virtual void setPosition(const Point& pos); virtual void setPosition(float &x,float &y); void setCursorPositionX(float x); // 设置光标x位置 // 把光标添加到和输入框一起的层中 void AddCursor(Node *node); // Layer Touch bool onTouchBegan(Touch *pTouch,Event *pEvent); void onTouchEnded(Touch *pTouch,Event *pEvent); // 判断是否点击在TextField处 bool isInTextField(Touch *pTouch); // 得到TextField矩形 Rect getRect(); // 打开输入法 void openIME(); // 关闭输入法 void closeIME(); std::string split_text(std::string name,int len,int start); const char* getInputText(); void setInpuntText(char* text); void setInputWidth(float width); void setInputMaxLength(float length); cocos2d::Node * parentNode; protected: EventListenerTouchOneByOne * listener; }; #endifCursorTextField.cpp
#include "CursorTextField.h" #include "MyCharSet.h" const static float DELTA = 0.5f; using namespace cocos2d; using namespace std; CursorTextField::CursorTextField() { TextFieldTTF(); m_pCursorSprite = NULL; } CursorTextField::~CursorTextField() { } void CursorTextField::onEnter() { TextFieldTTF::onEnter(); listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(CursorTextField::onTouchBegan,this); listener->onTouchEnded = CC_CALLBACK_2(CursorTextField::onTouchEnded,this); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraPHPriority(listener,this); this->setDelegate(this); } CursorTextField * CursorTextField::textFieldWithPlaceHolder(Node * node,float fontSize) { auto pRet = new CursorTextField(); pRet->parentNode = node; if (pRet && ((TextFieldTTF*)pRet)->initWithPlaceHolder(placeholder,fontName,fontSize)) { pRet->autorelease(); if (placeholder) { pRet->setPlaceHolder(placeholder); } pRet->init(); pRet->initCursorSprite(fontSize); pRet->setHorizontalAlignment(kCCTextAlignmentLeft); return pRet; } CC_SAFE_DELETE(pRet); return NULL; } bool CursorTextField::init(){ this->inputFrameWidth = 400; this->inputMaxLength = 16; this->nLenCount = 0; memset(codeNumType,sizeof(codeNumType)); this->codeCur = 0; this->startCur = 0; this->endCur = 0; inpuText = ""; return true; } void CursorTextField::initCursorSprite(const int mHeight) { int column = 2; int nHeight = 20; int pixels[50][2]; for (int i = 0; i < nHeight; ++i) { for (int j = 0; j < column; ++j) { pixels[i][j] = 0xffffffff; } } Texture2D* texture = new Texture2D(); texture->initWithData(pixels,20,Texture2D::PixelFormat::RGB888,4,mHeight,CCSizeMake(column,nHeight)); m_pCursorSprite = Sprite::createWithTexture(texture); texture->autorelease(); if (m_pCursorSprite == nullptr) { CCLOG("NULL"); } Size winSize = getContentSize(); m_pCursorSprite->setVisible(false); parentNode->addChild(m_pCursorSprite); m_pCursorAction = RepeatForever::create(Sequence::create(FadeOut::create(0.25f),FadeIn::create(0.25f),NULL)); m_pCursorSprite->runAction(m_pCursorAction); } void CursorTextField::setPosition(float &x,float &y) { Point posi(x,y); setPosition(posi); } void CursorTextField::setPosition(const Point& pos) { TextFieldTTF::setPosition(pos); // 设置光标位置 if (NULL != m_pCursorSprite) { Size winSize = getContentSize(); m_cursorPos = ccp(0,0/*winSize.height / 2*/); m_cursorPos = m_cursorPos + pos; m_pCursorSprite->setPosition(m_cursorPos.x,m_cursorPos.y + m_pCursorSprite->getContentSize().height / 2.0); } } void CursorTextField::setCursorPositionX(float x) // 设置光标x位置 { Point pt = getPosition(); // 获取输入框位置 m_pCursorSprite->setPositionX(pt.x + x); } // 把光标添加到和输入框一起的层中 void CursorTextField::AddCursor(Node *node) { if (NULL != node && NULL != m_pCursorSprite) { node->addChild(m_pCursorSprite); m_pCursorSprite->setPositionY(getContentSize().height / 2.0); m_pCursorSprite->runAction(m_pCursorAction); } } bool CursorTextField::onTouchBegan(cocos2d::Touch *pTouch,cocos2d::Event *pEvent) { m_beginPos = pTouch->getLocation(); return true; } Rect CursorTextField::getRect() { Size size = getContentSize(); return CCRectMake(0,-size.height / 2,inputFrameWidth,size.height); } //获取输入框内容 const char* CursorTextField::getInputText(){ const char* text = m_pInputText.c_str(); return text; } //设置输入框内容 void CursorTextField::setInpuntText(char* text){ m_pInputText = ""; setString(text); m_pCursorSprite->setPositionX(this->getPosition().x); memset(codeNumType,sizeof(codeNumType)); codeCur = 0; startCur = 0; endCur = 0; inpuText = ""; } //设置输入框宽度 一旦字符串宽度超度这个长度 字符串会自动向左缩进 void CursorTextField::setInputWidth(float width){ this->inputFrameWidth = width; } //设置输入宽显示的最大字符数量Unicode void CursorTextField::setInputMaxLength(float length){ this->inputMaxLength = length; } //判断点击事件,是否响应在输入框范围内 bool CursorTextField::isInTextField(cocos2d::Touch *pTouch) { return getRect().containsPoint(convertTouchToNodeSpaceAR(pTouch)); } void CursorTextField::onTouchEnded(cocos2d::Touch *pTouch,cocos2d::Event *pEvent) { Point endPos = 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(); } //弹出手机键盘时响应事件 bool CursorTextField::onTextFieldAttachWithIME(cocos2d::TextFieldTTF *pSender) { if (m_pInputText.empty()) { return false; } m_pCursorSprite->setPositionX(this->getPosition().x + getContentSize().width); return false; } //当有输入进来时响应 //@param pSender 发送事件对象 //@param text 输入内容 //@param 内容字节长度 bool CursorTextField::onTextFieldInsertText(cocos2d::TextFieldTTF* sender,size_t nLen) { int j = 0 ; std::string mytext = text; for (j = 0; j < mytext.size();) { std::string sText = m_pInputText.c_str(); wchar_t* wText = new wchar_t[200]; char t[200]; memset(t,sizeof(t)); strcpy(t,sText.c_str()); int unisize = 0; int cou = MyCharSet::getinstence()->utf8_to_unicode((uint8_t*)t,(uint16_t **)wText,&unisize); std::string ss = split_text(mytext,1,j); j += ss.length(); //当字符数量超过规定值 不做处理 if (cou >= inputMaxLength) { CC_SAFE_DELETE_ARRAY(wText); return true; } //return true; //屏蔽回车输入 if (ss == "\n") { CC_SAFE_DELETE_ARRAY(wText); continue; } //输入框总内容添加 m_pInputText.append(ss); //输入框当前字符串添加 inpuText.append(ss); //当前字符的长度 codeNumType[codeCur++] = ss.length(); std::string localText = m_pInputText; setString(m_pInputText); //如果总字符串的长度大于指定宽度 if (getContentSize().width > inputFrameWidth){ //大于,截取字符串,直到字符串的长度小于指定宽度为止 setString(inpuText); while (getContentSize().width > inputFrameWidth){ int nnLen = ss.length(); if (codeNumType[startCur] == 1){ nnLen = 1; } if (codeNumType[startCur] == 3){ nnLen = 3; } startCur++; nLenCount += nnLen; float gap = localText.size() - nLenCount; inpuText = localText.substr(nLenCount,gap); setString(inpuText.c_str()); float coWidth = getContentSize().width; } } else{ //小于,直接设置显示总字符串 nLenCount = 0; startCur = 0; setString(m_pInputText); } //设置光标位置 m_pCursorSprite->setPositionX(this->getPosition().x + getContentSize().width); CC_SAFE_DELETE_ARRAY(wText); //AndroidShowtext(mychar,1); } return true; } //当有输入进来时响应 //@param pSender 发送事件对象 //@param text 删除内容 //@param 内容字节长度 bool CursorTextField::onTextFieldDeleteBackward(cocos2d::TextFieldTTF* sender,size_t nLen) { // 将总字符串长度减去nLen字节长 m_pInputText.resize(m_pInputText.size() - nLen); //当前字符数减一 codeNumType[codeCur--] = 0; std::string localText = m_pInputText; setString(m_pInputText); if (getContentSize().width > inputFrameWidth){ //大于指定宽度,截取字符串,直到字符串长度小于指定宽度 while (getContentSize().width > inputFrameWidth){ int nnLen = 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; float gap = localText.size() - nLenCount; const std::string text = localText.substr(nLenCount,gap); setString(text); inpuText = text; } } else{ nLenCount = 0; startCur = 0; setString(m_pInputText.c_str()); } //设置光标位置 m_pCursorSprite->setPositionX(this->getPosition().x + getContentSize().width); if (m_pInputText.empty()) { m_pCursorSprite->setPositionX(this->getPosition().x); } return true; } bool CursorTextField::onTextFieldDetachWithIME(cocos2d::TextFieldTTF *pSender) { return false; } void CursorTextField::openIME() { m_pCursorSprite->setVisible(true); setString(m_pInputText); ((TextFieldTTF *)this)->attachWithIME(); } void CursorTextField::closeIME() { m_pCursorSprite->setVisible(false); //auto pTextField = (TextFieldTTF *)pRet; ((TextFieldTTF *)this)->detachWithIME(); } void CursorTextField::onExit() { TextFieldTTF::onExit(); Director::getInstance()->getEventDispatcher()->removeEventListener(listener); } std::string CursorTextField::split_text(std::string name,int start) { int i = start; std::string str; if (name[i] < 0) { i++; } //while (name[i] < 0) //{ // i++; // if (i - start == 2) // { // break; // } //} if (start == i) { str = name.substr(start,1); } else { str = name.substr(start,3); } //log("mysubstr %s",str.c_str()); return str; }
字节转换的
MyCharSet.h
#pragma once #include "stdint.h" #include "stdio.h" #include <string.h> #include <malloc.h> #include <memory.h> class MyCharSet { public: MyCharSet(); ~MyCharSet(); static MyCharSet * getinstence(); static void destoryinstence(); int utf8_to_unicode(uint8_t *in,uint16_t **out,int *outsize); int unicode_to_utf8(uint16_t *in,int insize,uint8_t **out); };
MyCharSet.cpp
#include "MyCharSet.h" static MyCharSet *_MyCharSet = NULL; MyCharSet::MyCharSet() { } MyCharSet::~MyCharSet() { } MyCharSet * MyCharSet::getinstence() { if (_MyCharSet == NULL) { _MyCharSet = new MyCharSet(); } return _MyCharSet; } void MyCharSet::destoryinstence() { if (_MyCharSet != NULL) { delete _MyCharSet; } } int MyCharSet::utf8_to_unicode(uint8_t *in,int *outsize) { uint8_t *p = in; uint16_t *result = NULL; int resultsize = 0; uint8_t *tmp = NULL; result = (uint16_t *)malloc(strlen((char *)in) * 2 + 2); /* should be enough */ memset(result,strlen((char*)in) * 2 + 2); tmp = (uint8_t *)result; while (*p) { if (*p >= 0x00 && *p <= 0x7f) { *tmp = *p; tmp++; *tmp = '\0'; resultsize += 1; } else if ((*p & (0xff << 5)) == 0xc0) { uint16_t t = 0; uint8_t t1 = 0; uint8_t t2 = 0; t1 = *p & (0xff >> 3); p++; t2 = *p & (0xff >> 2); *tmp = t2 | ((t1 & (0xff >> 6)) << 6);//t1 >> 2; tmp++; *tmp = t1 >> 2;//t2 | ((t1 & (0xff >> 6)) << 6); tmp++; resultsize += 1; } else if ((*p & (0xff << 4)) == 0xe0) { uint16_t t = 0; uint8_t t1 = 0; uint8_t t2 = 0; uint8_t t3 = 0; t1 = *p & (0xff >> 3); p++; t2 = *p & (0xff >> 2); p++; t3 = *p & (0xff >> 2); //Little Endian *tmp = ((t2 & (0xff >> 6)) << 6) | t3;//(t1 << 4) | (t2 >> 2); tmp++; *tmp = (t1 << 4) | (t2 >> 2);//((t2 & (0xff >> 6)) << 6) | t3; tmp++; resultsize += 1; } p++; } //*tmp = '\0'; //tmp++; //*tmp = '\0'; //resultsize += 2; //*out = result; //*outsize = resultsize; return resultsize; } int MyCharSet::unicode_to_utf8(uint16_t *in,uint8_t **out) { int i = 0; int outsize = 0; int charscount = 0; uint8_t *result = NULL; uint8_t *tmp = NULL; charscount = insize / sizeof(uint16_t); result = (uint8_t *)malloc(charscount * 3 + 1); memset(result,charscount * 3 + 1); tmp = result; for (i = 0; i < charscount; i++) { uint16_t unicode = in[i]; if (unicode >= 0x0000 && unicode <= 0x007f) { *tmp = (uint8_t)unicode; tmp += 1; outsize += 1; } else if (unicode >= 0x0080 && unicode <= 0x07ff) { *tmp = 0xc0 | (unicode >> 6); tmp += 1; *tmp = 0x80 | (unicode & (0xff >> 2)); tmp += 1; outsize += 2; } else if (unicode >= 0x0800 && unicode <= 0xffff) { *tmp = 0xe0 | (unicode >> 12); tmp += 1; *tmp = 0x80 | (unicode >> 6 & 0x00ff); tmp += 1; *tmp = 0x80 | (unicode & (0xff >> 2)); tmp += 1; outsize += 3; } } *tmp = '\0'; *out = result; return outsize; }
如果使用直接:
CursorTextField *m_pCursorInputLayer = CursorTextField::textFieldWithPlaceHolder(this,"click and input","fonts/Marker Felt.ttf",40); m_pCursorInputLayer->setAnchorPoint(ccp(0.0f,0.0f)); m_pCursorInputLayer->setInputWidth(visibleSize.width); Vec2 posi(0,visibleSize.height / 2); m_pCursorInputLayer->setPosition(posi); this->addChild(m_pCursorInputLayer,1);
这个输入自行扩展,现在我的需求不用不需要,也就没写,大家可以自行输入。
给个思路大家吧,在切割字符的时候可以自行添加回车,我暂时想到这样来做!
我做的效果!