cocos2dx3.6 实现带光标的输入框(二);光标可移动

现在光标终于可移动了,然后其实主要是逻辑问题,也没什么技术含量,所以总是一大堆位置判断!再者自己能力比较水,所以代码比较挫,这里代码只有更新那部分,具体的回车什么的自己去弄就好了,其实跟这个思想差不多吧!个人觉得。

代码:

CursorTextField.h

#ifndef _CursorTextField_H_
#define _CursorTextField_H_

#include "cocos2d.h"

USING_NS_CC;

class CursorTextField : public TextFieldTTF, public TextFieldDelegate
{
private:

	// 点击开始位置
	Point m_beginPos;
	// 光标精灵
	Sprite * m_pCursorSprite;
	// 光标动画
	Action *m_pCursorAction;
	// 光标坐标
	Point m_cursorPos;
	//输入框长度
	float inputFrameWidth;
	//允许输入的最大字符数Unicode
	float inputMaxLength;
	int m_Sprite_Posi = 0;
	// 输入框总内容
	std::string m_pInputText;
	std::string inpuText; //当前输入框内容
	int fontsize = 0;
	std::string fontName;
	int nowtextlenght = 0;
	void setTextPosi(std::string , bool is_add = true);
public:
	CursorTextField();
	~CursorTextField();
	static CursorTextField * getinstance();
	// 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);
	virtual void setPositionX(Node *node , float x);

	// 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);
	void onKeyPressed(cocos2d::EventKeyboard::KeyCode, cocos2d::Event*);
	void onKeyReleased(cocos2d::EventKeyboard::KeyCode, cocos2d::Event*);

	// 判断是否点击在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;

	void BlickSpriteLeft();

	void BlickSpriteRight();
	void KeyDelete();
	float getLabelWidth(std::string str , std::string fontName, float fontsize);
	int getPosifromText(std::string str, int posi);
	int getPosiformPosi(std::string str, float posi);

	void MyRemoveFromParent();
protected:
	EventListenerTouchOneByOne * listener;
};

#endif

CursorTextField.cpp

#include "CursorTextField.h"

#include "MyCharSet.h"
#include "MyKeyInsert.h"

const static float DELTA = 0.5f;

using namespace cocos2d;
using namespace std;
static CursorTextField * _CursorTextField;
CursorTextField::CursorTextField()
{
	TextFieldTTF();

	m_pCursorSprite = NULL;
	m_Sprite_Posi = 0;
}

CursorTextField::~CursorTextField()
{
}

CursorTextField * CursorTextField::getinstance()
{
	return _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)
{
	_CursorTextField = new (std::nothrow)CursorTextField();
	_CursorTextField->parentNode = node;
	if (_CursorTextField && ((TextFieldTTF*)_CursorTextField)->initWithPlaceHolder(placeholder, fontName, fontSize))
	{
		_CursorTextField->fontsize = fontSize;
		_CursorTextField->fontName = fontName;
		_CursorTextField->autorelease();
		KeyInsert::getinstence()->addKeyBordClick(node);
		if (placeholder)
		{
			_CursorTextField->setPlaceHolder(placeholder);
		}
		_CursorTextField->init();
		_CursorTextField->initCursorSprite(fontSize);
		_CursorTextField->setHorizontalAlignment(kCCTextAlignmentLeft);
		return _CursorTextField;
	}
	CC_SAFE_DELETE(_CursorTextField);
	return NULL;
}

bool CursorTextField::init(){
	this->inputFrameWidth = 400;
	this->inputMaxLength = 16;
	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");
	}
	//m_pCursorSprite->setColor(Color3B(255, 0, 0));
	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);
	//m_pInputText = new std::string();
}

