多的不说,我这个学渣,我写的代码比较搓!忍耐下吧!
CursorTextField.h
#ifndef _CursorTextField_H_CursorTextField.cpp
#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;
};
#endif
#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;
}
//设置输入宽显示的最大字符数量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, 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);
这个输入自行扩展,现在我的需求不用不需要,也就没写,大家可以自行输入。
给个思路大家吧,在切割字符的时候可以自行添加回车,我暂时想到这样来做!
我做的效果!
需求来了,希望可以移动光标进行删除指定的!所以下一篇讲讲光标移动实现!