cocos2dx3.6 实现带光标的输入框

来源:互联网 发布:java高并发orm 编辑:程序博客网 时间:2024/05/18 11:48

多的不说,我这个学渣,我写的代码比较搓!忍耐下吧!

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;//允许输入的最大字符数Unicodefloat inputMaxLength;int nLenCount;int codeNumType[50];    //每个字符对应的字节数量int codeCur;         //当前第几个字符int startCur;        //行开头字符下标int endCur;          //行末尾下标// 输入框总内容std::string m_pInputText;std::string inpuText; //当前输入框内容public:CursorTextField();~CursorTextField();// staticstatic CursorTextField * textFieldWithPlaceHolder(cocos2d::Node * node , const char *placeholder, const char *fontName, float fontSize);// Layervoid onEnter();void onExit();bool init();// 初始化光标精灵void initCursorSprite(int nHeight);// TextFieldDelegatevirtual 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 Touchbool 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;};#endif
CursorTextField.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 , const char *placeholder, const char *fontName, 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, 0, 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, 0, sizeof(codeNumType));codeCur = 0;startCur = 0;endCur = 0;inpuText = "";}//设置输入框宽度 一旦字符串宽度超度这个长度 字符串会自动向左缩进void CursorTextField::setInputWidth(float width){this->inputFrameWidth = width;}//设置输入宽显示的最大字符数量Unicodevoid 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, const char * text, 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, 0, 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, const char * delText, 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 len , 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, uint16_t **out, 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, 0, 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, int insize, 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, 0, 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);


我这个输入解决了Android上一堆输入导致的错误,大家可以仔细去看看!
这个输入自行扩展,现在我的需求不用不需要,也就没写,大家可以自行输入。

给个思路大家吧,在切割字符的时候可以自行添加回车,我暂时想到这样来做!


我做的效果!

需求来了,希望可以移动光标进行删除指定的!所以下一篇讲讲光标移动实现!

0 0