void CursorTextField::setPositionX(Node * node, float x)
{
	int i = 0;
	int count = 0;
	float width = 0.0;
	std::string str;
	if (m_Sprite_Posi <= 0)
	{
		width = 0.0;
		m_Sprite_Posi = 0;
	}
	else
	{
		std::string ss;
		for (i = 0; i < inpuText.size();)
		{
			ss = split_text(inpuText, 1, i);
			i += ss.length();
			str.append(ss);
			count++;
			if (count == m_Sprite_Posi)
			{
				break;
			}
		}
		width = getLabelWidth(str, _CursorTextField->fontName, _CursorTextField->fontsize);
	}
	width += x;
	node->setPositionX(width);
}

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_pCursorSprite->getContentSize().width , m_cursorPos.y + m_pCursorSprite->getContentSize().height / 2.0);
	}
}

void CursorTextField::setCursorPositionX(float x) // 设置光标x位置
{
	Point pt = getPosition(); // 获取输入框位置
	x += pt.x;
	setPositionX(m_pCursorSprite , 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 check;
	check.width = fontsize;
	Size size = getContentSize() + check;
	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);
	setPositionX(m_pCursorSprite, this->getPosition().x);
	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();
	if (m_pCursorSprite->isVisible())
	{
		//开始所在字节
		int len = getPosiformPosi(inpuText, m_pCursorSprite->getPositionX());
		//结束所在的字节
		int endlen = getPosiformPosi(inpuText, endPos.x);
		m_pCursorSprite->setPositionX(this->getPositionX() + getLabelWidth(inpuText.substr(0, endlen), fontName, fontsize));

		int i = 0;
		int count = 0;
		//点了前面,mposi减去字符
		if (len > endlen)
		{
			count = 0;
			for (i = endlen; i < len;)
			{
				std::string temp = split_text(inpuText, 1, i);
				count++;
				i += temp.length();
			}
			m_Sprite_Posi -= count;
		}
		//原来位置
		else if (len == endlen)
		{
		}
		//点了后面,mposi加上字符
		else
		{
			count = 0;
			for (i = len; i < endlen;)
			{
				std::string temp = split_text(inpuText, 1, i);
				count++;
				i += temp.length();
			}
			m_Sprite_Posi += count;
		}
	}
}

//弹出手机键盘时响应事件
bool CursorTextField::onTextFieldAttachWithIME(cocos2d::TextFieldTTF *pSender)
{
	if (m_pInputText.empty()) {
		return false;
	}
	//setPositionX(m_pCursorSprite , this->getPosition().x);
	return false;
}

//当有输入进来时响应
//@param pSender 发送事件对象
//@param text 输入内容
//@param  内容字节长度

bool CursorTextField::onTextFieldInsertText(cocos2d::TextFieldTTF* sender, const char * text, size_t nLen)
{
	//log("OUT   ====   %s =Length= %d", text , 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 codenum = MyCharSet::getinstence()->utf8_to_unicode((uint8_t*)t, (uint16_t **)wText, &unisize);
		//当字符数量超过规定值 不做处理
		if (codenum >= inputMaxLength && inputMaxLength != 0)
		{
			codenum = inputMaxLength;
			CC_SAFE_DELETE_ARRAY(wText);
			return true;
		}
		nowtextlenght++;
		std::string ss = split_text(mytext, 1, j);
		j += ss.length();
		//屏蔽回车输入
		if (ss == "\n")
		{
			CC_SAFE_DELETE_ARRAY(wText);
			continue;
		}
		std::string mmss = "";
		std::string mystr;
		int i = 0;
		//根据字符位置插入
		if (m_Sprite_Posi != 0)
		{

			int count = 0;
			for (i = 0; i < m_pInputText.size();)
			{
				mmss = split_text(m_pInputText, 1, i);
				i += mmss.length();
				mystr.append(mmss);
				count++;
				if (count == m_Sprite_Posi)
				{
					break;
				}
			}
		}
		//字符位置相加
		m_Sprite_Posi++;
		mystr.append(ss);
		mystr.append(m_pInputText.substr(i));
		//输入框总内容就是两个相加
		m_pInputText.clear();
		//inpuText.clear();
		m_pInputText.append(mystr);
		//inpuText.append(mystr);
		//输入框当前字符串添加
		//inpuText.append(ss);
		setTextPosi(ss, true);
		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)
{
	std::string ss;
	if (m_Sprite_Posi != 0)
	{
		int i = 0;
		int count = 0;
		for (i = 0; i < m_pInputText.size();)
		{
			ss = split_text(m_pInputText, 1, i);
			i += ss.length();
			count++;
			if (count == m_Sprite_Posi)
			{
				m_pInputText.erase(i - ss.length(), ss.length());
				//inpuText.erase(i - ss.length(), ss.length());
				break;
			}
		}
	}
	//字符位置减1
	m_Sprite_Posi--;
	//m_pInputText.resize(m_pInputText.size() - nLen);
	if (m_pInputText.size() <= 0)
	{
		m_Sprite_Posi = 0;
	}
	if (m_Sprite_Posi < 0)
	{
		m_Sprite_Posi = 0;
	}
	setTextPosi(ss , false);

	return true;
}

