Dấu phẩy phân tách thập phân (',') với số Kiểu đầu vào tối ưu trong EditText


133

Phần inputType numberDecimaltrong EditTextsử dụng dấu chấm '.' như dấu phân cách thập phân. Ở châu Âu, người ta thường sử dụng dấu phẩy ','. Mặc dù ngôn ngữ của tôi được đặt là tiếng Đức, dấu phân cách thập phân vẫn là '.'

Có cách nào để có dấu phẩy là dấu phân cách thập phân không?



1
lỗi này cuối cùng đã được sửa trong Android O: suetracker.google.com/issues/36907764
Lovis

Họ nói nó đã được sửa nhưng tôi không thể xác nhận nó đã sửa? bạn có thể?
sebastian

5
Tôi có thể xác nhận rằng nó KHÔNG được sửa, ít nhất là trên Nexus 4 của tôi chạy Android 8.1 (còn gọi là LineageOS 15.1). Với Cài đặt-> Ngôn ngữ được đặt thành tiếng Pháp (Pháp), EditText với android: inputType = "numberDecimal" cung cấp dấu tách ',' (dấu phẩy) nhưng vẫn từ chối chấp nhận dấu phẩy. Đề nghị '.' (dấu thập phân) được chấp nhận. Đã hơn 9 năm kể từ khi lỗi này được báo cáo lần đầu tiên. Đó có phải là một loại hồ sơ? Què.
pete

Câu trả lời:


106

Một cách giải quyết (cho đến khi Google sửa lỗi này) là sử dụng EditTextvới android:inputType="numberDecimal"android:digits="0123456789.,".

Sau đó, thêm một TextChangedListener vào EditText với phần sau afterTextChanged:

public void afterTextChanged(Editable s) {
    double doubleValue = 0;
    if (s != null) {
        try {
            doubleValue = Double.parseDouble(s.toString().replace(',', '.'));
        } catch (NumberFormatException e) {
            //Error
        }
    }
    //Do something with doubleValue
}

1
@Zoombie để dấu phẩy (,) hiển thị trên bàn phím của bạn tùy thuộc vào ngôn ngữ được đặt trên thiết bị của bạn. Nếu đầu vào của bạn có số numberDecimal và ngôn ngữ của bạn là tiếng Anh (Hoa Kỳ), nó sẽ hiển thị trên các thiết bị Nexus (tham khảo). Có thể các thiết bị không phải của Nexus không tôn trọng điều này
hcpl

11
Nó hoạt động, nhưng lưu ý rằng nó cho phép một văn bản như "24,22,55" được thông qua. Bạn có thể cần thêm một số xác nhận bổ sung để sửa lỗi này!
dimsuz

8
Đây vẫn là con đường để đi?
Willi Mentzel

Thậm chí tốt hơn, hãy sử dụng char localizedSeparator = DecimalFormatSymbols.getInstance (). GetDecimalSpayator (); localizedFloatString = localizedFloatString.replace ('.', localizedSeparator);
miền nam

4
Có vẻ như đây chỉ là giao dịch một lỗi cho người khác. Như đã thực hiện ở trên, điều này sẽ làm việc cho các địa phương sử dụng, thay vì. với chi phí ngược lại là phổ biến hơn trên toàn thế giới. Tinh chỉnh của @ southerton giúp ích cho điều đó, tuy nhiên người dùng của bạn có thể ngạc nhiên khi họ nhấn a. và có một, xuất hiện trong đầu vào.
Nick

30

Một biến thể về các giải pháp 'chữ số' được cung cấp ở đây:

char separator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));

Có tính đến dải phân cách miền địa phương.


Đây là câu trả lời rõ ràng nhất cho câu hỏi ban đầu. Cảm ơn
peter.bartos

Đặt cái này vào onCreate (), đây là cách để đi, IMHO.
TechNyquist

