Cocos2d-x学习(四):带光标的输入框

 


cocos2d-x为我们提供了一个跨平台的输入框,CCTextFieldTTF,初看时感觉提供的功能很少,当看到tests中TextInputTest这个例子的时候,感觉它的使用还真是很复杂,其原因无非是一些设置和判断的繁琐。不过话说回来了,输入框最主要的是跨平台监听输入,而不是样式!至于我们想要做的,就是根据游戏的需要相对封装一个简单的输入框而已!

今天我就以一个简单的带光标的输入框为例子,简单的解释一下输入框的工作原理和简单的封装,做到了控件使用时的简单,但是这只是一个简单的模型,目前只支持单行输入!

1.CCTextFieldTTF分析

这个类纯属是cocos2d-x的一个UI控件的扩展,当我们看到它的父类的时候,就会恍然大悟,喔!原来就是一个CCLabelTTF的子类啊!对,CCTextFieldTTF就是一个“动态”的CCLabelTTF,所谓的动态就是在监听到输入的时候动态的设置Label上的文字显示,仅此而已!而输入法的监听,则由其另一个父类CCIMEDelegate来实现。
class CC_DLL CCTextFieldTTF : public CCLabelTTF, public CCIMEDelegate

再看其方法,总结为三大类:

(1)静态初始化方法,

01./** creates a CCTextFieldTTF from a fontname, alignment, dimension and font size */  
02.    static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const CCSize& dim  ensions, CCTextAlignment alignment, const char *fontName, float fontSize);  
03.    /** creates a CCLabelTTF from a fontname and font size */  
04.    static CCTextFieldTTF * textFieldWithPlaceHolder(const char *placeholder, const char *fontN  ame, float fontSize);  
05.    /** initializes the CCTextFieldTTF with a font name, alignment, dimension and font size */  
06.    bool initWithPlaceHolder(const char *placeholder, const CCSize& dimensions, CCTextAlignment   alignment, const char *fontName, float fontSize);  
07.    /** initializes the CCTextFieldTTF with a font name and font size */  
08.    bool initWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);

 

(2)输入法控制方法,

@brief  Open keyboard and receive input text. 
03.    */  
04.    virtual bool attachWithIME();  
05.  
06.    /** 
07.    @brief  End text input  and close keyboard. 
08.    */  
09.    virtual bool detachWithIME();


(3)字符输入处理方法

01.virtual void insertText(const char * text, int len);  
02.virtual void deleteBackward();  
03.virtual const char * getContentText(); 

具体使用方法可以参考tests中的TextInputTest例子,用法很复杂,如果我们在每个需要输入的Layer中都去实现,那估计是会疯的!理所应当的做法是根据我们游戏的需要将其封装一下,以满足我们的需求!

(1) 首先,我们需要知道输入框控件要提供哪些想要的操作,而要完成这些操作,我们需要继承哪些父类

偷个懒,输入的任务就交给cocos2d-x的CCTextFieldTTF了,输入框中字符串的处理我们需要CCTextFieldDelegate,而要从Layer中将触摸判断解放出来,我们还需要CCTouchDelegate,所以,我们的自定义输入框的声明会是这样


 

01.class CursorTextField: public CCTextFieldTTF, public CCTextFieldDelegate, public CCTouchDeleg ate  
02.{  
03.private:  
04.    // 点击开始位置  
05.    CCPoint m_beginPos;  
06.      
07.    // 光标精灵  
08.    CCSprite *m_pCursorSprite;  
09.      
10.    // 光标动画  
11.    CCAction *m_pCursorAction;  
12.                   
13.    // 光标坐标  
14.    CCPoint m_cursorPos;  
15.      
16.    // 输入框内容  
17.    std::string *m_pInputText;  
18.public:  
19.    CursorTextField();  
20.    ~CursorTextField();  
21.      
22.    // static  
23.    static CursorTextField* textFieldWithPlaceHolder(const char *placeholder, const char *fon tName, float fontSize);  
24.      
25.    // CCLayer  
26.    void onEnter();  
27.    void onExit();  
28.      
29.    // 初始化光标精灵  
30.    void initCursorSprite(int nHeight);  
31.      
32.    // CCTextFieldDelegate  
33.    virtual bool onTextFieldAttachWithIME(CCTextFieldTTF *pSender);  
34.    virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender);  
35.    virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);  
36.    virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, in t nLen);  
37.      
38.    // CCLayer Touch  
39.    bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);  
40.    void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);  
41.      
42.    // 判断是否点击在TextField处  
43.    bool isInTextField(CCTouch *pTouch);  
44.    // 得到TextField矩形  
45.    CCRect getRect();  
46.      
47.    // 打开输入法  
48.    void openIME();  
49.    // 关闭输入法  
50.    void closeIME();  
51.};  
52.  
53.#endif


