有些东西,刚看的时候,可能觉得很可怕,这东西很难。迟迟不肯下手,不知拖的越长对自己越是一种折磨,并逐渐丧失信心。
万事开头难,放手去做,逼自己一下。等开始做起来。才发现并不是想象的那样,原来这东西如此简单。
CCEditBox 比 textFiled好用太多,textFiled问题很多,使用输入框基本都用CCEditBox或是自己实现组件。
基本用法:
LUA
-- inputMode 0: 开启任何文本的输入键盘,包括换行 (android下 输入是可支持换行的 因为文字显示虚拟框里面 ios是直接显示在输入框上所以不支持换行)
-- // 1: 开启 邮件地址 输入类型键盘
-- // 2: 开启 数字符号 输入类型键盘
-- // 3: 开启 电话号码 输入类型键盘
-- // 4: 开启 URL 输入类型键盘
-- // 5: 开启 数字 输入类型键盘,允许小数点
-- // 6: 开启任何文本的输入键盘,不包括换行
--]]
function CreateEditBox(uilayer, imgPath, size, point,length, fontSize, inputMode, holdStr, pwdFlay)
local cs9 = CCScale9Sprite:create(imgPath)
local editBox = CCEditBox:create(size, cs9)
editBox:setPosition(point)
editBox:setMaxLength(length) --设置输入最大长度
fontSize = fontSize or 30
editBox:setFontSize(fontSize) --设置字体大小
inputMode = inputMode or 6
editBox:setInputMode(inputMode) --设置输入模式 这里可以控制调出的键盘 比如数字键盘 文字键盘
holdStr = holdStr or ""
editBox:setPlaceHolder(holdStr) --如果输入框为空 显示的默认字符串 点击调出键盘后字符串会自动消失
pwdFlay = pwdFlay or 3
editBox:setInputFlag(pwdFlay) --设置输入的标记 设置是密码 输入完后就显示星号 英文首字母大写 ==其他模式
uilayer:addChild(editBox, 0)
return editBox
end
CCScale9Sprite* scale9 = CCScale9Sprite::createWithSpriteFrame(frame);
editbox = CCEditBox::create(getContentSize(), scale9);
editbox->setTouchPriority(1);
this->addChild(editbox);
SetAlignH(H_CENTER);
SetAlignV(V_CENTER);
editbox->setInputMode(kEditBoxInputModeAny);//kEditBoxInputModeSingleLine
editbox->setInputFlag(kEditBoxInputFlagInitialCapsWord);
editbox->setMaxLength(20);
editbox->setDelegate(this);
editbox->setFont(DEFAULT_FONT, DefaultFontSize);
CCEditBoxDelegate 为键盘回调代理类 里面有4个方法,如果需要接收这个4个事件,继承这个类就可以了。
editBoxEditingDidBegin //打开键盘回调事件
editBoxEditingDidEnd //关闭键盘回调事件
editBoxTextChanged //每次按下键盘都回回调该方法
editBoxReturn //关闭键盘回调事件在 上面的 End之后调用的
这几个事件都非常有用
如果想在lua中实现的话,让CCEditBox 继承 public CCEditBoxDelegate (默认CCEditBox是没有继承CCEditBoxDelegate的)
然后实现这个四个方法,在这里面设置回调lua的函数
void CCEditBox::editBoxTextChanged(CCEditBox* editBox, const std::string& text)
{
char luaCode[256] = {0};
sprintf(luaCode, "__onEditBoxTextChanged(%d)", editBox->getTag());
CCLuaEngine::defaultEngine()->executeString(luaCode);
}
void CCEditBox::editBoxEditingDidBegin(CCEditBox * editBox)
{
char luaCode[256] = {0};
sprintf(luaCode, "__onEditBoxDidBegin(%d)", editBox->getTag());
CCLuaEngine::defaultEngine()->executeString(luaCode);
}
void CCEditBox::editBoxEditingDidEnd(CCEditBox * editBox)
{
char luaCode[256] = {0};
sprintf(luaCode, "__onEditBoxDidEnd(%d)", editBox->getTag());
CCLuaEngine::defaultEngine()->executeString(luaCode);
}
void CCEditBox::editBoxReturn(CCEditBox * editBox)
{
setText(m_pEditBoxImpl->getText());
b_editState = false;
}
在c++中封装为组件类,组件类继承CCEditBoxDelegate, 内部含私有变量 CCEditBox ,重写 上面四个方法,然后在里面设置lua的回调方法
void Editor::editBoxEditingDidBegin(CCEditBox* editBox)
{
if(form!=NULL&&showScript.Length()>0)
{
lua_State* luaState=form->GetLuaState();
if(luaState!=NULL)
{
lua_getglobal(luaState, showScript.Data());
if(lua_type(luaState, -1)==LUA_TFUNCTION)
{
form->PushView(this);
LUA_CALL(luaState, 1, 0);
}
}
}
}
void Form::PushView(View* view)
{
lua_getglobal(luaState, "thisFormViewVar");
View** obj = (View**)luaL_checkudata(luaState, -1, "View");
if(obj!=NULL)
{
*obj=view;
}
}
这种方法比第一种好些。
上面体现了 两种不同的调用lua全局函数的方法。lua与c语言相互调用,有时间要看看。
CCEditBox 的缺点:
输入模式
kEditBoxInputModeAny = 0, 可以输入任何字符包括换行符
kEditBoxInputModeSingleLine 可输入任何字符不包括换行符
1,不支持换行显示。android输入,会调用一个模拟显示框来显示输入的文字,用模式0 在模拟框可以自动换行。下面的模式不支持换行。点击键盘回车键会把虚拟显示框内的文字自动赋值到 输入框内。
在ios下,输入的文字是直接显示到输入框上得。
2,在android下,还有bug,因为是通过键盘的回车键来把 虚拟显示的字放到输入框内。个别机型,比如sony机器或百度输入法,点击回车赋值不到输入框内,或没有回车键。
不知道是不是输入模式弄的,保险起见。推荐用 kEditBoxInputModeSingleLine 模式。
那我们怎么解决输入不换行的问题内:
我们采用这种ui,如果是ios想实时的把输入框内的文字,显示CCLabelTTF中,因为每次输入都会调用 editBoxTextChanged 函数或在回调的lua函数中处理,把输入框的文字设置到CCLabelTTF中就可以了,
setPlaceHolder 设置显示默认提示字符,点击之后会自动消失 把editBox->setText("") 就会自动显示 提示字符
如果在 editBoxEditingDidEnd 回调事件中,把editBox->setText("") 在android下,输入框竟然会显示个 0 ,妈的,找了好长时间
在editBoxReturn 回调事件中, 把editBox->setText("") 就没问题CCLabelTTF中的 setDimensions 就是设置换行的,单词也支持换行,不会在单词中间断开。
setDimensions(CCSizeMake(width, 0)) //高度要设置为0 才能正确换行,否则会出现截断多余的字符串的情况
源码很简单:
CCEditBox::create方法 调用构造函数,进行一些初始化的操作。
调用 initWithSizeAndBackgroundSprite 方法
m_pEditBoxImpl = __createSystemEditBox(this);
__createSystemEditBox 函数 在下面不同的平台都有,调用当前平台的系统api返回 一个输入框实例
唯一不明白的就是,因为是夸平台引擎。怎么实现的不同的工程调用不同的文件。
android CCEditBoxImplAndroid.h CCEditBoxImplAndroid.cpp
ios CCEditBoxImplIOS.hCCEditBoxImplIOS.mm
mac CCEditBoxImplMac.h CCEditBoxImplMac.mm
windows CCEditBoxImplWin.h CCEditBoxImplWin.cpp
不同的工程,配置工程的时候载入的是不同的文件。
上面的四个类都继承于 CCEditBoxImpl 这里 #include "CCEditBox.h" 就把 CCEditBox 与其他平台的文件关联起来了。
实现了不同的平台,调用不同平台的 __createSystemEditBox 方法。
如果还想继续修改,CCEditBox 就需要在上面这几个文件里面下功夫了。