6
Tôi thích điều này, nhưng hãy cẩn thận ... có những bàn phím không quan tâm đến ngôn ngữ người dùng, vì vậy người dùng không có chìa khóa ,trong bàn phím của họ. Ví dụ: Bàn phím Samsung (KitKat).
Brais Gabin

2
Điều này sẽ cho phép phân tách thập phân trùng lặp. Xem câu trả lời dưới đây để xử lý nó: stackoverflow.com/a/45384821/6138589
Esdras Lopez

19

Theo dõi Mặt nạ tiền tệ mã cho EditText ($ 123,125.155)

Giao diện Xml

  <EditText
    android:inputType="numberDecimal"
    android:layout_height="wrap_content"
    android:layout_width="200dp"
    android:digits="0123456789.,$" />

EditText testFilter=...
testFilter.addTextChangedListener( new TextWatcher() {
        boolean isEdiging;
        @Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
        @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

        @Override public void afterTextChanged(Editable s) {
            if(isEdiging) return;
            isEdiging = true;

            String str = s.toString().replaceAll( "[^\\d]", "" );
            double s1 = Double.parseDouble(str);

            NumberFormat nf2 = NumberFormat.getInstance(Locale.ENGLISH);
            ((DecimalFormat)nf2).applyPattern("$ ###,###.###");
            s.replace(0, s.length(), nf2.format(s1));

            isEdiging = false;
        }
    });

16

Đây là một lỗi đã biết trong SDK Android. Cách giải quyết duy nhất là tạo bàn phím mềm của riêng bạn. Bạn có thể tìm thấy một ví dụ về việc thực hiện ở đây .


15
Có tin tức nào sau bốn năm không?
Antonio Sesto

Trải nghiệm điều này trong Xamarin.Forms là tốt. Văn hóa là {se-SV} và numpad hiển thị bot "," (dấu tách thập phân) và "." (dấu phân cách nhóm nghìn) nhưng khi nhấn "," không có gì được nhập vào trường văn bản và không có sự kiện nào được đưa ra
joacar

Tôi có thể xác nhận rằng lỗi vẫn tồn tại.
Lensflare

đã sửa trong bản xem trước dành cho nhà phát triển Android O
R00 Chúng tôi

6

Câu trả lời của Martins sẽ không hoạt động nếu bạn đang lập trình EditText theo chương trình. Tôi đã đi trước và sửa đổi bao gồmDigitsKeyListener lớp được từ API 14 để cho phép cả dấu phẩy và dấu chấm là dấu phân cách thập phân.

Để sử dụng, gọi setKeyListener()vào EditText, ví dụ:

// Don't allow for signed input (minus), but allow for decimal points
editText.setKeyListener( new MyDigitsKeyListener( false, true ) );

Tuy nhiên, bạn vẫn phải sử dụng mánh khóe của Martin ở TextChangedListenernơi bạn thay thế dấu phẩy bằng dấu chấm

import android.text.InputType;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.NumberKeyListener;
import android.view.KeyEvent;

class MyDigitsKeyListener extends NumberKeyListener {

    /**
     * The characters that are used.
     *
     * @see KeyEvent#getMatch
     * @see #getAcceptedChars
     */
    private static final char[][] CHARACTERS = new char[][] {
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', ',' },
    };

    private char[] mAccepted;
    private boolean mSign;
    private boolean mDecimal;

    private static final int SIGN = 1;
    private static final int DECIMAL = 2;

    private static MyDigitsKeyListener[] sInstance = new MyDigitsKeyListener[4];

    @Override
    protected char[] getAcceptedChars() {
        return mAccepted;
    }

    /**
     * Allocates a DigitsKeyListener that accepts the digits 0 through 9.
     */
    public MyDigitsKeyListener() {
        this(false, false);
    }

    /**
     * Allocates a DigitsKeyListener that accepts the digits 0 through 9,
     * plus the minus sign (only at the beginning) and/or decimal point
     * (only one per field) if specified.
     */
    public MyDigitsKeyListener(boolean sign, boolean decimal) {
        mSign = sign;
        mDecimal = decimal;

        int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
        mAccepted = CHARACTERS[kind];
    }

