申明:此类借鉴了网上的部分代码,还有不完善的地方需要修改,不过基本功能都实现了。放置此处以飨众生。欢迎各位同学提出宝贵的意见或建议。
#pragma once
#include "cocos2d.h"
USING_NS_CC;
using namespace std;
class NQTextField : public CCTextFieldTTF, public CCTextFieldDelegate, public CCTouchDelegate
{
public:
NQTextField();
~NQTextField();
public:
// static
static NQTextField* textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);
// CCLayer
void onEnter();
void onExit();
bool init();
// 初始化光标精灵
void initCursorSprite(int mHeight);
// CCTextFieldDelegate
virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);
virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);
// CCLayer Touch
bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
// 打开输入法
void openIME( int posTag );
// 关闭输入法
void closeIME();
private:
//光标
CCSprite* m_pCursorSprite;
//字体大小
float fontHeight;
//输入框的宽度
float inputFrameWidth;
//输入框的内容
string *m_pInputText;
//用户写入的placeholder
std::string m_placeholder;
//是否为密码框
bool m_bPassword;
//密码字符串*
std::string str_password;
//存储输入框中字母的字节,用于判断是否为中文
vector<int> vec_len;
//输入字符的最大长度
int m_maxInputWidth;
//字符的计数
int m_inputFlag;
//存储字符总长度,为了点击时,光标位置的移动
vector<float> vec_sum_len;
//存储单个字符长度
vector<float> vec_one_len;
//保存点击区域,来移动光标的位置
vector<float> vec_click_area;
//点击的位置
int m_int_pos;
//现在为止,还没用
//是否点击该文本框
bool m_bClickText;
public:
//设置为密码框
void setPassword( bool isPasswrod = true );
//设置点击区域的宽度 默认宽度200
void setInputFrameWidth( float newWidth );
//设置输入框的内容
void setInputText( std::string newInputText );
//得到输入框的内容
const char* getText();
//设置可以输入的最多字符数
void setMaxLength(int newMaxInputWidth);
//判断是否为中文
bool isChinese();
//得到输入框的长度
int getInputWidth();
//下面两个函数现在为止,还没用
bool getClickText();
void setCursorPos( int cursor_direction );
};
#include "NQTextField.h"
using namespace cocos2d;
using namespace std;
NQTextField::NQTextField(void)
{
CCTextFieldTTF();
}
NQTextField::~NQTextField(void)
{
}
NQTextField* NQTextField::textFieldWithPlaceHolder( const char *placeholder, const char *fontName, float fontSize )
{
NQTextField *pRet = new NQTextField();
if(pRet && pRet->initWithString("", 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;
}
void NQTextField::onEnter()
{
CCTextFieldTTF::onEnter();
//设置点击代理
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-128,false);
this->setDelegate(this);
}
void NQTextField::onExit()
{
CCTextFieldTTF::onExit();
//销毁点击代理
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
bool NQTextField::init()
{
//必须设置锚点(0,0);
this->setAnchorPoint(CCPointZero);
//输入框宽度
inputFrameWidth = 270;
//初始化
m_pInputText = NULL;
//得到placeholder
m_placeholder = getPlaceHolder();
//不是密码框
m_bPassword = false;
//密码框字符为空
str_password = "";
//最多可以输入字符,默认10
m_maxInputWidth = 30;
//计数默认为0
m_inputFlag = 0;
//点击的位置
m_int_pos = 0;
//没有点击文本框
m_bClickText = false;
return true;
}
//初始化光标
void NQTextField::initCursorSprite( int mHeight )
{
const int column = 1;
const int nHeight = (const int)mHeight;
int pixels[50][column];
for (int i=0; i<nHeight; ++i) {
for (int j=0; j<column; ++j) {
//pixels[i][j] = 0xffffffff;
pixels[i][j] = 0x00000000;
}
}
//创建光标精灵
CCTexture2D *texture = new CCTexture2D();
texture->initWithData(pixels, kCCTexture2DPixelFormat_RGB888, 1, 1, CCSizeMake(column, nHeight));
m_pCursorSprite = CCSprite::createWithTexture(texture);
m_pCursorSprite->setPosition(ccp(0, mHeight / 2));
this->addChild(m_pCursorSprite);
m_pCursorSprite->setVisible(false);
CCActionInterval* m_pCursorAction = CCRepeatForever::create((CCActionInterval *) CCSequence::create(CCFadeOut::create(0.25f), CCFadeIn::create(0.25f), NULL));
//CCActionInterval* m_pCursorAction = CCRepeatForever::create(CCBlink::create(0.5f,1));
m_pCursorSprite->runAction(m_pCursorAction);
/*
float scaleY = mHeight*1.0/25;
m_pCursorSprite = CCSprite::create("Login/cursor.png");
m_pCursorSprite->setScaleY(scaleY);
m_pCursorSprite->setPosition(ccp(0, mHeight / 2));
this->addChild(m_pCursorSprite);
m_pCursorSprite->setVisible(false);
CCActionInterval* m_pCursorAction = CCRepeatForever::create((CCActionInterval *) CCSequence::create(CCFadeOut::create(0.25f), CCFadeIn::create(0.25f), NULL));
m_pCursorSprite->runAction(m_pCursorAction);
*/
//输入字符
m_pInputText = new std::string();
//设置字体高度
fontHeight = mHeight*1.0f;
}
//插入文本
bool NQTextField::onTextFieldInsertText( CCTextFieldTTF * pSender, const char * text, int nLen )
{
m_pCursorSprite->setVisible(true);
//计数超过最大输入字符数,不能插入
if (m_inputFlag > m_maxInputWidth)
{
return true;
}
//屏蔽回车输入
if(text[0] == '\n')
return true;
//存储字节
vec_len.insert(vec_len.begin()+m_int_pos,nLen);
//计数加一
m_inputFlag++;
//输入框总内容添加
//m_pInputText->append(text);
int textPos = 0;
for (int i=0;i<m_int_pos;i++)
{
textPos += vec_len[i];
}
m_pInputText->insert(textPos,text);
//文本框显示字符
setString(m_pInputText->c_str());
//判断是否为密码框
if (m_bPassword)
{
str_password.append("*");
setString(str_password.c_str());
}
if (vec_one_len.size() == 0)
{
//当前字符的长度
float textWidth = getContentSize().width;
//保存长度
vec_one_len.insert(vec_one_len.begin()+m_int_pos,textWidth);
vec_sum_len.push_back(textWidth);
}
else
{
//当前字符的长度
float textWidth = getContentSize().width - vec_sum_len[vec_sum_len.size()-1];
//保存长度
vec_one_len.insert(vec_one_len.begin()+m_int_pos,textWidth);
vec_sum_len.clear();
vec_click_area.clear();
float cursorPosX = 0.0f;
float clickPosX = 0.0f;
for (int i=0;i<vec_one_len.size();i++)
{
cursorPosX += vec_one_len[i];
vec_sum_len.push_back(cursorPosX);
if (i == 0)
{
clickPosX = vec_one_len[i]/2;
}
else
{
clickPosX = vec_click_area[i-1] + vec_one_len[i]/2;
}
vec_click_area.push_back(clickPosX);
}
}
//位置下标加1
m_int_pos++;
//设置光标位置
if (m_int_pos == m_inputFlag)
{
float cursorPosX = getContentSize().width;
m_pCursorSprite->setPositionX(cursorPosX);
}else
{
float cursorPosX = 0.0f;
for (int i=0;i<m_int_pos;i++)
{
cursorPosX += vec_one_len[i];
}
m_pCursorSprite->setPositionX(cursorPosX);
}
return true;
}
bool NQTextField::onTextFieldDeleteBackward( CCTextFieldTTF * pSender, const char * delText, int nLen )
{
m_pCursorSprite->setVisible(true);
if (m_int_pos == 0)
{
return true;
}
//如果有中文的话,对字符的操作
int textPos = 0;
for (int i=0;i<m_int_pos-1;i++)
{
textPos += vec_len[i];
}
m_pInputText->erase(textPos,vec_len[m_int_pos-1]);
//存储字节减一
vector<int>::iterator iter = vec_len.begin()+m_int_pos-1;
iter = vec_len.erase(iter);
//删除长度
vector<float>::iterator iter1 = vec_one_len.begin()+m_int_pos-1;
iter1 = vec_one_len.erase(iter1);
vec_sum_len.clear();
vec_click_area.clear();
for (int i=0; i<vec_one_len.size(); i++)
{
if (i == 0)
{
vec_sum_len.push_back(vec_one_len[i]);
vec_click_area.push_back(vec_one_len[i]/2);
}
else
{
vec_sum_len.push_back( vec_sum_len[i-1] + vec_one_len[i] );
vec_click_area.push_back(vec_click_area[i-1] + vec_one_len[i]/2);
}
}
//计数减一
m_inputFlag--;
//文本框显示字符
setString(m_pInputText->c_str());
//CCLOG("m_pInputText: %s",delText);
//当前字符的长度
float textWidth = getContentSize().width;
//判断是否为密码框
if (m_bPassword)
{
str_password.resize(str_password.size()-1);
setString(str_password.c_str());
}
//位置下标减一
m_int_pos--;
//设置光标位置
if (m_pInputText->empty() || m_int_pos==0 )
{
setPlaceHolder("");
m_pCursorSprite->setPositionX(0);
}
else
{
float posX = vec_sum_len[m_int_pos-1];
m_pCursorSprite->setPositionX(posX);
//m_pCursorSprite->setPositionX(getContentSize().width);
}
return true;
}
bool NQTextField::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent )
{
CCPoint touchPoint = convertTouchToNodeSpace(pTouch);
// 判断是打开输入法还是关闭输入法
if (CCRectMake(0, 0, inputFrameWidth, fontHeight).containsPoint(touchPoint))
{
m_pCursorSprite->setVisible(true);
float touchWidth = touchPoint.x/2;
CCLog("touchWidth: %lf",touchWidth);
if ( vec_click_area.size() == 0 )
{
openIME(0);
return true;
}
for (int i=0;i<vec_click_area.size();i++)
{
if (touchWidth < vec_click_area[i])
{
openIME(i);
return true;
}
}
openIME(vec_click_area.size());
}
else
{
m_pCursorSprite->setVisible(false);
closeIME();
}
return true;
}
//打开光标和输入法
void NQTextField::openIME( int posTag )
{
if (posTag != 0)
{
float posX = vec_sum_len[posTag-1];
m_pCursorSprite->setPositionX(posX);
//点击的位置
m_int_pos = posTag;
}else
{
m_pCursorSprite->setPositionX(0);
//点击的位置
m_int_pos = 0;
}
m_bClickText = true;
m_pCursorSprite->setVisible(true);
this->attachWithIME();
}
//关闭光标和输入法
void NQTextField::closeIME()
{
/*
if (m_pInputText->empty())
{
setPlaceHolder(m_placeholder.c_str());
}
*/
CCLOG("content size: %lf,%lf",this->getContentSize().width,this->getContentSize().height);
for (int i=0;i<vec_click_area.size();i++)
{
CCLOG("vec_sum_len: %lf",vec_click_area[i]);
}
m_bClickText = false;
m_pCursorSprite->setVisible(false);
CCLOG("your string is %s",this->getText());
this->detachWithIME();
}
//判断是否为中文
bool NQTextField::isChinese( )
{
for (int i=0;i<vec_len.size();i++)
{
//CCLog("vec_len[%d]: %d",i,vec_len[i]);
if (vec_len[i]>1)
{
return true;
}
}
return false;
}
//设置密码
void NQTextField::setPassword( bool isPasswrod )
{
m_bPassword = isPasswrod;
}
void NQTextField::setInputFrameWidth( float newWidth )
{
inputFrameWidth = newWidth;
}
void NQTextField::setInputText( std::string newInputText )
{
m_pInputText->append(newInputText.c_str());
}
const char* NQTextField::getText()
{
return m_pInputText->c_str();
}
void NQTextField::setMaxLength( int newMaxInputWidth )
{
m_maxInputWidth = newMaxInputWidth-1>0?(newMaxInputWidth-1):-1;
}
int NQTextField::getInputWidth()
{
int sum = 0;
for (int i=0;i<vec_len.size();i++)
{
if (vec_len[i]>1)
{
sum = sum + 2;
}
else
{
sum = sum + 1;
}
}
return sum;
}
bool NQTextField::getClickText()
{
return m_bClickText;
}
void NQTextField::setCursorPos( int cursor_direction )
{
if (cursor_direction == 1)
{
m_int_pos++;
}
else if (cursor_direction == 2)
{
m_int_pos--;
}
if (m_int_pos < 0 )
{
m_int_pos = 0;
}
if ( m_int_pos >= vec_one_len.size() )
{
m_int_pos = vec_one_len.size();
}
float cursorPosX = 0.0f;
for (int i=0;i<m_int_pos;i++)
{
cursorPosX += vec_one_len[i];
}
m_pCursorSprite->setPositionX(cursorPosX);
}