我是一个很喜欢炫耀的人,我最近解决了一个问题,所以来炫耀了~嘿嘿~
希望各位被我炫耀的同时,也把我学到的知识偷走,随便偷,不要钱哈~
在看我的帖子之前,请确保你已经看过或者掌握了这个帖子(在没有输入焦点类控件上调用输入法):
http://www.android-fans.net/forum.php?mod=viewthread&tid=38&extra=page%3D1
是这位朋友发了这个帖子之后我才得以解决这个问题的~再次感谢他~
好了,描述一下我的问题,游戏开发的过程中,很少甚至可以说是没有用到系统自带的控件~
反正我是没有用到,不知道是不是我井底之蛙了,嘿嘿~
按钮、标签、窗口、滑动窗口之类的控件,虽说实现得不是很好,但是起码还是能自己实现的。
唯独这个输入框,整晕我了,困扰了我好久~
我不知道怎么弹出输入法,就算后来我知道了,我还是不知道怎么去获取输入法的输入。
不知道有没有人有着和我一样的困扰呢?~
是不是发现我好多废话?~别着急,你还要忍受我的很多废话呢,嘻嘻~
好喇,开始~
先看截图,免得浮躁,嘻嘻:
整个例子的代码都在附件里,我的注释应该算蛮清晰的,嘿嘿,所以大家看代码就好,在这里我只是简单说几个要注意的地方~
再次提醒,记得先看懂了上面提到的那个帖子再往下看哈~
1. 首先来看看游戏的主界面,GameView里要重写一个方法:
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new XInputConnection(this, false);
}
是的,这个就是上面提到的那个帖子里教我们的,重写这个方法就能监听到输入法的一些小动作,这家伙,逃不过我们的手掌的,嘿嘿~
2. 当然,必须得自己实现一个XInputConnection类,先别看代码,写看看我的解释,哈哈:
public class XInputConnection extends BaseInputConnection {
public XInputConnection(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
/* 发送每一个输入的字符到自定义的输入框控件 */
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("sChar", (String)text);
GlobalClient.messageDispatch.dispatchMessage(EnumMsgDispatchType.EN_COMMIT_TEXT, map);
return true;
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
/* 发送键盘事件到自定义的输入框控件 */
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("keyEvent", event);
GlobalClient.messageDispatch.dispatchMessage(EnumMsgDispatchType.EN_SEND_KEY_EVENT, map);
return super.sendKeyEvent(event);
}
}
这个类很简单,抓住了输入法的两个小动作,一个是输入字符,一个是软键盘的事件(可能我说错了,大概是这样的,可以纠正我错误~)。
抓住了输入字符的事件,我们就可以让自己的输入框显示这些字符,这个很重要,输入框必须得有的功能嘛~
抓住键盘事件又是做什么的呢?那大家想想,我只能输入,不能删除,那这个输入框要来做嘛?~
是的,有了键盘事件,我们就能监听到删除键,然后就能删除字符。
OK~输入框要的两个基本功能已经有条件实现了~
注意喇,别去研究两个方法的具体实现先,那只是我实现的方法,大家都可以用自己的方式去实现的~
有了杯子和水,至于怎么把水装进杯子,就因人而异了,对不对?~
3. 主角出场~我自己实现的EditText控件(只贴出部分代码):
/**
* 自定义的输入框
* @author 笨木头
*
*/
public class XEditText implements IMessageDispatchSink, ISoldHold {
public XEditText(Context _context, Point _point, Bitmap _background) {
this.context = _context;
this.point = _point;
this.background = _background;
initOnClickListener();
}
public void drawMe(Canvas canvas) {
/* 输入框背景 */
canvas.drawBitmap(background, point.x, point.y, paint);
/* 输入框文字的坐标调整了,调整的算法是临时的,所以可以忽略 */
canvas.drawText(sText, point.x + iFontSize / 2,
point.y + iFontSize / 2 + background.getHeight() / 2, paint);
}
@Override
public void onRecv(EnumMsgDispatchType enMsgDispatchType, HashMap<String, Object> map) {
switch(enMsgDispatchType) {
case EN_COMMIT_TEXT: /* 输入字符 */
commitText(map);
break;
case EN_SEND_KEY_EVENT: /* 键盘事件 */
sendKeyEvent(map);
break;
}
}
@Override
public void onClickCMD() {
listener.onClick();
}
@Override
public void setOnClickListener(IMsgOnClickListener listener) {
this.listener = listener;
}
/**
* 输入字符
* @param map
*/
private void commitText(HashMap<String, Object> map) {
if(map == null) {
return;
}
String sChar = (String) map.get("sChar");
sText += sChar;
}
/**
* 键盘事件
* @param map
*/
private void sendKeyEvent(HashMap<String, Object> map) {
if(map == null) {
return;
}
KeyEvent event = (KeyEvent) map.get("keyEvent");
if(event.getAction() == 1) {
/* 删除字符事件 */
if(event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
int iLen = sText.length();
if(iLen > 0) {
sText = sText.substring(0, iLen - 1);
}
}
}
}
/**
* 设置监听事件
*/
private void initOnClickListener() {
this.setOnClickListener(new IMsgOnClickListener() {
@Override
public void onClick() {
/* 发布显示输入法的消息 */
GlobalClient.messageDispatch.dispatchMessage(EnumMsgDispatchType.EN_SHOW_IUPUT, null);
}
});
}
}
首先,作为一个控件,肯定少不了要有一个OnClick事件咯,至于实现的方法,大家用自己的方法就好,可以不用管我的方法。
然后,XEditText里还有两个方法,一个commitText(), 大家都知道了,用来获取字符的;还有一个sendKeyEvent(), 用来删除字符的~
OK,那,输入法输入字符和删除字符的动作,是怎么告诉我的输入框的呢?我用的方法是消息派发:
XInputConnection里调用这两个方法的时候,就发布消息,告诉所有想知道这个方法的对象。
至于消息派发是什么东西,也有大部分人都懂了~
如果有还没有接触到消息派发的朋友,我以后再另开帖子写一下我的见解哈~
反正现在大家只要知道一点,输入法有了输入字符和删除字符的动作,就会调用XInputConnection 的commitText()和sendKeyEvent()方法,
而这两个方法被我们重写了,我们可以在两个方法里利用消息派发,把输入的字符和删除字符动作告诉输入框。
OK了~嘿嘿
4. 还有一点要注意的,GameView要获取了焦点之后才能弹出输入法:
/**
* 显示输入法界面
*/
private void showInput() {
/* 要让GameView获得焦点后才能弹出输入法 */
this.requestFocus();
input.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
我的唠叨到此结束喇~
最后当然要附上我的代码喇~
为了来这里炫耀,这个例子我写了一个多小时,然后这篇文字我又写了差不多一个小时,大家不要辜负我吖~嘿嘿
对了,补充一下,这个方法是可以实现输入框,但是有个问题:
部分手机在横屏的情况下,会无法显示输入法的候选栏,这个我还没有解决,如果有哪位朋友解决,请分享咯~嘿嘿
代码是为了尽量节省时间,所以有些地方是写死的:
1. 一些字符串常量没有抽离出来
2. 没有写专门管理控件的模块
3. 初始化函数堆了很多东西,有些乱
4. 坐标写死
5. 除了以上4条,如果有其他问题,一定要告诉我哈,记得咯~
源代码(CSDN上传的资源还没有验证通过,大家暂时到这个帖子里下载哈):http://www.android-fans.net/forum.php?mod=viewthread&tid=99#lastpost
CSDN的资源已经上传了,补上: http://download.csdn.net/detail/musicvs/4112154