javax.microedition.lcdui.List 是 MIDP 高級 UI 中專門用於單選/多選/隱式選擇的 Screen 子類。它內置選項管理、圖標支持、命令交互、選中狀態維護,是構建菜單、設置頁、多選表單的核心組件。本文系統解析三大模式 (EXCLUSIVE/IMPLICIT/MULTIPLE) 差異、核心 API、選中狀態操作、命令處理機制,提供完整三模式演示代碼。
三大列表模式核心差異
| 模式常量 | 中文名 | 選擇行為 | 命令觸發機制 | 典型場景 |
| Choice.EXCLUSIVE | 單選 (Radio) | 同一時刻僅一項被選中,選中新項自動取消舊項 | 用戶按「確定」鍵觸發 List.SELECT_COMMAND | 設置頁單選、菜單導航 |
| Choice.IMPLICIT | 隱式/即時 | 單選外觀,**選中即觸發動作**,無需額外確認鍵 | **選中瞬間自動發送 List.SELECT_COMMAND** | 主菜單、快速啟動列表 |
| Choice.MULTIPLE | 多選 (Checkbox) | 可同時選中多項,再次點擊切換勾選狀態 | 用戶按「確定」鍵觸發 List.SELECT_COMMAND | 批量操作、權限勾選、標簽選擇 |
構造函數與項目管理 API
// 構造函數 1: 標題 + 模式 + 字符串數組 + 圖標數組
List list = new List("標題", Choice.EXCLUSIVE, new String[]{"項1","項2"}, new Image[]{img1, img2});
// 構造函數 2: 標題 + 模式 (空列表,後續動態添加)
List list = new List("標題", Choice.MULTIPLE);
// 核心項目操作
list.append("新項目", icon); // 末尾添加
list.insert(0, "插入項目", icon); // 指定索引插入
list.set(0, "修改項目", newIcon); // 替換指定索引
list.delete(0); // 刪除指定索引
list.deleteAll(); // 清空列表
String text = list.getString(0); // 獲取文本
Image img = list.getImage(0); // 獲取圖標
int size = list.size(); // 項目數量
選中狀態管理 API (核心)
| 方法 | 適用模式 | 說明 |
getSelectedIndex() | EXCLUSIVE, IMPLICIT | 獲取當前選中項索引 (-1 表示無) |
setSelectedIndex(i, true) | EXCLUSIVE, IMPLICIT | 設置選中 (單選模式下自動取消其他) |
isSelected(i) | MULTIPLE | 檢查指定索引是否被勾選 |
getSelectedFlags(boolean[] arr) | MULTIPLE | 批量獲取勾選狀態到數組 (arr[0]=true 表示選中) |
setSelectedFlags(boolean[] arr) | MULTIPLE | 批量設置勾選狀態 |
命令處理機制詳解
list.addCommand(new Command("確定", Command.OK, 1));
list.addCommand(new Command("返回", Command.BACK, 2));
list.setCommandListener(listener);
// CommandListener 實現
public void commandAction(Command c, Displayable d) {
if (d instanceof List) {
List list = (List) d;
if (c == List.SELECT_COMMAND) { // 選中觸發 (IMPLICIT 自動發送,EXCLUSIVE/MULTIPLE 需按確定鍵)
int idx = list.getSelectedIndex(); // 單選/隱式
// 多選模式需用 getSelectedFlags
boolean[] flags = new boolean[list.size()];
list.getSelectedFlags(flags);
// 業務處理...
} else if (c.getCommandType() == Command.BACK) {
// 返回上級
}
}
}
完整三模式演示 MIDlet
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ListDemoMIDlet extends MIDlet implements CommandListener {
private Display display;
private List mainMenu, exclusiveList, implicitList, multipleList;
private static final Command CMD_EXIT = new Command("退出", Command.EXIT, 1);
private static final Command CMD_BACK = new Command("返回", Command.BACK, 1);
private Image[] icons;
protected void startApp() {
if (display == null) display = Display.getDisplay(this);
if (mainMenu == null) buildLists();
display.setCurrent(mainMenu);
}
private void buildLists() {
// 加載圖標 (捕獲異常防止設備不支持)
try {
Image icon = Image.createImage("/res/icon.png");
icons = new Image[]{icon, icon, icon, icon};
} catch (Exception e) { icons = null; }
String[] items = {"選項 A", "選項 B", "選項 C", "選項 D"};
// 1. 單選列表
exclusiveList = new List("單選模式", Choice.EXCLUSIVE, items, icons);
exclusiveList.addCommand(CMD_BACK);
exclusiveList.addCommand(CMD_EXIT);
exclusiveList.setCommandListener(this);
// 2. 隱式列表 (選中即執行)
implicitList = new List("隱式模式", Choice.IMPLICIT, items, icons);
implicitList.addCommand(CMD_BACK);
implicitList.addCommand(CMD_EXIT);
implicitList.setCommandListener(this);
// 可選:關閉隱式自動選中命令
// implicitList.setSelectCommand(null);
// 3. 多選列表
multipleList = new List("多選模式", Choice.MULTIPLE, items, icons);
multipleList.addCommand(CMD_BACK);
multipleList.addCommand(CMD_EXIT);
multipleList.setCommandListener(this);
// 主菜單 (隱式模式導航)
String[] menuItems = {"單選模式", "隱式模式", "多選模式"};
mainMenu = new List("請選擇列表類型", Choice.IMPLICIT, menuItems, icons);
mainMenu.addCommand(CMD_EXIT);
mainMenu.setCommandListener(this);
}
public void commandAction(Command c, Displayable d) {
if (d == mainMenu) {
if (c == List.SELECT_COMMAND) {
switch (mainMenu.getSelectedIndex()) {
case 0: display.setCurrent(exclusiveList); break;
case 1: display.setCurrent(implicitList); break;
case 2: display.setCurrent(multipleList); break;
}
} else if (c == CMD_EXIT) { notifyDestroyed(); }
} else if (d == exclusiveList || d == implicitList || d == multipleList) {
if (c == CMD_BACK) {
display.setCurrent(mainMenu);
} else if (c == CMD_EXIT) {
notifyDestroyed();
} else if (c == List.SELECT_COMMAND) {
// 處理選中邏輯 (演示打印)
List list = (List) d;
if (list.getType() == Choice.MULTIPLE) {
boolean[] flags = new boolean[list.size()];
list.getSelectedFlags(flags);
System.out.println("多選結果: " + Arrays.toString(flags));
} else {
System.out.println("單選/隱式選中: " + list.getString(list.getSelectedIndex()));
}
}
}
}
protected void pauseApp() {}
protected void destroyApp(boolean unconditional) {}
}
進階技巧與避坑指南
| 技巧/坑點 | 說明 |
| 動態修改列表內容 | 在 paint() 或命令處理中 insert/delete/set 後,列表自動重繪,無需手動刷新 |
| 圖標尺寸統一 | 所有項目圖標建議同尺寸 (如 16x16 或 24x24),否則行高不一致影響美觀 |
| IMPLICIT 模式關閉自動選中 | list.setSelectCommand(null) 後,選中不再發送 SELECT_COMMAND,需自行在命令中處理 (第一個參數為 null) |
| MULTIPLE 模式全選/反選 | 遍歷 size() 調用 setSelectedFlags 或逐項 setSelectedIndex(i, true/false) |
| 超長列表性能 | 項目 > 50 時滾動卡頓,建議分頁或使用自定義 Canvas 實現虛擬列表 |
| 文本過長截斷 | 設備自動截斷顯示,重要信息前置;可用 Font.stringWidth() 預估 |
| 命令優先級 | 同類型 Command 按 priority 排序,priority 越小越優先顯示在左軟鍵 |
總結
List 三大模式覆蓋了移動端單選導航 (EXCLUSIVE)、即時啟動 (IMPLICIT)、批量勾選 (MULTIPLE)核心交互場景。掌握模式選擇、選中狀態 API (單選用 Index,多選用 Flags)、SELECT_COMMAND 觸發時機差異是高效開發的關鍵。此「模式化選擇組件」設計思想在 Android ListView choiceMode、iOS UITableView allowsMultipleSelection、Web select multiple / radio group 中完美延續。