quick-cocos2d-x的输入框

游戏引擎一般提供两种输入框:editbox和textfielttf。editbox比较简单,在ios上效果也还行,但是在android上就比较丑了,每次输入都会悬浮一个小框框。对于游戏来说eidtbox可以满足基本需求,毕竟输入还是少数情况。textfielttf是一种特殊的label,显示效果比较好,但是计算起来比较麻烦,要自己绘制光标,要自己绘制文字,自己计算增加和删除。

这里还是说一下自己实现的一种简陋的支持增加删除的方式吧。其实比较简单,原理就是记录每个字及每个字的位置,然后增加删除的时候既要对字处理也要对位置处理。(这里只针对单行进行说明,多行的还要自己维护高度等信息)。

先来说一下绘制函数,这里用的是自己维护的显示内容contentString

bool CCTextFieldTTFExtend::onDraw(CCTextFieldTTF *pSender)
{
    CCLog("the contentstring in fieldttf extend is %s", contentString.c_str());
    //检测是否有删改
    pSender->setString(contentString.c_str());
    if (once == 1) {
        once = 0;
        if (recordPos.size() > 0 && pSender->getContentSize().width - recordPos[recordPos.size()-1].point.x < 0) {
            //有记录的数据,切操作之后显示的文字内容比记录的要短,说明进行的是删除操作
            if (posInList > 1) {
                float distance = recordPos[posInList-2].point.x - recordPos[posInList-1].point.x;
                m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + distance/2);
                pSender->setString(contentString.c_str());
                updateDelete(pSender);
            }else if (posInList== 1){
                float distance = 0 - recordPos[posInList-1].point.x;
                m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + distance/2);
                pSender->setString(contentString.c_str());
                updateDelete(pSender);
            }
            return false;
        }
        if (recordPos.size() > 0 && pSender->getContentSize().width-recordPos[recordPos.size()-1].point.x > 1 ) {
            //有记录的数据,切操作之后显示的文字内容比记录的要长,说明进行的是增加操作
            float distance = pSender->getContentSize().width - recordPos[recordPos.size()-1].point.x;
            m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + distance/2);
            pSender->setString(contentString.c_str());
            updateAdd(pSender);
            return false;
        }else{
            if(recordPos.size() == 0 && pSender->getContentSize().width > 0){
                //显现没有记录说明没有文字,现在有记录说明是增加操作
                m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX() + pSender->getContentSize().width/2);
                updateAdd(pSender);
            }
        }
    }
    return false;
}

删除内容操作:

//删除内容
void CCTextFieldTTFExtend::deleteString(){
    if (strcmp(contentString.c_str(), "") && posInList < 1) {
        return;
    }
    //计算删除了几个汉字或字符
    int nDeleteLen = 1;
    while(0x80 == (0xC0 & contentString.at(posInString - nDeleteLen)))
    {
        ++nDeleteLen;
    }
    string tempNext = contentString.substr(posInString);
    string tempPrev = contentString.substr(0, posInString-nDeleteLen);
    contentString = tempPrev + tempNext;
    posInString -= nDeleteLen;
    once = 1;
    
}

增加内容操作:

//增加内容
void CCTextFieldTTFExtend::addString(const char *text){
    string tempPrev = contentString.substr(0, posInString);
    string tempNext = contentString.substr(posInString);
    
    string tempString = tempPrev + text + tempNext;

    int addLength = (strlen(tempString.c_str())-strlen(contentString.c_str()));
    posInString += addLength;
    contentString = tempString;
    judgeChines = addLength;

    CCLog("the contentString is %s", contentString.c_str());
    once = 1;
}

删除位置操作:

void CCTextFieldTTFExtend::updateDelete(CCTextFieldTTF * pSender){
    //销毁足迹
    float distance = 0;
    if (posInList != 0) {
        distance = recordPos[posInList].point.x - recordPos[posInList-1].point.x;
    }
    
    vector<RecordTTF> temp = recordPos;
    recordPos.clear();
    for (int i = 0; i < posInList-1; ++ i) {
        recordPos.push_back(temp[i]);
    }
    for (int i = posInList; i < temp.size(); ++ i) {
        temp[i].point.x -= distance;
        recordPos.push_back(temp[i]);
    }
    
    posInList --;
}

