javax.microedition.lcdui.TextBox 是 MIDP 高級 UI 中唯一支持多行、多模式文本輸入的 Screen 子類。它集成了設備原生輸入法、支持輸入限制 (數字/郵箱/電話/密碼等)、內置游標編輯、可附加 Ticker 跑馬燈。本文系統梳理構造參數、輸入模式、Command 交互、驗證最佳實踐,提供完整可運行示例。
TextBox(String title, String text, int maxSize, int constraints)
| 參數 | 說明 | 注意事項 |
|---|---|---|
| title | 標題欄文本 | 顯示在屏幕頂部 |
| text | 初始文本內容 | 可為空字符串 "",不可為 null |
| maxSize | 最大字符數 (非字節數) | 設備可能強制更小限制,實際可輸入以 getMaxSize() 為準 |
| constraints | 輸入限制模式 (位掩碼組合) | 決定軟鍵盤類型、允許字符集、顯示方式 |
定義在 TextField 類中,TextBox 繼承使用:
| 常量 | 值 | 允許輸入 | 軟鍵盤/顯示行為 | 典型場景 |
|---|---|---|---|---|
| ANY | 0 | 任意字符 | 全鍵盤 | 一般文本、備註 |
| EMAILADDR | 1 | 郵箱字符集 (@ . _ - 字母數字) | 郵箱優化鍵盤 | 郵箱輸入 |
| NUMERIC | 2 | 僅數字 0-9 | 數字鍵盤 | 數量、ID |
| PHONENUMBER | 3 | 電話字符 (+ - * # 數字) | 撥號鍵盤 | 電話號碼 |
| URL | 4 | URL 字符集 (/ : . - _ ~ 字母數字) | URL 優化鍵盤 | 網址輸入 |
| DECIMAL | 5 | 數字 + 小數點 (設備相關) | 數字鍵盤含小數點 | 金額、坐標 |
修飾符 (可與上述 OR 組合):
PASSWORD (0x10000):顯示為 * / ●,不回顯明文UNEDITABLE (0x20000):只讀,不可編輯SENSITIVE (0x40000):不存入設備預測詞典/自動完成NON_PREDICTIVE (0x80000):關閉 T9/智能輸入INITIAL_CAPS_WORD / SENTENCE:首字母大寫提示
// 組合示例:密碼模式 + 敏感不記錄
int constraints = TextField.PASSWORD | TextField.SENSITIVE;
// 郵箱 + 首字母小寫
int constraints = TextField.EMAILADDR | TextField.INITIAL_CAPS_WORD;
TextBox box = new TextBox("登錄", "", 20, TextField.ANY);
// 設置初始文本
box.setString("默認值");
// 獲取用戶輸入
String input = box.getString();
// 設置最大長度 (可能受限於構造時 maxSize)
box.setMaxSize(30);
// 設置/獲取輸入模式
box.setConstraints(TextField.NUMERIC | TextField.PASSWORD);
// 添加 Command (必須!否則用戶無法觸發動作,陷入輸入框)
box.addCommand(new Command("確定", Command.OK, 1));
box.addCommand(new Command("取消", Command.CANCEL, 2));
box.setCommandListener(listener);
// Ticker 跑馬燈
box.setTicker(new Ticker("請輸入用戶名..."));
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class TextBoxDemoMIDlet extends MIDlet implements CommandListener {
private Display display;
private Form configForm;
private ChoiceGroup typeChoice, optionChoice;
private static final Command CMD_SHOW = new Command("啟動輸入", Command.OK, 1);
private static final Command CMD_EXIT = new Command("退出", Command.EXIT, 2);
private static final Command CMD_BACK = new Command("返回", Command.BACK, 1);
private static final String[] TYPE_LABELS = {"任意文本", "郵箱", "純數字", "小數", "電話", "網址"};
private static final int[] TYPE_VALUES = {
TextField.ANY, TextField.EMAILADDR, TextField.NUMERIC,
TextField.DECIMAL, TextField.PHONENUMBER, TextField.URL
};
protected void startApp() {
if (display == null) display = Display.getDisplay(this);
if (configForm == null) buildConfigForm();
display.setCurrent(configForm);
}
private void buildConfigForm() {
configForm = new Form("TextBox 模式選擇");
typeChoice = new ChoiceGroup("輸入類型", Choice.EXCLUSIVE, TYPE_LABELS, null);
optionChoice = new ChoiceGroup("顯示選項", Choice.MULTIPLE,
new String[]{"密碼模式", "顯示跑馬燈"}, null);
configForm.append(typeChoice);
configForm.append(optionChoice);
configForm.addCommand(CMD_SHOW);
configForm.addCommand(CMD_EXIT);
configForm.setCommandListener(this);
}
public void commandAction(Command c, Displayable d) {
if (c == CMD_EXIT) { notifyDestroyed(); return; }
if (c == CMD_BACK) { display.setCurrent(configForm); return; }
if (c != CMD_SHOW) return;
int idx = typeChoice.getSelectedIndex();
int constraints = TYPE_VALUES[idx];
boolean[] opts = new boolean[2];
optionChoice.getSelectedFlags(opts);
if (opts[0]) constraints |= TextField.PASSWORD; // 密碼模式覆蓋類型
if (opts[1]) { /* 跑馬燈稍後設置 */ }
TextBox box = new TextBox(TYPE_LABELS[idx], "", 50, constraints);
if (opts[1]) box.setTicker(new Ticker("TextBox: " + TYPE_LABELS[idx]));
box.addCommand(CMD_BACK);
box.setCommandListener(this);
display.setCurrent(box);
}
protected void pauseApp() {}
protected void destroyApp(boolean unconditional) {}
}
| 場景 | 正確做法 | 常見錯誤 |
|---|---|---|
| 密碼輸入 | PASSWORD | SENSITIVE (不記錄預測詞) | 僅用 PASSWORD,系統可能記錄明文預測 |
| 金額輸入 | DECIMAL + 後端再次驗證格式 | 信任前端格式,忽略設備差異 (某設備 DECIMAL 允許多個點) |
| 必填驗證 | CommandListener 中 getString().trim().isEmpty() 判斷 | 不驗證直接提交空值 |
| 長文本輸入 | maxSize 設大 (如 2000),分頁顯示或提示剩餘字數 | maxSize 太小導致內容截斷 |
| 跑馬燈提示 | 關鍵提示信息 (格式示例、必填說明) | 無提示或提示過長遮擋輸入區 |
| 無 Command | **必須添加至少一個 Command (OK/BACK)** | 用戶無法退出輸入框,應用假死 |
| 維度 | TextBox | TextField |
|---|---|---|
| 類別 | Screen 子類 (獨立顯示) | Item 子類 (放入 Form) |
| 佈局 | 全屏獨佔 | Form 中流式佈局 |
| 適用場景 | 獨立輸入頁面、登錄、搜索、大文本編輯 | 表單多字段、混合選項/輸入 |
| Command 支持 | 直接添加 | 依賴 Form 的 Command |
| Ticker 支持 | 支持 | 不支持 (Form 支持) |
TextBox 是 MIDP 文本輸入的核心組件,掌握約束模式組合、Command 交互閉環、密碼/敏感標誌、跑馬燈輔助即可覆蓋 95% 輸入場景。鐵律:無 Command 不創建 TextBox,否則用戶將無法退出輸入模式。現代 J2ME 開發極少,但此「模式化輸入 + 模態交互」設計思想在 Android EditText inputType、iOS UITextField keyboardType、Web input type/pattern 中完美延續。