    /**
     * Returns a DigitsKeyListener that accepts the digits 0 through 9.
     */
    public static MyDigitsKeyListener getInstance() {
        return getInstance(false, false);
    }

    /**
     * Returns a DigitsKeyListener that accepts the digits 0 through 9,
     * plus the minus sign (only at the beginning) and/or decimal point
     * (only one per field) if specified.
     */
    public static MyDigitsKeyListener getInstance(boolean sign, boolean decimal) {
        int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);

        if (sInstance[kind] != null)
            return sInstance[kind];

        sInstance[kind] = new MyDigitsKeyListener(sign, decimal);
        return sInstance[kind];
    }

    /**
     * Returns a DigitsKeyListener that accepts only the characters
     * that appear in the specified String.  Note that not all characters
     * may be available on every keyboard.
     */
    public static MyDigitsKeyListener getInstance(String accepted) {
        // TODO: do we need a cache of these to avoid allocating?

        MyDigitsKeyListener dim = new MyDigitsKeyListener();

        dim.mAccepted = new char[accepted.length()];
        accepted.getChars(0, accepted.length(), dim.mAccepted, 0);

        return dim;
    }

    public int getInputType() {
        int contentType = InputType.TYPE_CLASS_NUMBER;
        if (mSign) {
            contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
        }
        if (mDecimal) {
            contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
        }
        return contentType;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dstart, int dend) {
        CharSequence out = super.filter(source, start, end, dest, dstart, dend);

        if (mSign == false && mDecimal == false) {
            return out;
        }

        if (out != null) {
            source = out;
            start = 0;
            end = out.length();
        }

        int sign = -1;
        int decimal = -1;
        int dlen = dest.length();

        /*
         * Find out if the existing text has '-' or '.' characters.
         */

        for (int i = 0; i < dstart; i++) {
            char c = dest.charAt(i);

            if (c == '-') {
                sign = i;
            } else if (c == '.' || c == ',') {
                decimal = i;
            }
        }
        for (int i = dend; i < dlen; i++) {
            char c = dest.charAt(i);

            if (c == '-') {
                return "";    // Nothing can be inserted in front of a '-'.
            } else if (c == '.' ||  c == ',') {
                decimal = i;
            }
        }

        /*
         * If it does, we must strip them out from the source.
         * In addition, '-' must be the very first character,
         * and nothing can be inserted before an existing '-'.
         * Go in reverse order so the offsets are stable.
         */

        SpannableStringBuilder stripped = null;

        for (int i = end - 1; i >= start; i--) {
            char c = source.charAt(i);
            boolean strip = false;

            if (c == '-') {
                if (i != start || dstart != 0) {
                    strip = true;
                } else if (sign >= 0) {
                    strip = true;
                } else {
                    sign = i;
                }
            } else if (c == '.' || c == ',') {
                if (decimal >= 0) {
                    strip = true;
                } else {
                    decimal = i;
                }
            }

            if (strip) {
                if (end == start + 1) {
                    return "";  // Only one character, and it was stripped.
                }

                if (stripped == null) {
                    stripped = new SpannableStringBuilder(source, start, end);
                }

                stripped.delete(i - start, i + 1 - start);
            }
        }

        if (stripped != null) {
            return stripped;
        } else if (out != null) {
            return out;
        } else {
            return null;
        }
    }
}

từ doc: KeyListener chỉ nên được sử dụng cho các trường hợp ứng dụng có bàn phím riêng trên màn hình và cũng muốn xử lý các sự kiện bàn phím cứng để khớp với nó. developer.android.com/reference/android/text/method/
mài

6

bạn có thể sử dụng như sau cho các địa phương khác nhau

