J2ME 內建的 List 類功能較弱,未實現 View 與 Model 的分離,導致控制較為繁瑣。若自行繪製 Canvas 版 TreeList 則需大量座標計算,開發難度高。本文介紹一種折衷方案:繼承 List 類,封裝資料模型,實現一個易於控制、支援兩層展開收合的目錄樹組件。
每個節點資料包含:預設圖示路徑、選中狀態圖示路徑、節點類型(GROUP/ITEM)、顯示標籤、攜帶的任意物件內容、是否展開狀態。
public class ExpandListItem {
private String imagePath = "";
private String selectImgPath = null;
public static final int GROUP = 1;
public static final int ITEM = 0;
private boolean ifselected = false;
private String label;
private int type;
private Object content;
// getter/setter 略
}
說明:GROUP 代表父節點,其 content 為包含子節點的 Vector;ITEM 為葉子節點。selectImgPath 為空時選中不切換圖示。
繼承自 List,實現 CommandListener。核心資料結構:
itemList:真實資料儲存 VectorappearHookList:螢幕顯示順序的節點列表(含展開的子節點)currentSelectedIndex / currentSelectedObject:當前選中項索引與物件public void LoadList() {
Init(); // 清空顯示列表
for (int i = 0; i < itemList.size(); i++) {
ExpandListItem elItem = (ExpandListItem) itemList.elementAt(i);
if (elItem.getType() == ExpandListItem.GROUP) {
Image icon = Util.getImage(elItem.getImagePath());
if (elItem.Ifselected()) { // 展開狀態
if (elItem.getSelectImgPath() != null)
icon = Util.getImage(elItem.getSelectImgPath());
appendItem(elItem, icon, false); // 父節點
Vector group = (Vector) elItem.getContent();
for (int j = 0; j < group.size(); j++) { // 遞歸添加子節點
ExpandListItem item = (ExpandListItem) group.elementAt(j);
appendItem(item, Util.getImage(item.getImagePath()), true);
}
} else { // 收合狀態僅顯示父節點
appendItem(elItem, icon, false);
}
} else { // ITEM 類型
appendItem(elItem, Util.getImage(elItem.getImagePath()), false);
}
}
if (currentSelectedIndex != -1)
setSelectedIndex(currentSelectedIndex, true);
}
使用者點選節點時:
Vector v = new Vector();
v.addElement(new ExpandListItem(subVector1, "/img/close.png", "/img/open.png", "群組A", ExpandListItem.GROUP, false));
v.addElement(new ExpandListItem(subVector2, "/img/close.png", "/img/open.png", "群組B", ExpandListItem.GROUP, false));
v.addElement(new ExpandListItem("單項內容", "/img/item.png", null, "單項", ExpandListItem.ITEM, false));
Display.getDisplay(this).setCurrent(new ExpandList("標題", Choice.IMPLICIT, v));
此方案利用 List 現有繪製機制,以資料驅動視圖更新,避免了 Canvas 座標計算的複雜度。雖全量重繪在大量資料時效率稍低,但對於典型手機選單層級足夠使用。未來可優化為局部插入/刪除子節點,進一步提升效能。最徹底的方案仍是自繪 Canvas,靈活度最高。