cocos2d-x实现文字输入框以及字符串中文字的提取

原创 2013年10月22日 17:56:20

Colin-Liao 个人原创,欢迎转载,转载请注明地址。Colin-Liao的专栏地址http://blog.csdn.net/focusdeveloper

今天分享下如何做一个聊天窗口的文字输入框并且在其中提取汉字以及各种字符。

这个方法是相当于重写cocos2d-x中的CCTextFieldTTF这个类。那么下面看看头文件

<span style="font-family: SimSun;"><span style="font-size:14px;">#include <iostream>
#include "cocos2d.h"

USING_NS_CC;

class ChatText: public CCTextFieldTTF, public CCTextFieldDelegate
{
    CC_SYNTHESIZE(CCRect, textLabelRect, TextLabelRect);//输入框矩形
private:
    
    // 光标精灵
    CCSprite *m_pChatSprite;
    
    // 光标动画
    CCAction *m_pChatAction;
    
    // 光标坐标
    CCPoint m_chatPos;
    
    
    // 输入框内容
    std::string m_pInputText;
    //输入框实际内容
    std::string m_pInputString;
    //输入框文字字节数组
    int m_pInputCount[60];
    //第几个文字
    int index;
public:
    ChatText();
    ~ChatText();
    
    // static
    static ChatText* textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize);
    
    //    // CCLayer
    void onEnter();
    void onExit();
    
    // 初始化光标精灵
    void initChatSprite(int nHeight);
    
    // 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);
    
    // 打开输入法
    void openIME();
    // 关闭输入法
    void closeIME();
    
    void emptyString();
    
    //获得输入框实际内容
    const char* getInputString();
};
</span></span>

这里继承了CCTextFieldTTF和CCTextFieldDelegate两个类,并且重写了其中的函数,之后会贴出每个函数的作用。

因为在屏幕上实现一个输入框的长度是有限的,但是当我们输入的文字超过这个输入框的时候,那么我们应该把前面的文字隐藏起来,这就是为什么这里会设置两个string ,m_pInputText是用来实际显示出来的文字内容,m_pInputString是输入框中实际文字内容。这里有一个整数数组,长度为60,也就是说可以输入60个字符,然后index为这个数组的下标。

下面贴出cpp文件中每个函数并且讲解

<span style="font-family: SimSun;"><span style="font-size:14px;">ChatText::ChatText()
{
    CCTextFieldTTF();
    
    m_pChatSprite = NULL;
    m_pChatAction = NULL;
    
}

ChatText::~ChatText()
{

}

void ChatText::onEnter()
{
    CCTextFieldTTF::onEnter();
    this->setDelegate(this);
}
</span></span>
这里的onEnter函数中设置了输入框的Delegate。

<span style="font-family: SimSun;"><span style="font-size:14px;">ChatText * ChatText::textFieldWithPlaceHolder(const char *placeholder, const char *fontName, float fontSize)
{
    ChatText *pRet = new ChatText();
    if(pRet && pRet->initWithString("", fontName, fontSize))
    {
        pRet->autorelease();
        if (placeholder)
        {
            pRet->setPlaceHolder(placeholder);
        }
        pRet->initChatSprite(fontSize);
        
        return pRet;
    }
    
    CC_SAFE_DELETE(pRet);
    
    return NULL;
}</span></span>
这里是在创建这个输入框时候调用的函数,在函数中,new了一个ChatText,然后设置了他的PlaceHolder,这个参数是在输入框初始化时候灰色的文字,一般用作提示作用。

