//2013-11-11更新\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
通过鼠标点击事件和键盘左右键移动光标的实现原理:
主要通过每个字体的宽度,存在一个容器中,然后判断点击点的位置,来实现鼠标的点击事件和键盘左右键
(ps: 写的太乱,还有好多可以优化,你们可以和我说,我尽量修改修改。这个输入框在win32中使用,ios和android用CCEditBox)
具体实现,
NQTextField.h:
// 打开输入法,设置光标的位置在posTag处
void openIME( int posTag );
virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);
//删除文字时。根据光标当前位置,从而进行删除文字和移动光标
virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);
//存储字符总长度,为了点击时,光标位置的移动
vector<float> vec_sum_len;
//存储单个字符长度
vector<float> vec_one_len;
//保存点击区域,来移动光标的位置
vector<float> vec_click_area;
//点击的位置
int m_int_pos;
//键盘左右键点击时相应的函数
void setCursorPos( int cursor_direction );
//点击
bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
NQTextField.cpp
//打开光标和输入法
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();
}
//删除文字时。根据光标当前位置,从而进行删除文字和移动光标
bool NQTextField::onTextFieldDeleteBackward( CCTextFieldTTF * pSender, const char * delText, int nLen )
{
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::onTextFieldInsertText( CCTextFieldTTF * pSender, const char * text, int nLen )
{
//计数超过最大输入字符数,不能插入
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_pInputText->empty())
{
m_pCursorSprite->setPositionX(0);
}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;
}
//键盘左右键点击时相应的函数
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);
}
//点击
bool NQTextField::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent )
{
CCPoint touchPoint = convertTouchToNodeSpace(pTouch);
// 判断是打开输入法还是关闭输入法
if (CCRectMake(0, 0, inputFrameWidth, fontHeight).containsPoint(touchPoint))
{
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
{
closeIME();
}
return true;
}
//在HelloWorldScene.cpp中init()调用
NQTextField* text = NQTextField::textFieldWithPlaceHolder("hahaha","Arial",25);
text->setPosition(ccp( size.width/2+100,size.height/2 ));
this->addChild(text);
//接受键盘左右键的点击事件
setAccelerometerEnabled(true);
重写父类方法 virtual void didAccelerate(CCAcceleration* pAccelerationValue);
void HelloWorld::didAccelerate( CCAcceleration* pAccelerationValue )
{
if (!text->getClickText())
{
return;
}
float dirX = pAccelerationValue->x;
if ( dirX > 0.0f )
{
text->setCursorPos(1);
}
else if( dirX < 0.0f )
{
text->setCursorPos(2);
}
}