(2) 实现一些必要的方法

a.延续了cocos2d-x的风格,将静态方法和初始化方法分开,这里几乎是CCTextFieldTTF的翻版,不过这里有一个小知识点,就是创建一个纯色精灵的办法,代码如下

01. int column = 4;  
02.    int pixels[nHeight][column];  
03.    for (int i=0; i<nHeight; ++i) {  
04.        for (int j=0; j<column; ++j) {  
05.             pixels[i][j] = 0xffffffff;  
06.        }  
07.    }  
08.  
09.    CCTexture2D *texture = new CCTexture2D();  
10.    texture->initWithData(pixels, kCCTexture2DPixelFormat_RGB888, 1, 1, CCSizeMake(column, nH eight));  
11.      
12.    m_pCursorSprite = CCSprite::spriteWithTexture(texture);  


 


我用一个纯色精灵做了一个白色的光标,哈哈,虽然很山寨,但是在用的时候不用导入光标的图片资源了!

b.触摸判断

这个是有必要的,我们要判断触摸点是否在输入框上,如果在的话,需要弹出输入法;如果不在,需要关闭输入法,这样的用户体验还是不错的!

判断方法

01.bool CursorTextField::isInTextField(cocos2d::CCTouch *pTouch)  
02.{  
03.    return CCRect::CCRectContainsPoint(getRect(), convertTouchToNodeSpaceAR(pTouch));  
04.}  


 


开启和关闭输入法的方法(顺便带上了光标的显示)

01.void CursorTextField::openIME()  
02.{  
03.    m_pCursorSprite->setIsVisible(true);  
04.    this->attachWithIME();  
05.}  
06.  
07.void CursorTextField::closeIME()  
08.{  
09.    m_pCursorSprite->setIsVisible(false);  
10.    this->detachWithIME();  
11.}


 


c.还需要处理的地方是关于输入框中的字符串的添加和删减

我们可以监听到添加和删减,CCTextFieldDelegate所提供的方法,但是需要我们自己记录输入框中的内容,因为我们需要根据输入框中字符串的长度来确定光标的位置,而监听到添加字符的方法时,如果调用getString方法总会是差一个字符的,所以需要我们单独记录,我们手动调用setString方法,CCTextFieldTTF是根据字符串的宽度动态变化宽度的,于是有了下面的方法

01.bool CursorTextField::onTextFieldInsertText(cocos2d::CCTextFieldTTF *pSender, const char *tex	t, int nLen)  
02.{  
03.    CCLOG("Width: %f", pSender->getContentSize().width);  
04.    CCLOG("Text: %s", text);  
05.    CCLOG("Length: %d", nLen);  
06.      
07.    m_pInputText->append(text);  
08.    setString(m_pInputText->c_str());  
09.      
10.    m_pCursorSprite->setPositionX(getContentSize().width);  
11.      
12.    return true;  
13.}  
14.  
15.bool CursorTextField::onTextFieldDeleteBackward(cocos2d::CCTextFieldTTF *pSender, const char 	*delText, int nLen)  
16.{  
17.    m_pInputText->resize(m_pInputText->size() - nLen);  
18.    setString(m_pInputText->c_str());  
19.      
20.    m_pCursorSprite->setPositionX(getContentSize().width);  
21.      
22.    if (m_pInputText->empty()) {  
23.        m_pCursorSprite->setPositionX(0);  
24.    }  
25.      
26.    return false;  
27.}


 


OK,我们自定义的输入框类基本上就写好了,省略了些简单的部分,需要的在结尾处会有源码下载链接!
3. 使用

我们想要的就是使用简单,我们想要的就是不去每层都设置触摸判断,我们想要的就是像cocos2d-x为我们提供的精灵一样使用,所以使用代码如下
01.m_pCursorTextField = CursorTextField::textFieldWithPlaceHolder("Input Text", "Thonburi", 64); 
02.        m_pCursorTextField->setPosition(ccp(winSize.width / 2, winSize.height / 2 + 100)); 
03.        this->addChild(m_pCursorTextField);

 

效果图如下




这只是一个简单的例子,记录了一些简单的接口,目前只支持单行的正常显示,多行的和更完善的版本,下次补上!


源码下载

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值