cocos2dx中的输入类CCTextFieldTTF。还是相当好用的,
其中,很多人都会关注怎么判断用户输入的数字,字母,汉字?
通过重载onTextFieldInsertText函数,我们可以自定义自己想要的效果。
以下代码,是参考官方的示例,添加了是否数字、字母、汉字的判断,还增加了以空格和回车作为输入结束符。
以下代码,拷到新建项目的HelloWorld中可以直接用(本文版本cocos2dx 2.2.2)。
上代码: .h文件
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
USING_NS_CC;
class HelloWorld : public cocos2d::CCLayer,public CCTextFieldDelegate,public CCIMEDelegate
{
public:
// Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer)
virtual bool init();
// there's no 'id' in cpp, so we recommend to return the class instance pointer
static cocos2d::CCScene* scene();
// preprocessor macro for "static create()" constructor ( node() deprecated )
CREATE_FUNC(HelloWorld);
void callbackRemoveNodeWhenDidAction(CCNode * pNode);
virtual void onClickTrackNode(bool bClicked,CCTextFieldTTF * pSender);
// CCLayer
virtual void onEnter();
virtual void onExit();
virtual void registerWithTouchDispatcher();
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
// CCTextFieldDelegate
virtual bool onTextFieldAttachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);
virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);
virtual bool onDraw(CCTextFieldTTF * pSender);
//CCIMEDelegate
//keyboard show/hide notification
//virtual void keyboardWillShow(CCIMEKeyboardNotificationInfo& info);
//virtual void keyboardWillHide(CCIMEKeyboardNotificationInfo& info);
private:
CCTextFieldTTF* m_pTextField;
CCTextFieldTTF* m_pTextField2;
CCAction* m_pTextFieldAction;
bool m_bAction;
int m_nCharLimit; // the textfield max char limit
CCPoint m_beginPos;
float adjustVert;
};
#endif // __HELLOWORLD_SCENE_H__
.cpp文件
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
using namespace cocos2d;
using namespace CocosDenshion;
#define FONT_NAME "Thonburi"
#define FONT_SIZE 36
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
setTouchEnabled(true); //注意要设置当前layer为可触摸
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition( ccp(size.width/2, size.height/2) );
this->addChild(pSprite, 0);
return true;
}
void HelloWorld::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, false);//true会吞噬
}
void HelloWorld::onEnter()
{
CCLayer::onEnter(); //这个父类的调用很重要!
m_nCharLimit = 12;
m_pTextFieldAction = CCRepeatForever::create(
CCSequence::create(
CCFadeOut::create(0.25),
CCFadeIn::create(0.25),
NULL
));
m_pTextFieldAction->retain(); //这里一定要retain一次,否则会出现内存问题。
m_bAction = false;
// add CCTextFieldTTF
CCSize s = CCDirector::sharedDirector()->getWinSize();
m_pTextField = CCTextFieldTTF::textFieldWithPlaceHolder("<click here for input>",
FONT_NAME,
FONT_SIZE);
m_pTextField->setColor(ccWHITE); //设置输入编辑框中字符的颜色
// m_pTextField->setSecureTextEntry(true); //输入密码时,用点字符替代
m_pTextField->setDelegate(this); //很重要 勿漏!!!
m_pTextField->setPosition(ccp(s.width / 2, s.height / 2+30)); //将输入编辑框的y轴位置设低是为了测试,当出现键盘的时候,输入编辑框的自动向上调整。
addChild(m_pTextField);
m_pTextField2 = CCTextFieldTTF::textFieldWithPlaceHolder("<click here for input>",
FONT_NAME,
FONT_SIZE);
m_pTextField2->setColor(ccWHITE); //设置输入编辑框中字符的颜色
// m_pTextField2->setSecureTextEntry(true); //输入密码时,用点字符替代
m_pTextField2->setDelegate(this);
m_pTextField2->setPosition(ccp(s.width / 2, s.height / 2-30)); //将输入编辑框的y轴位置设低是为了测试,当出现键盘的时候,输入编辑框的自动向上调整。
addChild(m_pTextField2);
}
//返回节点的rect
static CCRect getRect(CCNode * pNode)
{
CCRect rc;
rc.origin = pNode->getPosition();
rc.size = pNode->getContentSize();
rc.origin.x -= rc.size.width / 2;
rc.origin.y -= rc.size.height / 2;
return rc;
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
CCLOG("++++++++++++++++++++++++++++++++++++++++++++");
m_beginPos = pTouch->getLocation();
return true;
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
if (! m_pTextField)
{
return;
}
CCPoint endPos = pTouch->getLocation();
// 以下这部分代码是用于检测 begin touch 到 end touch之间的距离是否超过5.0,如果是,则返回;否则,继续执行下面的判断是否点击到编辑框的代码。
float delta = 5.0f;
if (::abs(endPos.x - m_beginPos.x) > delta
|| ::abs(endPos.y - m_beginPos.y) > delta)
{
// not click
m_beginPos.x = m_beginPos.y = -1;
return;
}
// decide the trackNode is clicked.
CCRect rect;
rect = getRect(m_pTextField);
this->onClickTrackNode(rect.containsPoint(endPos),m_pTextField);
CCRect rect2;
rect2 = getRect(m_pTextField2);
this->onClickTrackNode(rect2.containsPoint(endPos),m_pTextField2);
CCLOG("----------------------------------");
}
void HelloWorld::onClickTrackNode(bool bClicked,CCTextFieldTTF * pSender)
{
if (bClicked)
{
// TextFieldTTFTest be clicked
CCLOG("attachWithIME");
pSender->attachWithIME(); //调用键盘
}
else
{
// TextFieldTTFTest not be clicked
CCLOG("detachWithIME");
pSender->detachWithIME(); //隐藏键盘
}
}
void HelloWorld::onExit()
{
m_pTextFieldAction->release();
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
// CCTextFieldDelegate protocol
bool HelloWorld::onTextFieldAttachWithIME(CCTextFieldTTF * pSender)
{
if (! m_bAction)
{
pSender->runAction(m_pTextFieldAction);
m_bAction = true;
}
return false;
}
bool HelloWorld::onTextFieldDetachWithIME(CCTextFieldTTF * pSender)
{
if (m_bAction)
{
pSender->stopAction(m_pTextFieldAction);
pSender->setOpacity(255);
m_bAction = false;
}
return false;
}
//本文的重点在此
bool HelloWorld::onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen)
{
//if insert enter, treat as default to detach with ime
CCLOG("%d",nLen);//当前输入的单个字符长度
//空格和\n作为输入结束符
if (*text==' '||'\n' == *text)
{
pSender->detachWithIME(); //关闭输入 隐藏键盘
return true;
}
//中文的nlen是3 数字和字母的是1
//如果输入是中文 则不接受输入的内容
if (nLen>1)
{
return true;//true 则不接受输入的内容 但是可以继续输入
}
//判断是否数字或者字符,和下划线_
//不接受数字和英文大小写字符以外的输入
if((*text>='0'&& *text<='9')||((*text>='a'&&*text<='z')||((*text>='A')&&(*text<='Z')))||*text>='_')
{
}
else
{
return true;
}
// if the textfield's char count more than m_nCharLimit, doesn't insert text anymore.
if (pSender->getCharCount() >= m_nCharLimit)
{
return true;
}
创建输入时动画 create a insert text sprite and do some action
//CCLabelTTF * label = CCLabelTTF::create(text, FONT_NAME, FONT_SIZE);
//this->addChild(label);
//ccColor3B color = { 226, 121, 7};
//label->setColor(color);
//
move the sprite from top to position
//CCPoint endPos = pSender->getPosition();
//if (pSender->getCharCount())
//{
// endPos.x += pSender->getContentSize().width / 2;
//}
//CCSize inputTextSize = label->getContentSize();
//CCPoint beginPos(endPos.x, CCDirector::sharedDirector()->getWinSize().height - inputTextSize.height * 2);
//
//float duration = 0.5;
//label->setPosition(beginPos);
//label->setScale(8);
//
//CCAction * seq = CCSequence::create(
// CCSpawn::create(
// CCMoveTo::create(duration, endPos),
// CCScaleTo::create(duration, 1),
// CCFadeOut::create(duration),
// 0),
// CCCallFuncN::create(this, callfuncN_selector(HelloWorld::callbackRemoveNodeWhenDidAction)),
// 0);
//label->runAction(seq);
return false;
}
bool HelloWorld::onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen)
{
创建删除字符动画 create a delete text sprite and do some action
//CCLabelTTF * label = CCLabelTTF::create(delText, FONT_NAME, FONT_SIZE);
//this->addChild(label);
//
move the sprite to fly out
//CCPoint beginPos = pSender->getPosition();
//CCSize textfieldSize = pSender->getContentSize();
//CCSize labelSize = label->getContentSize();
//beginPos.x += (textfieldSize.width - labelSize.width) / 2.0f;
//
//CCSize winSize = CCDirector::sharedDirector()->getWinSize();
//CCPoint endPos(- winSize.width / 4.0f, winSize.height * (0.5 + (float)rand() / (2.0f * RAND_MAX)));
//
//float duration = 1;
//float rotateDuration = 0.2f;
//int repeatTime = 5;
//label->setPosition(beginPos);
//
//CCAction * seq = CCSequence::create(
// CCSpawn::create(
// CCMoveTo::create(duration, endPos),
// CCRepeat::create(
// CCRotateBy::create(rotateDuration, (rand()%2) ? 360 : -360),
// repeatTime),
// CCFadeOut::create(duration),
// 0),
// CCCallFuncN::create(this, callfuncN_selector(HelloWorld::callbackRemoveNodeWhenDidAction)),
// 0);
//label->runAction(seq);
return false;
}
bool HelloWorld::onDraw(CCTextFieldTTF * pSender)
{
return false;
}
void HelloWorld::callbackRemoveNodeWhenDidAction(CCNode * pNode)
{
this->removeChild(pNode, true);
}
//虚拟键盘
//void HelloWorld::keyboardWillShow(CCIMEKeyboardNotificationInfo& info)
//{
// CCLOG("TextInputTest:keyboardWillShowAt(origin:%f,%f, size:%f,%f)",
// info.end.origin.x, info.end.origin.y, info.end.size.width, info.end.size.height);
//
// if (! m_pTextField)
// {
// return;
// }
//
// CCRect rectTracked = getRect(m_pTextField);
//
// CCLOG("TextInputTest:trackingNodeAt(origin:%f,%f, size:%f,%f)",
// rectTracked.origin.x, rectTracked.origin.y, rectTracked.size.width, rectTracked.size.height);
//
// // if the keyboard area doesn't intersect with the tracking node area, nothing need to do.
// if (! rectTracked.intersectsRect(info.end))
// {
// return;
// }
//
// // assume keyboard at the bottom of screen, calculate the vertical adjustment.
//
// //计算出需要y轴需要调整的距离
// adjustVert = info.end.getMaxY() - rectTracked.getMinY();
// CCLOG("TextInputTest:needAdjustVerticalPosition(%f)", adjustVert);
//
// // move all the children node of KeyboardNotificationLayer
// CCArray * children = getChildren();
// CCNode * node = 0;
// int count = children->count();
// CCPoint pos;
// for (int i = 0; i < count; ++i)
// {
// node = (CCNode*)children->objectAtIndex(i);
// pos = node->getPosition();
// pos.y += adjustVert; //所有的节点都向上移动
// node->setPosition(pos);
// }
//}
//
//
//void HelloWorld::keyboardWillHide(CCIMEKeyboardNotificationInfo &info)
//{
// CCLOG("TextInputTest:keyboardWillShowAt(origin:%f,%f, size:%f,%f)",
// info.end.origin.x, info.end.origin.y, info.end.size.width, info.end.size.height);
//
// CCArray * children = getChildren();
// CCNode * node = 0;
// int count = children->count();
// CCPoint pos;
// for (int i = 0; i < count; ++i)
// {
// node = (CCNode*)children->objectAtIndex(i);
// pos = node->getPosition();
// pos.y -= adjustVert; //所有的节点都向下移动,恢复原来的位置
// node->setPosition(pos);
// }
//}
(注意:onTextFieldInsertText函数中是const char * text,使用的时候需要星号* text)
输入框,把锚点设置在(0.0,0.5),则会左对齐,此外如果这个修改了,也需要修改触摸的范围。
我习惯另外做一个显示的背景框,用作点击范围,这样用户使用比较方便。
CCTextFieldTTF相当灵活,方便我们自定义。很好!大赞!
参考资料:
http://blog.csdn.net/crayondeng/article/details/12175367 Cocos2d-x CCEditBox & CCTextFieldTTF