EditText 無 setEditable() 方法(API 3 棄用),動態控制可編輯狀態有三種主流方案:InputFilter 阻擋輸入、setFocusable(false) 移除焦點、setEnabled(false) 完全停用。視 UX 需求選擇。
// 設為唯讀
editText.setFilters(new InputFilter[] { new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
// 允許刪除、剪貼等非輸入操作
if (end <= start) return null; // 刪除鍵
return ""; // 阻擋所有字元輸入
}
}});
// 恢復可編輯
editText.setFilters(new InputFilter[0]); // 空陣列 = 無過濾
// 唯讀:可複製、可捲動、不可編輯、無游標、鍵盤不彈出
editText.setFocusable(false);
editText.setFocusableInTouchMode(false);
editText.setClickable(false); // 可選
editText.setLongClickable(false); // 可選
// 可編輯
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.setClickable(true);
editText.setLongClickable(true);
// 停用
editText.setEnabled(false); // 灰色、不可互動、不可複製
// 啟用
editText.setEnabled(true);
| 需求 | 推薦方案 | 外觀 | 可複製 | 鍵盤 | 游標 |
|---|---|---|---|---|---|
| 表單唯讀欄位(需複製) | setFocusable(false) | 正常 | ✅ | ❌ | ❌ |
| 條件式鎖定(保持外觀) | InputFilter | 正常 | ✅ | ✅ | ✅ |
| 完全停用(視覺區隔) | setEnabled(false) | 灰色 | ❌ | ❌ | ❌ |
| 密碼欄位切換顯示/隱藏 | setInputType + setSelection | 正常 | ❌ | ✅ | ✅ |
// 只允許數字,最長 11 位
editText.setFilters(new InputFilter[] {
new InputFilter.LengthFilter(11),
(source, start, end, dest, dstart, dend) -> {
for (int i = start; i < end; i++) {
if (!Character.isDigit(source.charAt(i))) return "";
}
return null; // 允許
}
});
| XML 屬性 | 程式碼等效 | 效果 |
|---|---|---|
android:editable="false" | 已棄用 | 舊版唯讀 |
android:focusable="false" | setFocusable(false) | 移除焦點 |
android:enabled="false" | setEnabled(false) | 完全停用 |
android:inputType="none" | setInputType(TYPE_NULL) | 隱藏鍵盤 |
setFocusable(false) + setFocusableInTouchMode(false)InputFilter 方案,解鎖只需 setFilters(new InputFilter[0])setImportantForAccessibility 確保 TalkBack 正確讀取根據互動需求選擇適當方案,InputFilter 適合「保持外觀但阻擋輸入」,setFocusable 適合標準表單唯讀。