原因分析
在iPad征服1.x版本中,输入方式是自己实现UITextInput协议。通过协议接口获得用户小键盘的输入信息,直接将数据传递给客户端的Edit控件。这样做的好处是与windows平台结构类似(windows平台也是通过OnChar获取字符串,然后传递给Edit控件),更加灵活高效(因为不使用苹果UIKit控件,没有控件本身的内存消耗,同时客户端获取数据后可以随意的对其进行处理,比如文字高亮、改变颜色等等)。
但是这么做有个致命的缺点,就是实现难度大,实现这套东西难度不啻于重写一个UITextField控件。因为没有完善的实现,所以导致的结果是:随机崩溃、无法保证与每一个输入法兼容、无法保证与iOS新特性兼容(比如,iOS5的iPad的拆分键盘功能)。
解决方案
参考千军破的方法,修改现有实现。新的实现方式是,使用两个UITextField控件接收输入,之所以是两个是因为有密码输入框,其显示方式与普通输入框有区别。用一个UITextField控件无法很好的兼容两种方式。
UITextField本身背景是透明的,文字是白色的,这样可以兼容大部分情况。在不进行输入的时候,输入框是隐藏的。游戏中由c3进行文字显示(游戏中的Edit控件)。当我们点击到Edit控件的时候,将UITextField设置到Edit的大小、位置、字体、文字内容,并将Edit隐藏。输入时一直由UITextField进行显示。当输入结束(小键盘消失)的时候,将文字设回Edit控件,并且显示Edit隐藏UITextField。
纠正措施
基本思路如解决方案所示,这样便完成了基本的输入操作,但是实际操作中会有更多的细节问题需要调试。
1、当Edit之间进行切换的时候,需要更新Edit和UITextField(这个过程中小键盘没有隐藏)
2、游戏内会有表情输入界面,所以要有更新UITextField文字的接口
3、某些情况下我们要确保游戏内的Edit控件文字与UITextField文字一致(因为我们在游戏中的逻辑判断都是使用Edit控件的文本数据),所以要有更新Edit控件文本的接口
4、当我们点击一个按钮的时候,判断当前对话框中是否有Edit控件,如果有的话,那就更新Edit控件数据,隐藏小键盘。这是大多数游戏逻辑会应用到的情况。
5、当小键盘显示的时候,如果Edit会被小键盘遮挡,那么就上移含有Edit的对话框,当小键盘隐藏的时候再还原对话框位置。这样可以比较理想的处理小键盘遮挡输入框的情况。
6、在textField shouldChangeCharactersInRange...函数中对每一次输入进行判断和过滤,比如,是否是可以输入的字符;输入的文本是否超过Edit的文本长度限制;对于数字模式的Edit进行Format用逗号分割数字...
7、(可选)在textField shouldChangeCharactersInRange...实时更新Edit数据,并发送TextChanged的事件,而Edit本身的SetWindowsText不再发送此事件。这样可以应付大多数对话框对Edit文本改变的逻辑判断。但是也可能有比较恶心的写法会因此而引发Bug
8、textFieldShouldReturn函数响应回车事件,这里可以选择关闭小键盘