游戏引擎一般提供两种输入框: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)
{
@H_502_113@
//检测是否有删改
@H_502_113@
pSender->setString(contentString.c_str());
@H_502_113@
once=0;
@H_502_113@
if
(recordPos.size()>0&&pSender->getContentSize().width-recordPos[recordPos.size()-1].point.x<0){
@H_502_113@
m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX()+distance/2);
@H_502_113@
pSender->setString(contentString.c_str());
@H_502_113@
updateDelete(pSender);
@H_502_113@
m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX()+distance/2);
@H_502_113@
pSender->setString(contentString.c_str());
@H_502_113@
updateDelete(pSender);
@H_502_113@
}
@H_502_113@
}
@H_502_113@
if
(recordPos.size()>0&&pSender->getContentSize().width-recordPos[recordPos.size()-1].point.x>1){
@H_502_113@
m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX()+distance/2);
@H_502_113@
pSender->setString(contentString.c_str());
@H_502_113@
updateAdd(pSender);
@H_502_113@
m_pCursorSprite->setPositionX(m_pCursorSprite->getPositionX()+pSender->getContentSize().width/2);
@H_502_113@
updateAdd(pSender);
@H_502_113@
}
@H_502_113@
}
@H_502_113@
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void
CCTextFieldTTFExtend::deleteString(){
@H_502_113@
}
@H_502_113@
{
@H_502_113@
++nDeleteLen;
@H_502_113@
}
@H_502_113@
stringtempNext=contentString.substr(posInString);
@H_502_113@
stringtempPrev=contentString.substr(0,posInString-nDeleteLen);
@H_502_113@
contentString=tempPrev+tempNext;
@H_502_113@
posInString-=nDeleteLen;
@H_502_113@
once=1;
@H_502_113@
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
void
CCTextFieldTTFExtend::addString(
const
char
*text){
@H_502_113@
stringtempPrev=contentString.substr(0,posInString);
@H_502_113@
stringtempNext=contentString.substr(posInString);
@H_502_113@
@H_502_113@
stringtempString=tempPrev+text+tempNext;
@H_502_113@
@H_502_113@
posInString+=addLength;
@H_502_113@
contentString=tempString;
@H_502_113@
judgeChines=addLength;
@H_502_113@
@H_502_113@
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){
@H_502_113@
//销毁足迹
@H_502_113@
distance=recordPos[posInList].point.x-recordPos[posInList-1].point.x;
@H_502_113@
}
@H_502_113@
@H_502_113@
vector<RecordTTF>temp=recordPos;
@H_502_113@
recordPos.clear();
@H_502_113@
recordPos.push_back(temp[i]);
@H_502_113@
}
@H_502_113@
temp[i].point.x-=distance;
@H_502_113@
recordPos.push_back(temp[i]);
@H_502_113@
}
@H_502_113@
@H_502_113@
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){
@H_502_113@
//原先字段的前部
@H_502_113@
vector<RecordTTF>temp=recordPos;
@H_502_113@
recordPos.clear();
@H_502_113@
recordPos.push_back(temp[i]);
@H_502_113@
}
@H_502_113@
@H_502_113@
RecordTTFlocal;
@H_502_113@
distance=pSender->getContentSize().width-temp[temp.size()-1].point.x;
@H_502_113@
local.point=CCPoint(temp[posInList-1].point.x+=distance,0);
@H_502_113@
local.flag=judgeChines;
@H_502_113@
recordPos.push_back(local);
@H_502_113@
RecordTTFlocal;
@H_502_113@
local.point=CCPoint(pSender->getContentSize().width,0);
@H_502_113@
local.flag=judgeChines;
@H_502_113@
recordPos.push_back(local);
@H_502_113@
RecordTTFlocal;
@H_502_113@
distance=pSender->getContentSize().width-temp[temp.size()-1].point.x;
@H_502_113@
local.point=CCPoint(temp[posInList-1].point.x+=distance,0);
@H_502_113@
local.flag=judgeChines;
@H_502_113@
recordPos.push_back(local);
@H_502_113@
}
@H_502_113@
}
@H_502_113@
@H_502_113@
temp[i].point.x+=distance;
@H_502_113@
recordPos.push_back(temp[i]);
@H_502_113@
}
@H_502_113@
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
{
@H_502_113@
NSArray*subviews=self.subviews;
@H_502_113@
@H_502_113@
{
@H_502_113@
{
@H_502_113@
{
@H_502_113@
[viewresignFirstResponder];
@H_502_113@
}
@H_502_113@
}
@H_502_113@
{
@H_502_113@
{
@H_502_113@
[viewresignFirstResponder];
@H_502_113@
}
@H_502_113@
}
@H_502_113@
}
}
|
原因代码也说的比较清楚了,原先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(){
@H_502_113@
@Override
@H_502_113@
if
(null!=Cocos2dxGLSurfaceView.
this
.mCocos2dxEditText&&Cocos2dxGLSurfaceView.
this
.mCocos2dxEditText.requestFocus()){
@H_502_113@
Cocos2dxGLSurfaceView.
this
.mCocos2dxEditText.removeTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
@H_502_113@
finalStringtext=(String)msg.obj;
@H_502_113@
Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper.setOriginText(text);
@H_502_113@
Cocos2dxGLSurfaceView.
this
.mCocos2dxEditText.addTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
@H_502_113@
finalInputMethodManagerimm=(InputMethodManager)Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@H_502_113@
}
|
原因是我将微信授权的回调activity也设成了cocos2dActivity。具体是什么造成的没有去深究,将其改为activity,并注意下到底是UIThread还是OpenGLThread,这样的问题就没有了。大部分这种操作都是线程混乱造成的,出现这种类似的情况,多看一下是否是线程的原因。
Cocos引擎中文官网有奖征集优秀原创Cocos教程 奖品丰厚!活动地址:http://www.cocoachina.com/bbs/read.php?tid-274890.html