private void localeDecimalInput(final EditText editText){

    DecimalFormat decFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
    DecimalFormatSymbols symbols=decFormat.getDecimalFormatSymbols();
    final String defaultSeperator=Character.toString(symbols.getDecimalSeparator());

    editText.addTextChangedListener(new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            if(editable.toString().contains(defaultSeperator))
                editText.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
            else
                editText.setKeyListener(DigitsKeyListener.getInstance("0123456789" + defaultSeperator));
        }
    });
}

Đây là giải pháp tốt nhất cho tôi, nhưng có một số vấn đề với một số điện thoại, ví dụ như Samsung, không hiển thị trạng thái hôn mê "," trong bàn phím. Vì vậy, tôi đã thay đổi điều này để cho phép cả hôn mê và chấm, nhưng sau đó thay thế cho địa phương
Riccardo Casatta

5

Bạn có thể sử dụng cách giải quyết sau đây để bao gồm dấu phẩy làm đầu vào hợp lệ: -

Thông qua XML:

<EditText
    android:inputType="number"
    android:digits="0123456789.," />

Lập trình:

EditText input = new EditText(THE_CONTEXT);
input.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));

Theo cách này, hệ thống Android sẽ hiển thị bàn phím số và cho phép nhập dấu phẩy. Hy vọng điều này trả lời câu hỏi :)


Với giải pháp này khi bạn nhấn vào ",", nhưng văn bản chỉnh sửa hiển thị "."
Ma vương Jimenez

2

Đối với các giải pháp Mono (Droid):

decimal decimalValue = decimal.Parse(input.Text.Replace(",", ".") , CultureInfo.InvariantCulture);

1

Bạn có thể làm như sau:

DecimalFormatSymbols d = DecimalFormatSymbols.getInstance(Locale.getDefault());
input.setFilters(new InputFilter[] { new DecimalDigitsInputFilter(5, 2) });
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + d.getDecimalSeparator()));

Và sau đó bạn có thể sử dụng bộ lọc đầu vào:

    public class DecimalDigitsInputFilter implements InputFilter {

Pattern mPattern;

public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
    DecimalFormatSymbols d = new DecimalFormatSymbols(Locale.getDefault());
    String s = "\\" + d.getDecimalSeparator();
    mPattern = Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}+((" + s + "[0-9]{0," + (digitsAfterZero - 1) + "})?)||(" + s + ")?");
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

    Matcher matcher = mPattern.matcher(dest);
    if (!matcher.matches())
        return "";
    return null;
}

}


có thể có một khoảng cách giữa nghìn và trăm, mẫu này sẽ từ chối đầu vào được định dạng
Eric Zhao

1

IMHO cách tiếp cận tốt nhất cho vấn đề này là chỉ sử dụng InputFilter. Một ý chính hay ở đây là DecimalDigitsInputFilter . Sau đó, bạn có thể chỉ:

editText.setInputType(TYPE_NUMBER_FLAG_DECIMAL | TYPE_NUMBER_FLAG_SIGNED | TYPE_CLASS_NUMBER)
editText.setKeyListener(DigitsKeyListener.getInstance("0123456789,.-"))
editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});

