You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android中监听EditText回车键/完成键实现实时数据保存的技术问询

Solution for Handling Enter Key (Including Line Feed) and Focus Loss to Save Data

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

火山引擎 最新活动