TextFiled是UI组件中必不可少的一部分,没有TextFiled,那么就无法输入,也就无法与用户进行更深入的交互了。LWUIT中的TextField的实现与其它的实现不太一样:很特别,很简单。在我看来,TextField中比较难的就是光标的实现,因为没有光标,用户就不知道当前输入位在那,也无法有选择性的增加删除(比如说删除倒数第三个字,在第二个字后加一个字,没有光标也就没法做这种操作),所以在这我只分析一下画光标的实现而已。
先看LWUIT中实现代码:
public void drawTextField(Graphics g, TextArea ta) {
setFG(g, ta);
// display ******** if it is a password field
String displayText = getTextFieldString(ta);
Style style = ta.getStyle();
int x = 0;
int cursorCharPosition = ta.getCursorPosition();
Font f = ta.getStyle().getFont();
int cursorX = 0;
int xPos = 0;
int align = ta.getAbsoluteAlignment();
int displayX = 0;
String inputMode = ta.getInputMode();
int inputModeWidth = f.stringWidth(inputMode);
// QWERTY devices don’t quite have an input mode hide it also when we have a VK
if(ta.isQwertyInput() || Display.getInstance().isVirtualKeyboardShowing()) {
inputMode = “”;
inputModeWidth = 0;
}
// there is currently no support for CENTER aligned text fields
if (align == Component.LEFT) {
if (cursorCharPosition > 0) {
xPos = f.stringWidth(displayText.substring(0, cursorCharPosition));
cursorX = ta.getX() + style.getPadding(ta.isRTL(), Component.LEFT) + xPos;
// no point in showing the input mode when there is only one input mode…
if(inputModeWidth > 0 && ta.getInputModeOrder() != null && ta.getInputModeOrder().length == 1) {
inputModeWidth = 0;
}
if(ta.isEnableInputScroll()) {
if (ta.getWidth() > (f.getHeight() * 2) && cursorX >= ta.getWidth()-inputModeWidth �C style.getPadding(ta.isRTL(), Component.LEFT)) {
while (x + xPos >= ta.getWidth() �C inputModeWidth �C style.getPadding(ta.isRTL(), Component.LEFT) * 2) {
x�C;
}
}
}
}
displayX = ta.getX() + x + style.getPadding(ta.isRTL(), Component.LEFT);
} else {
x = 0;
cursorX = getTextFieldCursorX(ta);
int baseX = ta.getX() + style.getPadding(false, Component.LEFT) + inputModeWidth;
int endX = ta.getX() + ta.getWidth() �C style.getPadding(false, Component.RIGHT);
if(cursorX<baseX) {
x = baseX �C cursorX;
} else {
if (cursorX > endX) {
x = endX �C cursorX;
}
}
displayX = ta.getX() + ta.getWidth() �C style.getPadding(false, Component.RIGHT) �C f.stringWidth(displayText)+x;
}
g.drawString(displayText, displayX, ta.getY() + style.getPadding(false, Component.TOP));
// no point in showing the input mode when there is only one input mode…
if(inputModeWidth > 0 && ta.getInputModeOrder() != null && ta.getInputModeOrder().length > 1) {
if (ta.handlesInput() && ta.getWidth() / 2 > inputModeWidth) {
int drawXPos = ta.getX() + style.getPadding(ta.isRTL(), Component.LEFT);
if((!ta.isRTL() && ta.getAlignment() == Component.LEFT) ||
(ta.isRTL() && ta.getAlignment() == Component.RIGHT)) {
drawXPos = drawXPos + ta.getWidth() �C inputModeWidth �C style.getPadding(false, Component.RIGHT) �C style.getPadding(false, Component.LEFT);
}
g.setColor(style.getFgColor());
g.fillRect(drawXPos, ta.getY() + style.getPadding(false, Component.TOP), inputModeWidth,
ta.getHeight(), (byte) 140);
g.setColor(style.getBgColor());
g.drawString(inputMode, drawXPos, ta.getY() + style.getPadding(false, Component.TOP));
}
}
}
代码一
红色的代码是比较重要的:
首先是得到整个输入框中的值
String displayText = getTextFieldString(ta);
代码二
接着计算文本的偏移量,然后通过下面的代码来计算它的绝对坐标
if (ta.getWidth() > (f.getHeight() * 2) && cursorX >= ta.getWidth()-inputModeWidth �C style.getPadding(ta.isRTL(), Component.LEFT)) {
while (x + xPos >= ta.getWidth() �C inputModeWidth �C style.getPadding(ta.isRTL(), Component.LEFT) * 2) {
x�C;
}
}
displayX = ta.getX() + x + style.getPadding(ta.isRTL(), Component.LEFT);
代码三
g.drawString(displayText, displayX, ta.getY() + style.getPadding(false, Component.TOP));
代码四
这段代码是什么就把光标绘制出来的了?我们可以分情况来考虑:
1、文字很短,在输入框内,这时所有文字都要draw到屏幕上去,而光标就在它所在位置上就成了
2、文字很长,输入框容纳不下,这时就有一部分文字要显示一部分文字不显示。这就分两种情况:
第一种情况就是用户一直在输入,那么光标的位置就肯定是在所有文字的后面,所以根据代码来说是显示正常的。
第二种情况就用户在一直输入后,按左右键移动光标,这时要注意的这与标准的UI控件不一样的地方,标准输入控件的如果碰到这种情况是显示的文字不变,光标向前移动一个,但是这种实现却是光标前面的文字都后退了一个字,看起来的效果就像是从后面删除了一个字一样。但是用户不注意也是无法察觉出不同来的。这也就是代码3在做的事。
这种实现的好处就在于实现简单,整个输入框的输入只要红色部分就可以了。但是缺点是它的实现不是标准的UI的实现,与用户的认识不太一样。但是如果是一个轻量级的输入框的实现的话,可以考虑这种实现的方法。
末:
之所以专门写一篇讲光标的实现,是因为我自己曾实现了一个输入控件,但是代码量是它的几倍(我实现的传统的控件),而LWUIT使用这么几行代码却实现了这功 能。看完后惊叹不已:作者是怎么想出来这种方式的实现的?!