最簡方案:XML 屬性配置
<EditText
android:id="@+id/et_field1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:imeOptions="actionNext"
android:nextFocusDown="@id/et_field2" />
<EditText
android:id="@+id/et_field2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:imeOptions="actionNext"
android:nextFocusDown="@id/et_field3" />
<!-- 最後一個輸入框 -->
<EditText
android:id="@+id/et_field20"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:imeOptions="actionDone" />
屬性詳解
| 屬性 | 作用 | 可選值 |
singleLine | 強制單行模式,回車鍵不換行 | true/false (API 3+ 棄用,建議用 maxLines="1") |
maxLines | 現代替代,限制最大行數 | 1 (單行) |
imeOptions | 設置軟鍵盤回車鍵動作 | actionNext/actionDone/actionGo/actionSearch/actionSend |
nextFocusDown | 指定下一個獲取焦點的 View ID | @id/next_edit_text |
inputType | 鍵盤類型 (配合 imeOptions) | text/textEmailAddress/textPassword/number等 |
程式化動態設置 (適用於運行時生成表單)
public void setupEditTextNavigation(List editTexts) {
for (int i = 0; i < editTexts.size(); i++) {
EditText current = editTexts.get(i);
current.setSingleLine(true); // 或 current.setMaxLines(1);
if (i < editTexts.size() - 1) {
current.setImeOptions(EditorInfo.IME_ACTION_NEXT);
current.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_NEXT) {
editTexts.get(i + 1).requestFocus();
return true; // 消費事件
}
return false;
});
} else {
// 最後一個
current.setImeOptions(EditorInfo.IME_ACTION_DONE);
current.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
hideKeyboard(current);
submitForm(); // 提交表單
return true;
}
return false;
});
}
}
}
private void hideKeyboard(View view) {
InputMethodManager imm = (InputMethodManager) view.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
進階:Tab 鍵導航支持 (實體鍵盤/平板)
// 在佈局 XML 中為每個 EditText 設置
android:nextFocusForward="@id/et_field2" // Tab 鍵下一個
android:nextFocusBack="@id/et_field1" // Shift+Tab 上一個
常見問題排查
| 現象 | 原因 | 解決 |
| 回車鍵仍換行 | 未設置 singleLine/maxLines | 添加 android:maxLines="1" |
| 鍵盤顯示「換行」而非「下一個」 | 缺少 imeOptions | 設置 actionNext |
| 跳轉錯誤/不跳轉 | nextFocusDown ID 錯誤 | 檢查 ID 拼寫、確保目標 View 可聚焦 |
| 最後一個框無法提交 | 未處理 IME_ACTION_DONE | 設置 OnEditorActionListener 調用提交邏輯 |
| 彈出鍵盤遮擋輸入框 | 窗口模式未調整 | Manifest android:windowSoftInputMode="adjustResize" |
Material Design 文字輸入框最佳實踐
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/field_label"
app:counterEnabled="true"
app:counterMaxLength="20"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:imeOptions="actionNext"
android:nextFocusDown="@id/next_field" />
</com.google.android.material.textfield.TextInputLayout>
- 內置字符計數、錯誤提示、動畫標籤
- 符合 Material Design 規範
- 更好的無障礙支持
表單驗證整合
private boolean validateAndFocusNext(EditText current, EditText next) {
String text = current.getText().toString().trim();
if (TextUtils.isEmpty(text)) {
current.setError("此項不能為空");
current.requestFocus();
return false;
}
if (next != null) {
next.requestFocus();
}
return true;
}