void CursorTextField::setTextPosi(std::string ss , bool is_add)
{
	if (inputFrameWidth <= 0)
	{
		inputFrameWidth = _CursorTextField->inputFrameWidth;
	}
	if (!is_add)
	{
		if (m_pInputText.empty())
		{
			m_Sprite_Posi = 0;
			m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() - getLabelWidth(ss, fontName, fontsize));
			setString("");
			inpuText.clear();
			return;
		}
		std::string localText = inpuText;
		int i = getPosifromText(m_pInputText, m_Sprite_Posi);
		int inlength = getPosiformPosi(inpuText, m_pCursorSprite->getPositionX());
		if (inlength == 0)
		{
			return;
		}
		std::string mystr;
		std::string instr;
		if (i >= inlength)
		{
			int reposi = i - inlength;
			for (i = 0; i < m_pInputText.length();)
			{
				std::string temp = split_text(m_pInputText, 1, i);
				if (i <= reposi && reposi < temp.length() + i)
				{
					break;
				}
				else
				{
					i += temp.length();
				}
			}
			mystr = m_pInputText.substr(i, 3);
			if (!mystr.empty())
			{
				if (mystr[2] < 0)
				{
					;
				}
				else
				{
					mystr = m_pInputText.substr(i, 1);
				}
			}
		}

		//当前输入框剔除
		std::string deletestr;
		if (inlength - 3 >= 0)
		{
			int reposi = inlength;
			for (i = 0; i < inpuText.length();)
			{
				std::string temp = split_text(inpuText, 1, i);
				if (i <= reposi && reposi <= temp.length() + i)
				{
					break;
				}
				else
				{
					i += temp.length();
				}
			}
			deletestr = inpuText.substr(i, 3);
			if (deletestr[0] < 0)
			{
				inpuText.erase(inlength - 3, 3);
			}
			else if (!deletestr.empty())
			{
				deletestr = inpuText.substr(inlength - 1, 1);
				inpuText.erase(inlength - 1, 1);
			}
			//log("%s   %s", inpuText.c_str(), deletestr.c_str());
		}
		else
		{
			deletestr = inpuText.substr(0, 3);
			if (deletestr[0] < 0)
			{
				inpuText.erase(inlength - 3, 3);
			}
			else if (!deletestr.empty())
			{
				deletestr = inpuText.substr(inlength - 1, 1);
				inpuText.erase(inlength - 1, 1);
			}
		}
		if (mystr.empty())
		{
			instr = m_pInputText.substr(inpuText.length() , 3);
			if (!instr.empty())
			{
				if (instr[0] < 0)
				{
					;
				}
				else
				{
					//instr.erase(1, 2);
					instr = m_pInputText.substr(inpuText.length(), 1);
				}
			}
			inpuText.append(instr);
		}
		std::string lastins = mystr;
		mystr.append(inpuText);
		inpuText = mystr;
		if (lastins.empty())
		{
			m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() - getLabelWidth(deletestr, fontName, fontsize));
		}
		else if (!instr.empty())
		{
			float reposi = getLabelWidth(deletestr, fontName, fontsize) - getLabelWidth(instr, fontName, fontsize);
			m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + reposi);
		}
		else if (!lastins.empty())
		{
			float reposi = getLabelWidth(lastins, fontName, fontsize) - getLabelWidth(deletestr, fontName, fontsize);
			m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + reposi);
		}
		setString(inpuText);
	}
	else
	{
		std::string localText = m_pInputText;
		setString(m_pInputText);
		//如果总字符串的长度大于指定宽度
		if (getLabelWidth(m_pInputText , fontName , fontsize) > inputFrameWidth){
			int inlength = getPosiformPosi(inpuText, m_pCursorSprite->getPositionX());
			//光标在0处,需要获取到当前输入框最后一个字符,
			if (inlength == 0)
			{
				std::string mystr = ss;
				mystr.append(inpuText);
				inpuText = mystr;
				std::string str = inpuText.substr(inpuText.length() - 1);
				if (str[0] < 0)
				{
					inpuText.resize(inpuText.length() - 3);
				}
				else
				{
					inpuText.resize(inpuText.length() - 1);
				}
				setString(inpuText);
				m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + getLabelWidth(ss, fontName, fontsize));
				return;
			}
			//光标在末尾,需要获取第一个字符
			else if (inlength == inpuText.length())
			{
				inpuText.append(ss);
				std::string str = inpuText.substr(0, 3);
				if (str[0] < 0)
				{
					inpuText.erase(0, 3);
				}
				else
				{
					str.erase(1, 2);
					inpuText.erase(0, 1);
				}
				setString(inpuText);
				float x = getLabelWidth(str, fontName, fontsize) - getLabelWidth(ss, fontName, fontsize);
				m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() - x);
				return;
			}
			//在字符两段切割
			std::string last = inpuText.substr(0 , inlength);
			std::string next = inpuText.substr(inlength);
			//字符相连
			inpuText = last;
			inpuText.append(ss);
			inpuText.append(next);
			std::string temp = inpuText.substr(0, 3);
			if (temp[0] < 0 )
			{
				inpuText.erase(0, 3);
			}
			else
			{
				inpuText.erase(0, 1);
				temp = inpuText.substr(0, 1);
			}
			float reposi = getLabelWidth(ss, fontName, fontsize) - getLabelWidth(temp, fontName, fontsize);
			m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + reposi);
			setString(inpuText);

		}
		else{
			//小于,直接设置显示总字符串
			int startCur = 0;
			setString(m_pInputText);
			inpuText = m_pInputText;
			std::string showinput;
			for (int j = 0; j < m_pInputText.size();)
			{
				std::string nowstr = split_text(m_pInputText , 1 ,j);
				showinput.append(nowstr);
				j += nowstr.length();
				startCur++;
				if (startCur == m_Sprite_Posi)
				{
					break;
				}
			}
			startCur = 0;
			m_pCursorSprite->setPositionX(this->getPosition().x + getLabelWidth(showinput, fontName, fontsize));
		}
		//设置光标位置
		//setPositionX(m_pCursorSprite, this->getPosition().x);
	}
}