Nó làm việc như một cơ duyên, cảm ơn bạn! (sau rất nhiều giải pháp sai ở trên ...: () .
Abigail La'Fay

1
cài đặt android: chữ số = "0123456789", có thể được thêm vào EditText. Ngoài ra, thay vì trả về null trong DecimalDigitsInputFilter, bạn có thể trả về source.replace (".", ",") Theo câu trả lời stackoverflow.com/a/40020731/1510222 không có cách nào để ẩn dấu chấm trong bàn phím tiêu chuẩn
Arkadiusz Cieśliński

1

để có được bản địa hóa sử dụng đầu vào của bạn:

char sep = DecimalFormatSymbols.getInstance().getDecimalSeparator();

và sau đó thêm:

textEdit.setKeyListener(DigitsKeyListener.getInstance("0123456789" + sep));

hơn đừng quên thay thế "," bằng "." vì vậy Float hoặc Double có thể phân tích cú pháp mà không có lỗi.


1
Giải pháp này cho phép nhập nhiều dấu phẩy
Leo Droidcoder

1

Tất cả các bài viết khác ở đây đều có lỗ hổng lớn trong đó, vì vậy đây là một giải pháp sẽ:

  • Thực thi dấu phẩy hoặc dấu chấm dựa trên khu vực, sẽ không cho phép bạn nhập ngược lại.
  • Nếu EditText bắt đầu với một số giá trị, nó sẽ thay thế dấu phân cách chính xác nếu cần.

Trong XML:

<EditText
    ...
    android:inputType="numberDecimal" 
    ... />

Biến lớp:

private boolean isDecimalSeparatorComma = false;

Trong onCreate, tìm dấu phân cách được sử dụng trong miền địa phương hiện tại:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    NumberFormat nf = NumberFormat.getInstance();
    if (nf instanceof DecimalFormat) {
        DecimalFormatSymbols sym = ((DecimalFormat) nf).getDecimalFormatSymbols();
        char decSeparator = sym.getDecimalSeparator();
        isDecimalSeparatorComma = Character.toString(decSeparator).equals(",");
    }
}

Ngoài ra onCreate, Sử dụng tùy chọn này để cập nhật nó nếu bạn đang tải một giá trị hiện tại:

// Replace editText with commas or periods as needed for viewing
String editTextValue = getEditTextValue(); // load your current value
if (editTextValue.contains(".") && isDecimalSeparatorComma) {
    editTextValue = editTextValue.replaceAll("\\.",",");
} else if (editTextValue.contains(",") && !isDecimalSeparatorComma) {
    editTextValue = editTextValue.replaceAll(",",".");
}
setEditTextValue(editTextValue); // override your current value

Cũng onCreate, Thêm người nghe

editText.addTextChangedListener(editTextWatcher);

if (isDecimalSeparatorComma) {
    editText.setKeyListener(DigitsKeyListener.getInstance("0123456789,"));
} else {
    editText.setKeyListener(DigitsKeyListener.getInstance("0123456789."));
}

chỉnh sửa Đồng hồ đeo tay

TextWatcher editTextWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) { }

    @Override
    public void afterTextChanged(Editable s) {
        String editTextValue = s.toString();

        // Count up the number of commas and periods
        Pattern pattern = Pattern.compile("[,.]");
        Matcher matcher = pattern.matcher(editTextValue);
        int count = 0;
        while (matcher.find()) {
            count++;
        }

        // Don't let it put more than one comma or period
        if (count > 1) {
            s.delete(s.length()-1, s.length());
        } else {
            // If there is a comma or period at the end the value hasn't changed so don't update
            if (!editTextValue.endsWith(",") && !editTextValue.endsWith(".")) {
                doSomething()
            }
        }
    }
};

Ví dụ doS Something (), chuyển đổi sang giai đoạn chuẩn để thao tác dữ liệu

private void doSomething() {
    try {
        String editTextStr = editText.getText().toString();
        if (isDecimalSeparatorComma) {
            editTextStr = editTextStr.replaceAll(",",".");
        }
        float editTextFloatValue = editTextStr.isEmpty() ?
                0.0f :
                Float.valueOf(editTextStr);

        ... use editTextFloatValue
    } catch (NumberFormatException e) {
        Log.e(TAG, "Error converting String to Double");
    }
}

0

Android có một định dạng số tích hợp.

Bạn có thể thêm phần này vào của bạn EditTextđể cho phép số thập phân và dấu phẩy: android:inputType="numberDecimal"android:digits="0123456789.,"

Sau đó, một nơi nào đó trong mã của bạn, khi người dùng nhấp vào lưu hoặc sau khi nhập văn bản (sử dụng trình nghe).

// Format the number to the appropriate double
try { 
    Number formatted = NumberFormat.getInstance().parse(editText.getText().toString());
    cost = formatted.doubleValue();
} catch (ParseException e) {
    System.out.println("Error parsing cost string " + editText.getText().toString());
    cost = 0.0;
}

0

Tôi quyết định thay đổi dấu phẩy thành dấu chấm trong khi chỉnh sửa. Đây là cách giải quyết đơn giản và tương đối đơn giản của tôi:

    editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            EditText editText = (EditText) v; 
            String text = editText.getText().toString();
            if (hasFocus) {
                editText.setText(text.replace(",", "."));
            } else {
                if (!text.isEmpty()) {
                    Double doubleValue = Double.valueOf(text.replace(",", "."));
                    editText.setText(someDecimalFormatter.format(doubleValue));
                }
            }
        }
    });

someDecimalFormatter sẽ sử dụng dấu phẩy hoặc dấu chấm phụ thuộc vào Locale


0

Tôi không biết tại sao câu trả lời của bạn rất phức tạp. Nếu có lỗi trong SDK, bạn phải ghi đè hoặc đi xung quanh.

Tôi đã chọn cách thứ hai để giải quyết vấn đề đó. Nếu bạn định dạng chuỗi của mình Locale.ENGLISHvà sau đó đặt chuỗi đó vào EditText(ngay cả dưới dạng chuỗi trống). Thí dụ:

String.format(Locale.ENGLISH,"%.6f", yourFloatNumber);

Theo đuổi giải pháp đó kết quả của bạn tương thích với bàn phím được hiển thị. Sau đó, số float và double hoạt động theo cách điển hình cho ngôn ngữ lập trình bằng dấu chấm thay vì dấu phẩy.


0

Giải pháp của tôi là:

  • Trong hoạt động chính:

    char separator =DecimalFormatSymbols.getInstance().getDecimalSeparator(); textViewPitchDeadZone.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));

  • Trong tệp xml: android:imeOptions="flagNoFullscreen" android:inputType="numberDecimal"

và tôi đã lấy gấp đôi trong editText dưới dạng Chuỗi.


0

Tôi có thể xác nhận rằng các bản sửa lỗi được đề xuất không hoạt động trên Samsung IME (ít nhất là trên S6 và S9) và có thể cả LG. Họ vẫn hiển thị một dấu chấm dưới dạng dấu phân cách thập phân bất kể miền địa phương. Chuyển sang IME của Google đã khắc phục điều này nhưng hầu như không phải là một lựa chọn cho hầu hết các nhà phát triển.

Nó cũng chưa được sửa trong Oreo cho các bàn phím này vì đây là cách khắc phục mà Samsung và / hoặc LG phải làm và sau đó đẩy ngay cả vào các thiết bị cầm tay cổ xưa của họ.

Thay vào đó, tôi đã rẽ nhánh dự án bàn phím số và thêm một chế độ trong đó nó hoạt động như một IME: fork . Xem mẫu dự án để biết chi tiết. Điều này đã làm việc khá tốt đối với tôi và tương tự như nhiều IME giả "nhập mã PIN" mà bạn thấy trong các ứng dụng ngân hàng.

Ảnh chụp màn hình ứng dụng mẫu


0

Đã hơn 8 năm trôi qua và tôi rất ngạc nhiên, vấn đề này vẫn chưa được khắc phục ...
Tôi đã vật lộn với vấn đề đơn giản này vì câu trả lời được đánh giá cao nhất của @Martin cho phép nhập nhiều dấu phân cách, tức là người dùng có thể nhập "12 ,,, ,,, 12,1 ,, 21,2, "
Ngoài ra, mối quan tâm thứ hai là trên một số thiết bị dấu phẩy không được hiển thị trên bàn phím số (hoặc yêu cầu nhấn nhiều lần vào nút chấm)

Đây là giải pháp khắc phục của tôi, giải quyết các vấn đề được đề cập và cho phép người dùng nhập '.' và ',', nhưng trong EditText, anh ta sẽ thấy dấu tách thập phân duy nhất tương ứng với ngôn ngữ hiện tại:

