您的位置:首页 > 产品设计 > UI/UE

仿造LWUIT textField的一次尝试

2009-11-20 20:10 92 查看
在应用程序开发中经常遇到用户输入的问题;Sun MIDP提供了TextField控件;这个控件用起来不方便,一个原因是TextField的实现,不同的java虚拟机移植,实现不同,有的java虚拟机实现不方便,应用开发者对此无能为力;比如我现在用的这个j2me平台,用户输入必须要先暂停虚拟机,切换到另一个本地实现的窗口,输入完毕后,再恢复虚拟机;客户对此抱怨很大;另一个原因是高级UI入门简单,但要实现自己想要的功能,就显得不灵活,而且经常会添乱。所以,我决定写一个用户输入类,支持英文字符输入和数字输入,支持输入模式切换,不支持汉字输入,不需要暂停虚拟机。而LWUIT的TextField控件恰好实现了我想要的功能。

简单地模仿它写了一段测试代码:

import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.*;
import java.util.Hashtable;
import java.util.Vector;

public class inputCanvas extends Canvas{
String m_strInput = "";
private static Hashtable inputModes;
private static Vector v_InputMode = new Vector();
private static Object s_CurrInputMode;

private static final String[] DEFAULT_KEY_CODES = {
// 0
" 0",
// 1
".,?!'/"1-()@/:_",
// 2
"ABC2",
// 3
"DEF3",
// 4
"GHI4",
// 5
"JKL5",
// 6
"MNO6",
// 7
"PQRS7",
// 8
"TUV8",
// 9
"WXYZ9",
};

private int m_iPressCount = 0;
private int m_iPrevKeyCode = 0;

private final static int fs_maxLength = 10;

static{
initInputModes();
}

public inputCanvas(){
this.setFullScreenMode(true);
}
public void paint(Graphics g){
g.setColor(0xFFFFFF);
g.fillRect(0, 0, this.getWidth(), this.getHeight());

g.setColor(0x000000);

g.drawString(m_strInput, 0, 0, Graphics.LEFT|Graphics.TOP);

g.drawString((String)s_CurrInputMode, 0, 50, Graphics.LEFT|Graphics.TOP);
}

protected void keyPressed(int keyCode){
m_iPressCount = 0;
m_iPrevKeyCode = keyCode;

if((keyCode >= 48)&&(keyCode <= 57)){
char c = getCharPerKeyCode(m_iPressCount,(keyCode-48));
insertChars(""+c,false);
}else if(keyCode == 35){
switchInputModes();
}else if(keyCode == -7){
deleteChar();
}
repaint();
}

protected void keyRepeated(int keyCode){
if((keyCode >= 48)&&(keyCode <= 57)&&(m_iPrevKeyCode == keyCode)){
m_iPressCount++;
char c = getCharPerKeyCode(m_iPressCount,(keyCode-48));
insertChars(""+c,true);
repaint();
}
}

protected void deleteChar(){
if(m_strInput.length() > 0){
m_strInput = m_strInput.substring(0, m_strInput.length()-1);
}
}

protected void insertChars(String c, boolean bOverWrite){

if(c == null){
return;
}
if(c.length() != 1){
return;
}
if(bOverWrite){
m_strInput = m_strInput.substring(0, m_strInput.length()-1)+c;
}else{
if(m_strInput.length() < fs_maxLength){
m_strInput = m_strInput + c;
}
}
}

protected char getCharPerKeyCode(int pressCount, int keyCode){

Hashtable mode = (Hashtable)inputModes.get(s_CurrInputMode);
String str = (String)mode.get(new Integer(keyCode+'0'));

if(str != null){
pressCount = pressCount%str.length();
return str.charAt(pressCount);
}
return 0;
}

private void switchInputModes(){
int iIndex = v_InputMode.indexOf(s_CurrInputMode);

iIndex = (iIndex+1)%v_InputMode.size();

s_CurrInputMode = v_InputMode.elementAt(iIndex);
}

private static void initInputModes(){
if(inputModes == null) {
inputModes = new Hashtable();
Hashtable upcase = new Hashtable();
for(int iter = 0 ; iter < DEFAULT_KEY_CODES.length ; iter++) {
upcase.put(new Integer('0' + iter), DEFAULT_KEY_CODES[iter]);
}

v_InputMode.addElement("ABC");
inputModes.put("ABC", upcase);

Hashtable lowcase = new Hashtable();
for(int iter = 0 ; iter < DEFAULT_KEY_CODES.length ; iter++) {
lowcase.put(new Integer('0' + iter), DEFAULT_KEY_CODES[iter].toLowerCase());
}

v_InputMode.addElement("abc");
inputModes.put("abc", lowcase);

Hashtable numbers = new Hashtable();
for(int iter = 0 ; iter < 10 ; iter++) {
numbers.put(new Integer('0' + iter), "" + iter);
}
inputModes.put("123", numbers);
v_InputMode.addElement("123");

s_CurrInputMode = v_InputMode.elementAt(0);
}
}
}


基本的原理是:

1. keyPress和keyRepeated;通过特殊的按键切换输入模式、删除键值;我这里没有做光标;

2. 一种输入模式对应一个Hashtable,然后将所有的输入模式放在一个hashtable;根据输入模式、键值和按键次数查询字符;

实际的效果并不好;经过测试发现,当一直按住某个键时,首先是keyPressed被回调,然后是keyRepeated不断地被调用;要切换某个字符,唯一的选择是一直按住某个键,直到想要的那个字符出现;而实际的情况是,按键的响应快过显示结果,很难精确地在看到某个字符时释放按键。

还需要改进。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: