cocos2d-x 输入框升级版 通过鼠标点击事件和键盘左右键移动光标

//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);
	}
}






评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值