bool CursorTextField::onTextFieldDetachWithIME(cocos2d::TextFieldTTF *pSender)
{
	return false;
}

void CursorTextField::openIME()
{
	m_pCursorSprite->setVisible(true);
#if ( CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	setString(m_pInputText);
#endif
	((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++;
	}
	if (start == i)
	{
		str = name.substr(start, 1);
	}
	else
	{
		str = name.substr(start, 3);
	}
	//log("mysubstr   %s", str.c_str());
	return str;
}
//向左移
void CursorTextField::BlickSpriteLeft()
{
	float posix = _CursorTextField->m_pCursorSprite->getPosition().x;
	float contextsizeposi = _CursorTextField->m_pCursorSprite->getContentSize().width / 2;
	float parentposi = _CursorTextField->getPosition().x;
	std::string str;
	//光标已在输入框最左边
	if (posix - parentposi <= contextsizeposi)
	{
		if (_CursorTextField->m_pInputText == _CursorTextField->inpuText || _CursorTextField->m_Sprite_Posi == 0)
		{
			return;
		}
		int mlength = _CursorTextField->getPosifromText(_CursorTextField->m_pInputText, _CursorTextField->m_Sprite_Posi);
		//光标在所有字符的最左边
		if (mlength <= 0)
		{
			return;
		}
		//选取光标前一个字符
		str = _CursorTextField->m_pInputText.substr(mlength - 1, 1);
		if (str[0] < 0)
		{
			str = _CursorTextField->m_pInputText.substr(mlength - 3, 3);
		}
		std::string mystr = _CursorTextField->inpuText.substr(_CursorTextField->inpuText.length() - 1, 1);
		//剔除最后一个字符
		if (mystr[0] < 0)
		{
			_CursorTextField->inpuText.resize(_CursorTextField->inpuText.length() - 3);
		}
		else
		{
			_CursorTextField->inpuText.resize(_CursorTextField->inpuText.length() - 1);
		}
		//字符相加
		str.append(_CursorTextField->inpuText);
		_CursorTextField->inpuText = str;
		_CursorTextField->setString(_CursorTextField->inpuText);
	}
	else
	{
		//只是移动
		int nlength = _CursorTextField->getPosiformPosi(_CursorTextField->inpuText, _CursorTextField->m_pCursorSprite->getPositionX());
		str = _CursorTextField->inpuText.substr(nlength - 1, 1);
		if (str[0] < 0)
		{
			str = _CursorTextField->inpuText.substr(nlength - 3, 3);
		}
		float nowposi = _CursorTextField->getLabelWidth(str, _CursorTextField->fontName, _CursorTextField->fontsize);
		_CursorTextField->m_pCursorSprite->setPositionX(_CursorTextField->m_pCursorSprite->getPositionX() - nowposi);

	}
	//光标所在所有字符中减一
	_CursorTextField->m_Sprite_Posi--;
	if (_CursorTextField->m_Sprite_Posi < 0)
	{
		_CursorTextField->m_Sprite_Posi = 0;
	}

}
//向右与左类似
void CursorTextField::BlickSpriteRight()
{

	float posix = _CursorTextField->m_pCursorSprite->getPosition().x;
	float contextsizeposi = _CursorTextField->m_pCursorSprite->getContentSize().width / 2;
	float parentposi = _CursorTextField->getPosition().x + _CursorTextField->getLabelWidth(_CursorTextField->inpuText , _CursorTextField->fontName , _CursorTextField->fontsize);
	std::string str;
	if (posix + contextsizeposi >= parentposi)
	{
		if (_CursorTextField->m_pInputText == _CursorTextField->inpuText || _CursorTextField->m_Sprite_Posi >= _CursorTextField->nowtextlenght)
		{
			return;
		}
		int mlength = _CursorTextField->getPosifromText(_CursorTextField->m_pInputText, _CursorTextField->m_Sprite_Posi);
		if (mlength == _CursorTextField->m_pInputText.length())
		{
			return;
		}
		str = _CursorTextField->m_pInputText.substr(mlength, 1);
		if (str[0] < 0)
		{
			str = _CursorTextField->m_pInputText.substr(mlength, 3);
		}
		std::string mystr = _CursorTextField->inpuText.substr(0, 1);
		if (mystr[0] < 0)
		{
			mystr = _CursorTextField->inpuText.substr(0, 3);
			_CursorTextField->inpuText.erase(0, 3);
		}
		else
		{
			_CursorTextField->inpuText.erase(0, 1);
		}
		_CursorTextField->inpuText.append(str);
		//位移差
		float posix = getLabelWidth(str, _CursorTextField->fontName, _CursorTextField->fontsize) - getLabelWidth(mystr , _CursorTextField->fontName ,_CursorTextField->fontsize);
		_CursorTextField->m_pCursorSprite->setPositionX(_CursorTextField->m_pCursorSprite->getPositionX() + posix);
		_CursorTextField->setString(_CursorTextField->inpuText);
	}
	else
	{
		int nlength = _CursorTextField->getPosiformPosi(_CursorTextField->inpuText, _CursorTextField->m_pCursorSprite->getPositionX());
		str = _CursorTextField->inpuText.substr(nlength, 1);
		if (str[0] < 0)
		{
			str = _CursorTextField->inpuText.substr(nlength, 3);
		}
		float nowposi = _CursorTextField->getLabelWidth(str, _CursorTextField->fontName, _CursorTextField->fontsize);
		_CursorTextField->m_pCursorSprite->setPositionX(_CursorTextField->m_pCursorSprite->getPositionX() + nowposi);

	}
	_CursorTextField->m_Sprite_Posi++;

}

void CursorTextField::KeyDelete()
{
	int nlength = _CursorTextField->getPosiformPosi(_CursorTextField->inpuText, _CursorTextField->m_pCursorSprite->getPositionX());
	int mlength = _CursorTextField->getPosifromText(_CursorTextField->m_pInputText, _CursorTextField->m_Sprite_Posi);
	std::string inlast;
	std::string innext;
	std::string insMNext;
	std::string insMLast;
	if (mlength == _CursorTextField->m_pInputText.length())
	{
		return;
	}
	std::string in_str = _CursorTextField->inpuText.substr(nlength, 3);
	std::string im_str = _CursorTextField->m_pInputText.substr(mlength, 3);
	if (in_str[0] < 0)
	{
		_CursorTextField->inpuText.erase(nlength, 3);
	}
	else
	{
		_CursorTextField->inpuText.erase(nlength, 1);
	}
	if (im_str[0] < 0)
	{
		_CursorTextField->m_pInputText.erase(mlength, 3);
	}
	else
	{
		_CursorTextField->m_pInputText.erase(mlength, 1);
	}
	insMNext = _CursorTextField->m_pInputText.substr(mlength + _CursorTextField->inpuText.length() - nlength, 1);
	if (insMNext[0] >= 0)
	{
		insMNext = _CursorTextField->m_pInputText.substr(mlength + _CursorTextField->inpuText.length() - nlength, 1);
	}
	else
	{
		insMNext = _CursorTextField->m_pInputText.substr(mlength + _CursorTextField->inpuText.length() - nlength, 3);
	}
	if (insMNext.empty() && mlength != nlength)
	{
		if (mlength - nlength - 3 < 0)
		{
			insMLast = _CursorTextField->m_pInputText.substr(mlength - nlength - 1, 1);
		}
		else
		{
			int lenposi = mlength - nlength;
			int i;
			for (i = 0; i < _CursorTextField->m_pInputText.length();)
			{
				std::string temp = _CursorTextField->split_text(_CursorTextField->m_pInputText, 1, i);
				if (i <= lenposi && lenposi < i + temp.length())
				{
					break;
				}
				i += temp.length();
			}
			lenposi = i;
			insMLast = _CursorTextField->m_pInputText.substr(lenposi - 3, 3);
			if (insMLast[2] >= 0)
			{
				insMLast = _CursorTextField->m_pInputText.substr(lenposi - 1, 1);
			}
		}
	}
	std::string myallstr;
	myallstr.append(insMLast);
	myallstr.append(_CursorTextField->inpuText);
	myallstr.append(insMNext);
	_CursorTextField->inpuText = myallstr;
	_CursorTextField->setString(_CursorTextField->inpuText);
	if (!insMLast.empty())
	{
		_CursorTextField->m_pCursorSprite->setPositionX(_CursorTextField->m_pCursorSprite->getPositionX() + _CursorTextField->getLabelWidth(insMLast, _CursorTextField->fontName, _CursorTextField->fontsize));
	}
}
//根据string获取字符宽度
float CursorTextField::getLabelWidth(std::string str, std::string fontName, float fontsize)
{
	if (str.empty())
	{
		return 0;
	}
	LabelTTF * label = LabelTTF::create(str, fontName, fontsize);
	float nowposi = label->getContentSize().width;
	return nowposi;
}

//根据字符位置返回字节位置
int CursorTextField::getPosifromText(std::string str, int posi)
{
	int count = 0;
	int i;
	for (i = 0; i < str.length();)
	{
		std::string mystr = split_text(str, 1, i);
		i += mystr.length();
		count++;
		if (count == posi)
		{
			return i;
		}
	}
	return 0;
}
//根据坐标位置返回字节位置
int CursorTextField::getPosiformPosi(std::string str, float posi)
{
	std::string mystr;
	std::string temp;
	float parentPosi = this->getPositionX();
	float reposi = posi - parentPosi;
	if (parentPosi + getLabelWidth(str , fontName ,fontsize) <= posi)
	{
		return str.length();
	}
	if (reposi <= 0)
	{
		return 0;
	}
	int i = 0;
	float last, next;
	for (i = 0; i < str.length();)
	{
		 temp = split_text(str, 1, i);
		 last = getLabelWidth(mystr, fontName, fontsize);
		 next = getLabelWidth(mystr.append(temp), fontName, fontsize);
		 if (last <= reposi && next > reposi)
		 {
			 return i;
		 }
		 else if (next == reposi)
		 {
			 return i + temp.length();
		 }
		 i += temp.length();
	}
	return 0;
}

void CursorTextField::MyRemoveFromParent()
{

	KeyInsert::getinstence()->destoryinstence();
	m_pCursorSprite->stopAllActions();
	parentNode->removeChild(m_pCursorSprite);
	parentNode->removeChild(_CursorTextField);
	CC_SAFE_RELEASE(_CursorTextField);
}

MyKeyInsert.h

#pragma once

//#include "cocos2d.h"
#include "CursorTextField.h"

class KeyInsert : public CursorTextField
{
public:

	KeyInsert();
	~KeyInsert();
	static KeyInsert * getinstence();
	static void destoryinstence();
	void addKeyBordClick(cocos2d::Node * node);
	cocos2d::Node * parentNode;
	cocos2d::EventListenerKeyboard * _keyBordListener;
	void onKeyPressed(cocos2d::EventKeyboard::KeyCode, cocos2d::Event*);
	void onKeyReleased(cocos2d::EventKeyboard::KeyCode,cocos2d::Event*);
private:

};

MyKeyInsert.cpp

#include "MyKeyInsert.h"

USING_NS_CC;

static KeyInsert * _KeyInsert = NULL;

KeyInsert::KeyInsert()
{
	_KeyInsert = this;
	_KeyInsert->autorelease();
}

KeyInsert::~KeyInsert()
{
}

KeyInsert * KeyInsert::getinstence()
{
	if (_KeyInsert == NULL)
	{
		_KeyInsert = new (std::nothrow)KeyInsert();
	}
	return _KeyInsert;
}

void KeyInsert::destoryinstence()
{
	Director::getInstance()->getEventDispatcher()->removeEventListener(_KeyInsert->_keyBordListener);
	CC_SAFE_RELEASE(_KeyInsert);
}

void KeyInsert::addKeyBordClick(cocos2d::Node * node)
{
	_KeyInsert->parentNode = node;
	_KeyInsert->_keyBordListener = EventListenerKeyboard::create();
	_KeyInsert->_keyBordListener->onKeyPressed = CC_CALLBACK_2(KeyInsert::onKeyPressed, this);
	_KeyInsert->_keyBordListener->onKeyReleased = CC_CALLBACK_2(KeyInsert::onKeyReleased, this);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(_keyBordListener, _KeyInsert->parentNode);
}

void KeyInsert::onKeyPressed(EventKeyboard::KeyCode keycode, Event* event)
{
	switch (keycode)
	{
	case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
		//log("Left");
		BlickSpriteLeft();
		break;
	case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
		//log("right");
		BlickSpriteRight();
		break;
	case EventKeyboard::KeyCode::KEY_DELETE :
		KeyDelete();
		break;
	case EventKeyboard::KeyCode::KEY_UP_ARROW:
		log("Up");
		break;
	case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
		log("DOWN");
		break;
	default:
		break;
	}
}

void KeyInsert::onKeyReleased(EventKeyboard::KeyCode keycode, Event* event)
{
	//log("BBB");
}

具体效果自己去测试!我偷了下懒,那就是不是限定位置而是限定字符!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-12 20:42:07

cocos2dx3.6 实现带光标的输入框(二);光标可移动的相关文章

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

多的不说,我这个学渣,我写的代码比较搓!忍耐下吧! CursorTextField.h #ifndef _CursorTextField_H_ #define _CursorTextField_H_ #include "cocos2d.h" USING_NS_CC; class CursorTextField : public TextFieldTTF, public TextFieldDelegate , public IMEDelegate { private: // 点击开始位置

设置输入框的光标置于文字末尾

我们在项目开发过程中,会遇到这么一个问题:页面有个搜索框,点击搜索按钮或者回车键搜索后,文本框的光标置于文字前方,不便于继续输入, 影响操作,我们需要将光标置于文本之后,这时我就需要下面这段代码来控制光标. 为了方便使用已封闭成函数 1 function setCursorPos( input ) 2 { 3 var isIE = ( navigator.appName == "Microsoft Internet Explorer" );//判读是否为ie浏览器 4 var coun

Cocos2d-x3.0模版容器具体解释之二:cocos2d::Map&amp;lt;K,V&amp;gt;

1.概述: 版本号: v3.0 beta 语言: C++ 定义在 "COCOS2DX_ROOT/cocos/base" 路径下的 "CCMap.h" 的头文件里. template <class K, class V> class CC_DLL Map; cocos2d::Map<K,V> 是一个内部使用了 std::unordered_map的关联容器模版. std::unordered_map 是一个存储了由key-value键值对组合成

Bootstrap3基础 form-control 圆角的输入框,光标放入后边框变色

礼悟:    公恒学思合行悟,尊师重道存感恩.叶见寻根三返一,江河湖海同一体.          虚怀若谷良心主,愿行无悔给最苦.读书锻炼养身心,诚劝且行且珍惜.              ide:visual studio 2017             browser:Firefox / Chrome   bootstrap:3.3.7 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8&qu

Android中CleanEditText自动带X号输入框的EditText

图标在这里.你懂得 实现的效果如下: 今天做项目遇到的问题.记录下.自动带删除按钮的EditText. public class CleanEditText extends EditText implements OnFocusChangeListener, TextWatcher { /** * 删除按钮的引用 */ private Drawable mClearDrawable; public CleanEditText(Context context) { this(context, nu

生成带参数的微信二维码

场景:用户扫描带参数的二维码,可能推送以下两种事件: 1.如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者.2.如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者.说明:是将参数返回给开发者,不是给用户推送特定信息或跳转到页面. 步骤:1.登录你的微信公众号,点击左下角[接口权限],然后找到“生成带参数的二维码”,点击进入,这样我们就到了微信开发者文档的相关地方了.2.调试工具,在此页中找到[使用网页调试工具调试该接

iOS自带扫描 和 生成二维码

1.二维码生成 libqrencode介绍:是一个用C语言编写的用来解析二维条形码(QRCode)的程序库,libqrencode通过手机的CCD摄像头来扫描二维条形码. 导入libqrencode库,下面直接代码: #import <Foundation/Foundation.h> @interface QRCodeGenerator : NSObject + (UIImage *)qrImageForString:(NSString *)string imageSize:(CGFloat)

PHP 使用QR code库生成带LOGO图像的二维码

这几天的项目中要用到生成二维码的功能,而且老板要求二维码中间有一个LOGO,以往都是生成那种标准的,也就是比较纯净的二维码,现在老板的这个要求,一时让我无头绪,不过经过努力查找资料,发现PHP中有一个类库叫php qrcode,用它来生成这种二维码很是方便,于是就研究下,终于搞定了,下面把代码分享给大家.先来看看生成的效果: 具体的PHP代码,先调用phpqrcode.php,然后看代码里的注释,然后把 www.codesc.net这个网址修改成你自己的,还有logo图片替换成你的,再修改其它的

西门子PLC学习笔记十七-(不带参数FC编程二)

不带参数FC编程示例二,本次是要实现如下功能: 1.当未按下自动按钮时,可以分别手动控制3个灯的亮灭. 2.当按下自动按钮后,则这3个灯依次循环闪烁,每次亮的时间是1s 程序编写如下: FC1:手动控制 FC2:自动控制 程序可以在此下载.