Android中监听EditText回车键/完成键实现实时数据保存的技术问询
Got it, let's work through fixing this issue step by step. The core problems you're dealing with are:
- The line feed Enter key (shown when your EditText is in a middle row) doesn't trigger your save logic
- You want data saved both when the user presses Enter (any variant) and when they navigate away from the EditText
Here's a complete, optimized solution that also ensures your EditText only accepts valid double values:
1. Enforce Double-Only Input First
First, let's lock down the EditText to only accept valid decimal numbers to avoid parsing errors later:
// Set input type for decimal numbers est.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); // Add a filter to prevent multiple decimal points and invalid characters est.setFilters(new InputFilter[]{new InputFilter() { @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String currentText = dest.toString(); // Block multiple decimal points if (currentText.contains(".") && source.toString().contains(".")) { return ""; } // Allow only digits and a single decimal point if (!source.toString().matches("[0-9.]")) { return ""; } return null; } }});
2. Fix Enter Key Listener to Catch All Enter Variants
Your current listener misses the line feed Enter because it's tied to IME_ACTION_DONE. Let's adjust it to catch every Enter press, regardless of the keyboard's displayed action:
est.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // Check for any Enter key press (including line feed and done) boolean isEnterTrigger = (event != null && event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER) || actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT; // Catch line feed Enter if (isEnterTrigger) { saveEditTextData(est); // Hide keyboard after save InputMethodManager inputManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); return true; // Consume the event to prevent default behavior } return false; } });
3. Add Focus Loss Listener to Save When Navigating Away
To cover cases where the user taps outside the EditText or switches to another input, add a focus change listener:
est.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { // Save data immediately when the EditText loses focus saveEditTextData((EditText) v); } } });
4. Reusable Save Logic (Avoid Code Duplication)
Extract your save logic into a single method to keep your code clean and maintainable:
private void saveEditTextData(EditText editText) { String input = editText.getText().toString().trim(); Double damageCost = 0d; // Parse input safely if (!TextUtils.isEmpty(input)) { try { damageCost = Double.parseDouble(input); // Or use your existing getCleanDoubleValue() method: // damageCost = editText.getCleanDoubleValue(); } catch (NumberFormatException e) { // Handle invalid input (optional: show feedback to user) Toast.makeText(getContext(), "Please enter a valid number", Toast.LENGTH_SHORT).show(); editText.setText("0"); damageCost = 0d; } } Log.d("COST", String.valueOf(damageCost)); // Your existing validation and update logic if (ds.size() == 0) { new Handler(Looper.getMainLooper()).post(() -> { Toast.makeText(getContext(), "Please add damage to the vehicle to edit price", Toast.LENGTH_SHORT).show(); editText.setText(nf.format(vehicle.getTotal()).substring(1)); InputMethodManager inputManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(editText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); }); return; } for (Damage damage : ds) { if (damage == null) continue; for (VehicleUpdate vehicleUpdateItem : vehicleUpdate) { Vehicle vehicleUp = vehicleUpdateItem.vehicle; if (vehicleUp == null) continue; if (String.valueOf(damage.getVehicle()).equals(String.valueOf(vehicleUp.getUuid()))) { Log.d("DAMAGE UUID", String.valueOf(damage.getVehicle())); try { vehicleUp.setTotal(Objects.requireNonNull(damageCost)); vehicleRepository.update(vehicleUp); } catch (NullPointerException e) { Log.d("null", "Null pointer while updating vehicle"); } } } } }
Optional: Force Keyboard to Show Done Key (Instead of Line Feed)
If you prefer the keyboard to always show the Done button (even for middle rows), add these lines to your EditText setup:
est.setImeOptions(EditorInfo.IME_ACTION_DONE); est.setSingleLine(true); // Note: This makes the EditText single-line; adjust if you need multi-line support
内容的提问来源于stack exchange,提问作者KCYrgn