<span style="font-family: SimSun;"><span style="font-size:14px;">void ChatText::initChatSprite(int nHeight)
{
    // 初始化光标
    int column = 4;
    int pixels[nHeight][column];
    for (int i=0; i<nHeight; ++i) {
        for (int j=0; j<column; ++j) {
            pixels[i][j] = 0xffffffff;
        }
    }
    
    //初始化数组脚标
    this->index = -1;
    
    CCTexture2D *texture = new CCTexture2D();
    texture->initWithData(pixels, kCCTexture2DPixelFormat_RGB888, 1, 1, CCSizeMake(column, nHeight));
    
    m_pChatSprite = CCSprite::createWithTexture(texture);
    CCSize winSize = getContentSize();
    m_chatPos = ccp(0, winSize.height / 2);
    m_pChatSprite->setPosition(m_chatPos);
    this->addChild(m_pChatSprite);
    
    this->m_pChatAction = CCRepeatForever::create((CCActionInterval *) CCSequence::create(CCFadeOut::create(0.25f), CCFadeIn::create(0.25f), NULL));
    
    this->m_pChatSprite->setVisible(false);
    
    m_pChatSprite->runAction(m_pChatAction);
    
}
</span></span>
这个init主要作用是初始化光标,还有光标的动画。

<span style="font-family: SimSun;"><span style="font-size:14px;">bool ChatText::onTextFieldAttachWithIME(cocos2d::CCTextFieldTTF *pSender)
{
    if (m_pInputText.empty()) {
        return false;
    }
    
    m_pChatSprite->setPositionX(getContentSize().width);
    
    return false;
}</span></span>

这是来自CCTextFieldDelegate的回调函数,就是在打开输入法编辑器的时候会被调用,如果返回true则输入法编辑器不能被打开,这里返回的是yes并且设置了光标的位置为现在输入框中文字的宽度。

<span style="font-family: SimSun;"><span style="font-size:14px;">bool ChatText::onTextFieldInsertText(cocos2d::CCTextFieldTTF *pSender, const char *text, int nLen)
{
    CCLOG("Width: %f", pSender->getContentSize().width);
    CCLOG("Text: %s", text);
    CCLOG("Length: %d", nLen);
    

    
    if (*text == '\n') {
        
        this->closeIME();
        m_pChatSprite->setPositionX(0);
    }else
    {
        //将输入文字一个一个解析上线为60
        for (int i = 0; i < nLen; i++) {
            char cha[6];
            int count = 0;
            unsigned char ch = *(text+i);
            if (ch >=0x00 && ch <=0x7F) {
                count = 1;
                sprintf(cha, "%c",ch);
                
            }else if(ch >=0xC0 && ch <=0xDF)
            {
                count =2;
                sprintf(cha, "%c%c",ch,*(text+i+1));
                i = i+1;
                
            }
            else if(ch >=0xE0 && ch <=0xEF)
            {
                count =3;
                sprintf(cha, "%c%c%c",ch,*(text+i+1),*(text+i+2));
                i = i+2;
            }
            else if(ch >=0xF0 && ch <=0xF7)
            {
                count =4;
                sprintf(cha, "%c%c%c%c",ch,*(text+i+1),*(text+i+2),*(text+i+3));
                i = i+3;
            }
            else if(ch >=0xF8 && ch <=0xFB)
            {
                count =5;
                sprintf(cha, "%c%c%c%c%c",ch,*(text+i+1),*(text+i+2),*(text+i+3),*(text+i+4));
                i = i+4;
            }
            else if(ch >=0xFC && ch <=0xFD)
            {
                count =6;
                sprintf(cha, "%c%c%c%c%c%c",ch,*(text+i+1),*(text+i+2),*(text+i+3),*(text+i+4),*(text+i+5));
                i = i+5;
            }
            
            if (this->index < 59) {
                this->index = this->index+1;
                m_pInputString.append(cha);
                std::cout<<m_pInputString<<std::endl;
                m_pInputCount[this->index] = count;
            }else
            {
                break;
            }
            
        }
        
        
        if (this->index <= 59) {
            int showAmount = 0;
            int chinese = 0;
            int chineseAmount = 0;
            for (int i =this->index; i>= 0; i --) {
                if (showAmount <=32) {
                    if (this->m_pInputCount[i] == 3) {
                        chinese = chinese + 1;
                    }
                    showAmount = showAmount + this->m_pInputCount[i];
                }else
                {
                    if (chinese == 0) {
                        break;
                    }
                    
                    chineseAmount = chineseAmount + this->m_pInputCount[i];
                    
                    if (chineseAmount > chinese) {
                        showAmount = showAmount + chineseAmount - this->m_pInputCount[i];
                        break;
                    }else if (i <=0)
                    {
                        showAmount = showAmount+ chineseAmount;
                    }
                    
                }
                
            }
            m_pInputText = m_pInputString.substr(m_pInputString.length() - showAmount);
            
            setString(m_pInputText.c_str());
            
            m_pChatSprite->setPositionX(getContentSize().width);
        }

    }
    
    
    return true;
}
</span></span>
这个函数也是CCTextFieldDelegate的回调函数,在输入文字的时候被调用。当返回为true的时候输入的文字无效,不会被设置先是在输入框中,但是这里用自己将文字加入到了输入框。 

