Quick-Cocos2d-x的输入框详解

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


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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 ;  
}


删除内容操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//删除内容  
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;  
       
}


增加内容操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//增加内容  
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;  
}


删除位置操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 --;  
}


添加足迹的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-( 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输入框不显示键盘,跟踪发现启动键盘确实走到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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,这样的问题就没有了。大部分这种操作都是线程混乱造成的,出现这种类似的情况,多看一下是否是线程的原因。

Cocos引擎中文官网有奖征集优秀原创Cocos教程 奖品丰厚!活动地址:http://www.cocoachina.com/bbs/read.php?tid-274890.html

来源网址:http://blog.csdn.net/helius_sun/article/details/42271949

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值