添加足迹的操作:

void CCTextFieldTTFExtend::updateAdd(CCTextFieldTTF * pSender){
    //原先字段的前部
    vector<RecordTTF> temp = recordPos;
    recordPos.clear();
    for (int i = 0; i < posInList; ++ i) {
        recordPos.push_back(temp[i]);
    }
    
    //现增加的部分
    float distance = 0;
    if (posInList > 0) {
        RecordTTF local;
        distance = pSender->getContentSize().width - temp[temp.size()-1].point.x;
        local.point = CCPoint(temp[posInList-1].point.x += distance, 0);
        CCLog("现在的 %f", local.point.x);
        local.flag = judgeChines;
        recordPos.push_back(local);
    }else{
        if(temp.size() < 1){
            RecordTTF local;
            local.point = CCPoint(pSender->getContentSize().width, 0);
            local.flag = judgeChines;
            recordPos.push_back(local);
        }else{
            RecordTTF local;
            CCLog("the contentSize is %f", pSender->getContentSize().width);
            distance = pSender->getContentSize().width - temp[temp.size()-1].point.x;
            local.point = CCPoint(temp[posInList-1].point.x += distance, 0);
            CCLog("现在的 %f", local.point.x);
            local.flag = judgeChines;
            recordPos.push_back(local);
        }
    }
    
    //原先文字的后部
    for (int i = posInList; i < temp.size(); ++ i) {
        temp[i].point.x += distance;
        recordPos.push_back(temp[i]);
    }
    posInList ++;
}


还有一种可能,如果要换行的话,我这里采用的是用系统控件的方式。但是ios上输入完内容之后,只有回车才能关闭键盘,点击空白处,或者自己的按钮都接收不到触摸事件,这时改一下lib/cocos2d-x/cocos2dx/platform/ios/EAGLView.mm,

-(void) handleTouchesAfterKeyboardShow
{
    NSArray *subviews = self.subviews;
    
    for(UIView* view in subviews)
    {
        if([view isKindOfClass:NSClassFromString(@"CustomUITextField")])
        {
            if ([view isFirstResponder])
            {
                [view resignFirstResponder];
                return;
            }
        }
        if([view isKindOfClass:NSClassFromString(@"UITextView")])
        {
            if ([view isFirstResponder])
            {
                [view resignFirstResponder];
                return;
            }
        }
    }
}

原因代码也说的比较清楚了,原先quick只对自己的控件进行了处理,现在你增加一下把系统控件也处理以下。

此外,在做android微信授权登陆的时候出现从cocos2dActivity跳转出去再跳转回来之后所有的cocos2d输入框不显示键盘,跟踪发现启动键盘确实走到

Cocos2dxGLSurfaceView.sHandler = new Handler() {
			@Override
			public void handleMessage(final Message msg) {
				switch (msg.what) {
					case HANDLER_OPEN_IME_KEYBOARD:
						Log.i("", "接收到启动键盘通知");
						if (null != Cocos2dxGLSurfaceView.this.mCocos2dxEditText && Cocos2dxGLSurfaceView.this.mCocos2dxEditText.requestFocus()) {
							Log.i("", "接收到启动键盘通知 开始启动键盘");
							Cocos2dxGLSurfaceView.this.mCocos2dxEditText.removeTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
							Cocos2dxGLSurfaceView.this.mCocos2dxEditText.setText("");
							final String text = (String) msg.obj;
							Cocos2dxGLSurfaceView.this.mCocos2dxEditText.append(text);
							Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper.setOriginText(text);
							Cocos2dxGLSurfaceView.this.mCocos2dxEditText.addTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
							final InputMethodManager imm = (InputMethodManager) Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
							imm.showSoftInput(Cocos2dxGLSurfaceView.this.mCocos2dxEditText, 0);
							Log.d("GLSurfaceView", "showSoftInput");
						}
						break;


原因是我将微信授权的回调activity也设成了cocos2dActivity。具体是什么造成的没有去深究,将其改为activity,并注意下到底是UIThread还是OpenGLThread,这样的问题就没有了。大部分这种操作都是线程混乱造成的,出现这种类似的情况,多看一下是否是线程的原因。


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值