当输入文字是首先判断是不是'\n'字符,如果是表示是收到了键盘上的return消息,这里处理为关闭键盘,并且设置了光标位置。如果不是return消息,就要对文字做解析了,之前有说到最多能够输入60个字符。

这里提到UTF8编码,它最多的字符有6个字节,每个字符的第一个字节在一定的范围内,通过上面的代码解析出来每个字符。如果index并没有超过59的话就通过string的append函数将解析出来的字符一个一个加入到输入框的实际内容中去,同时把每个字符的字节数量加入到整数数组中,以便之后分割字符串用,如果超过则结束循环。

然后对选择一些输入框的内容作为显示内容。同样先判断index是否已经超过59。在数组中读取出你能够显示在你屏幕上的字节数量,因为汉字占用三个字节导致p输入框不能显示尽量多的汉字,所以这里把汉字处理为两个字节。32这个数量可以自己设定,这是适合我自己的显示宽度。之后在实际内容的string中获取到子string加入到显示string上,并且设置为输入框的文字,再设置了光标位置。

<span style="font-family: SimSun;"><span style="font-size:14px;">bool ChatText::onTextFieldDeleteBackward(cocos2d::CCTextFieldTTF *pSender, const char *delText, int nLen)
{
    
    this->m_pInputString = this->m_pInputString.substr(0,this->m_pInputString.length()-nLen);
    this->index = this->index -1;
    
    
    if (this->index <= 59) {
        int showAmount = 0;
        int chinese = 0;
        int chineseAmount = 0;
        for (int i =this->index; i>= 0; i --) {
            if (showAmount <=32) {
                if (this->m_pInputCount[i] == 3) {
                    chinese = chinese + 1;
                }
                showAmount = showAmount + this->m_pInputCount[i];
            }else
            {
                if (chinese == 0) {
                    break;
                }
                
                chineseAmount = chineseAmount + this->m_pInputCount[i];
                
                if (chineseAmount > chinese) {
                    showAmount = showAmount + chineseAmount - this->m_pInputCount[i];
                    break;
                }else if (i <=0)
                {
                    showAmount = showAmount+ chineseAmount;
                }
                
            }
            
        }
        m_pInputText = m_pInputString.substr(m_pInputString.length() - showAmount);
        
        setString(m_pInputText.c_str());
        
        m_pChatSprite->setPositionX(getContentSize().width);
        
        
        if (m_pInputText.empty()) {
            
            this->setPlaceHolder("输入聊天内容");
            m_pChatSprite->setPositionX(0);
        }
        
        return true;
    }
    return false;
}
</span></span>
这个回调函数是删除字符,一个一个删除,如果返回true则不删除字符,这里原理为把实际内容最后一个字符删除,然后用上面的方法取出显示的字符串,设置为显示字符串,这样就向是删除后字符串向后面移动。别忘记设置index变量。