editText.apply { addTextChangedListener(DoubleTextChangedListener(this)) }

Và người xem văn bản:

  open class DoubleTextChangedListener(private val et: EditText) : TextWatcher {

    init {
        et.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
        et.keyListener = DigitsKeyListener.getInstance("0123456789.,")
    }

    private val separator = DecimalFormatSymbols.getInstance().decimalSeparator

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        //empty
    }

    @CallSuper
    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
        et.run {
            removeTextChangedListener(this@DoubleTextChangedListener)
            val formatted = toLocalizedDecimal(s.toString(), separator)
            setText(formatted)
            setSelection(formatted.length)
            addTextChangedListener(this@DoubleTextChangedListener)
        }
    }

    override fun afterTextChanged(s: Editable?) {
        // empty
    }

    /**
     * Formats input to a decimal. Leaves the only separator (or none), which matches [separator].
     * Examples:
     * 1. [s]="12.12", [separator]=',' -> result= "12,12"
     * 2. [s]="12.12", [separator]='.' -> result= "12.12"
     * 4. [s]="12,12", [separator]='.' -> result= "12.12"
     * 5. [s]="12,12,,..,,,,,34..,", [separator]=',' -> result= "12,1234"
     * 6. [s]="12.12,,..,,,,,34..,", [separator]='.' -> result= "12.1234"
     * 7. [s]="5" -> result= "5"
     */
    private fun toLocalizedDecimal(s: String, separator: Char): String {
        val cleared = s.replace(",", ".")
        val splitted = cleared.split('.').filter { it.isNotBlank() }
        return when (splitted.size) {
            0 -> s
            1 -> cleared.replace('.', separator).replaceAfter(separator, "")
            2 -> splitted.joinToString(separator.toString())
            else -> splitted[0]
                    .plus(separator)
                    .plus(splitted.subList(1, splitted.size - 1).joinToString(""))
        }
    }
}

0

Giải pháp đơn giản, thực hiện một điều khiển tùy chỉnh. (điều này được thực hiện trong Xamarin android nhưng nên chuyển dễ dàng sang java)

public class EditTextDecimalNumber:EditText
{
    readonly string _numberFormatDecimalSeparator;

    public EditTextDecimalNumber(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        InputType = InputTypes.NumberFlagDecimal;
        TextChanged += EditTextDecimalNumber_TextChanged;
        _numberFormatDecimalSeparator = System.Threading.Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator;

        KeyListener = DigitsKeyListener.GetInstance($"0123456789{_numberFormatDecimalSeparator}");
    }

    private void EditTextDecimalNumber_TextChanged(object sender, TextChangedEventArgs e)
    {
        int noOfOccurence = this.Text.Count(x => x.ToString() == _numberFormatDecimalSeparator);
        if (noOfOccurence >=2)
        {
            int lastIndexOf = this.Text.LastIndexOf(_numberFormatDecimalSeparator,StringComparison.CurrentCulture);
            if (lastIndexOf!=-1)
            {
                this.Text = this.Text.Substring(0, lastIndexOf);
                this.SetSelection(this.Text.Length);
            }

        }
    }
}

0

Bạn có thể sử dụng inputType="phone", tuy nhiên trong trường hợp đó bạn sẽ phải xử lý nhiều ,hoặc .có mặt, vì vậy việc xác nhận bổ sung là cần thiết.


-1

Tôi nghĩ giải pháp này ít phức tạp hơn các giải pháp khác được viết ở đây:

<EditText
    android:inputType="numberDecimal"
    android:digits="0123456789," />

Cách này khi bạn nhấn '.' trong bàn phím mềm không có gì xảy ra; chỉ cho phép số và dấu phẩy.


4
nếu bạn làm điều này thì bạn sẽ phá vỡ tất cả các địa điểm sử dụng '.' thay thế.
Nick
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.