<span style="font-family: SimSun;"><span style="font-size:14px;">void ChatText::emptyString()
{
    m_pInputText.resize(0);
    this->m_pInputString.resize(0);
    this->index = -1;
    setString(m_pInputText.c_str());
    if (m_pInputText.empty()) {
        
        this->setPlaceHolder("输入聊天内容");
        m_pChatSprite->setPositionX(0);
    }
}</span></span>
这个函数是 用来重置字符串的把idex设置为-1,把两个string设置为“”。string被重置。显示出提示信息。

<span style="font-family: SimSun;"><span style="font-size:14px;">bool ChatText::onTextFieldDetachWithIME(cocos2d::CCTextFieldTTF *pSender)
{
    return false;
}</span></span>
这个函数为键盘关闭的时候会调用,如果返回true,则键盘不被关闭。

<span style="font-family: SimSun;"><span style="font-size:14px;">void ChatText::openIME()
{
    
    ChatUI* scene = (ChatUI*)this->getParent();
    scene->setPosition(ccp(scene->getPosition().x, scene->getPosition().y+280));
    
    
    m_pChatSprite->setVisible(true);
    this->attachWithIME();
}

void ChatText::closeIME()
{
    
    ChatUI* scene = (ChatUI*)this->getParent();
    scene->setPosition(ccp(scene->getPosition().x, scene->getPosition().y-280));
    
    m_pChatSprite->setVisible(false);
    this->detachWithIME();
}

void ChatText::onExit()
{
    CCTextFieldTTF::onExit();
}

const char* ChatText::getInputString()
{
    return this->m_pInputString.c_str();
}
</span></span>
这几个函数第一个表示打开键盘,第二个 关闭键盘,分别调用父类的函数。最后一个表示获取输入框全部内容。

最后在别的界面中对触摸信息做一个处理点击到输入框的时候调出键盘。


更新一下在键盘调出之后,发现就无法在接收触摸消息了,解决方法在工程中找到EAGLView.mm文件在其touchesBegan,touchesBegan,touchesEnded,touchesCancelledtouchesMoved,
函数中注视掉其中判断键盘是否弹出就return的代码就好了

//    if (isKeyboardShown_)

//    {

//        [self handleTouchesAfterKeyboardShow];

//        return;

//    }


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

相关文章推荐

Cocos2d-x3.3Final(12)TextField常用成员函数(C++)

TextField * textField = TextField::create("input words here", "Arial", 30); textField->setPosition(...

cocos2d-x 中英文字符串截取

#pragma mark 获取字符串长度 int RoutesController::strLength(const std::string &str) {        if (typei...

Cocos2d-x中的字符串

Cocos2d-x中的字符串 在Cocos2d-x中能够使用的字符串constchar*、std::string和cocos2d::__String等,其中const char*是C风格的字符串,s...

Cocos2D-x游戏开发之二十四:自定义字符串分割类

今天我们为下一节的CSV文件处理做一个准备,开始自定义一个对字符串按照特定的符号分割的类,实现如下: class StringUtil : public CCObject { public: ...

Cocos2dx中英文混合字符串截取

Cocos2dx中英文混合字符串截取方法

Cocos2D-x游戏开发之二十五:自定义文本读取工具类

现在我们在上一节的基础上开始对文件进行解析,

Cocos2d-x3.1中的Text控件的使用

1、TextAtlas 定义UITextAtlas

cocos2d-x 中添加显示文字的三种方式(CCLabelTTF 、CCLabelBMFont 和CCLabelAtlas)

在 cocos2d-x 中有三个类可以在层或精灵中添加文字: CCLabelTTFCCLabelBMFontCCLabelAtlas CCLabelTTF    TTF(Tr...

cocos2d-x 中添加显示文字的三种方式 LabelTTF 、LabelBMFont 和 LabelAtlas

在 cocos2d-x 中有三个类可以在层或精灵中添加文字: LabelTTFLabelBMFontLabelAtlas LabelTTF 直接支持使用 TTF 字库,可以支持全部的中文,...

cocos2d-x带光标的输入框

  • 2012-05-16 14:50
  • 1.10MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)