EditText에서 numberDecimal inputType이있는 10 진 구분 기호 쉼표 ( ',')


133

그만큼 inputType numberDecimal에서이 EditText점을 사용합니다 '.' 소수점 구분 기호로. 유럽에서는 쉼표 ','를 사용하는 것이 일반적입니다. 내 로캘이 독일어로 설정되어 있어도 소수점 구분 기호는 여전히 '.'입니다.

쉼표를 소수점 구분 기호로 얻는 방법이 있습니까?



1
이 버그는 Android O에서 수정되었습니다. issuetracker.google.com/issues/36907764
Lovis

그들은 그것이 고정되어 있다고 말하지만 고정 된 것을 확인할 수 없습니까? 너는 할수 있니?
sebastian

5
적어도 Android 8.1 (일명 LineageOS 15.1)을 실행하는 Nexus 4에서 수정되지 않았 음을 확인할 수 있습니다. Settings-> Language를 French (France)로 설정하면 android : inputType = "numberDecimal"이있는 EditText는 ','(쉼표) 구분 기호를 제공하지만 여전히 쉼표를 허용하지 않습니다. 제공되는 '.' (소수점)이 허용됩니다. 이 버그가 처음보고 된 지 9 년이 지났습니다. 그게 어떤 기록인가요? 절름발이.
pete

답변:


105

해결 방법은 (구글이이 버그를 해결 될 때까지)을 사용하는 것입니다 EditText함께 android:inputType="numberDecimal"하고 android:digits="0123456789.,".

그런 다음 다음 afterTextChanged를 사용하여 TextChangedListener를 EditText에 추가하십시오.

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는 장치에 설정된 언어에 따라 다릅니다. 입력 한 숫자가 10 진수이고 언어가 영어 (미국) 인 경우 Nexus 기기에 표시됩니다 (참조). 그것은 비 Nexus 기기가이 존중하지 않는 것이 가능
HCPL

11
작동하지만 "24,22.55"와 같은 텍스트가 통과 할 수 있습니다. 이 문제를 해결하려면 추가 유효성 검사를 추가해야 할 수도 있습니다!
dimsuz

8
이것은 여전히 ​​갈 길입니까?
Willi Mentzel 2016 년

더 좋은 방법은 char localizedSeparator = DecimalFormatSymbols.getInstance (). getDecimalSeparator ();를 사용하는 것입니다. localizedFloatString = localizedFloatString.replace ( '.', localizedSeparator);
southerton

4
이것은 단지 하나의 버그를 다른 버그로 교환하는 것 같습니다. 위에서 구현 된 것처럼이 대신에을 사용하는 로케일에서 작동합니다. 전 세계적으로 더 일반적으로 반대의 비용으로. @ southerton 's tweak가 도움을 주지만 사용자가을 (를) 누르면 놀라게 될 수 있습니다. 입력에가 나타납니다.
Nick

30

여기에 제공되는 '숫자'솔루션의 변형 :

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

로캘 구분 기호를 고려합니다.


이것은 원래 질문에 대한 가장 확실한 대답입니다. 감사합니다
peter.bartos

이것을 onCreate ()에 넣으십시오.이 방법은 IMHO입니다.
TechNyquist

6
나는 이것을 좋아하지만 조심해야합니다 ... 사용자 로캘을 신경 쓰지 않는 키보드가 있으므로 키보드에 키가없는 사용자가 ,있습니다. 예 : 삼성 키보드 (KitKat)
Brais Gabin

2
이렇게하면 소수점 구분 기호가 중복 될 수 있습니다. 아래 답변을 참조하십시오 : stackoverflow.com/a/45384821/6138589
Esdras Lopez

19

EditText에 대한 다음 코드 통화 마스크 ($ 123,125.155)

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

이것은 Android SDK 의 알려진 버그 입니다. 유일한 해결 방법은 고유 한 소프트 키보드를 만드는 것입니다. 여기서 구현 예제를 찾을 수 있습니다 .


15
4 년 후 뉴스가 있습니까?
Antonio Sesto

Xamarin.Forms에서도 이것을 경험하십시오. 문화권은 {se-SV}이고 숫자 키패드는 봇 ","(소수 구분 기호) 및 "."를 표시합니다. (천 그룹 구분자) ""를 누르면 텍스트 필드에 아무 것도 입력되지 않으며 아무런 이벤트도 발생하지 않습니다.
joacar

버그가 여전히 존재하는지 확인할 수 있습니다.
Lensflare

Android O 개발자 미리보기에서 수정 됨
R00We

6

프로그래밍 방식으로 EditText를 인스턴스화하면 Martins 답변이 작동하지 않습니다. DigitsKeyListener쉼표와 마침표를 소수점 구분 기호로 사용할 수 있도록 API 14에서 포함 된 클래스를 수정했습니다 .

이를 사용하려면 전화 setKeyListener()EditText, 예를 들어,

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

그러나 TextChangedListener쉼표를 마침표로 바꾸는 경우 여전히 Martin의 트릭을 사용해야 합니다.

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;
        }
    }
}

doc : KeyListener는 응용 프로그램에 자체 온 스크린 키패드가 있고 하드 키보드 이벤트를 처리하여 일치시키려는 경우에만 사용해야합니다. developer.android.com/reference/android/text/method/…
Loda

6

다른 로케일에 대해 다음을 사용할 수 있습니다

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));
        }
    });
}

이것은 나에게 가장 좋은 해결책이지만 키보드와 같이 ","쉼표를 표시하지 않는 Samsung과 같은 일부 전화에는 문제가 있습니다. 그래서 나는 코마와 도트를 모두 허용하도록 이것을 변경했지만 그에 따라 로케일로 대체했습니다.
Riccardo Casatta

5

다음 해결 방법을 사용하여 쉼표를 유효한 입력으로 포함 할 수도 있습니다.

XML을 통해 :

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

프로그래밍 방식으로 :

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

이런 식으로 안드로이드 시스템은 숫자의 키보드를 보여주고 쉼표 입력을 허용합니다. 이것이 질문에 대답하기를 바랍니다 :)


이 솔루션을 사용하면 ","를 탭하지만 편집 텍스트는 "."
Mara Jimenez

2

모노 (Droid) 솔루션의 경우 :

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

1

다음을 수행 할 수 있습니다.

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

그런 다음 입력 필터를 사용할 수 있습니다.

    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;
}

}


천과 백 사이의 공백이있을 수 있습니다.이 패턴은 형식화 된 입력을 거부합니다.
Eric Zhao

1

이 문제에 대한 가장 좋은 방법은 InputFilter를 사용하는 것입니다. 좋은 요지는 여기 DecimalDigitsInputFilter 입니다. 그럼 당신은 할 수 있습니다 :

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)});

그것은 매력처럼 작동했습니다, 감사합니다! (위의 너무 많은 잘못된 해결책 후에 ... :() 그러나 질문이 있습니다 : 헝가리에서는 쉼표를 소수점 구분 기호로 사용하기 때문에 점 ( ".")이 아닌 화면에 표시되는 쉼표 ( ",")를 어떻게 얻을 수 있습니까? .
아비가일 La'Fay

1
android : digits = "0123456789,"설정을 EditText에 추가 할 수 있습니다. 대신 DecimalDigitsInputFilter에 널 (null)을 반환하는 또한, 당신은 ( "", ".") source.replace를 반환 할 수 있습니다 응답에 따라 stackoverflow.com/a/40020731/1510222 표준 키보드에서 숨기기 점에 방법이 없습니다
Arkadiusz Cieśliński

1

입력 사용을 현지화하려면 :

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

다음을 추가하십시오.

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

","를 "."로 바꾸는 것을 잊지 마십시오. Float 또는 Double은 오류없이 구문 분석 할 수 있습니다.


1
이 솔루션을 사용하면 여러 개의 쉼표를 입력 할 수 있습니다
Leo Droidcoder

1

여기에있는 다른 모든 게시물에는 큰 구멍이 있었으므로 다음과 같은 해결책이 있습니다.

  • 지역을 기준으로 쉼표 또는 마침표를 적용하면 반대의 마침표를 입력 할 수 없습니다.
  • EditText가 어떤 값으로 시작하면 필요에 따라 올바른 구분 기호를 대체합니다.

XML에서 :

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

클래스 변수 :

private boolean isDecimalSeparatorComma = false;

onCreate에서 현재 로케일에 사용 된 구분 기호를 찾으십시오.

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(",");
    }
}

또한 onCreate, 현재 값으로로드하는 경우 이것을 사용하여 업데이트하십시오.

// 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

또한 onCreate, 리스너 추가

editText.addTextChangedListener(editTextWatcher);

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

editTextWatcher

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()
            }
        }
    }
};

doSomething () 예제, 데이터 조작을 위해 표준 기간으로 변환

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

안드로이드에는 숫자 포맷터가 내장되어 있습니다.

EditText소수점 이하와 쉼표를 허용하도록 이것을 추가 할 수 있습니다 . android:inputType="numberDecimal"android:digits="0123456789.,"

그런 다음 사용자가 저장을 클릭하거나 텍스트를 입력 한 후 (리스너 사용) 코드의 어딘가에 있습니다.

// 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

편집하는 동안에 만 쉼표를 점으로 변경하기로 결정했습니다. 내 까다 롭고 상대적으로 간단한 해결 방법은 다음과 같습니다.

    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는 로케일에 따라 쉼표 또는 점을 사용합니다.


0

귀하의 답변이 왜 그렇게 복잡한 지 모르겠습니다. SDK에 버그가 있으면이를 재정의하거나 해결해야합니다.

그 문제를 해결하기 위해 두 번째 방법을 선택했습니다. 문자열을 형식화 Locale.ENGLISH한 다음 EditText빈 문자열로도 넣습니다 . 예:

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

해당 솔루션을 추구하면 결과가 표시된 키보드와 호환됩니다. 그런 다음 부동 및 이중 숫자는 일반적으로 쉼표 대신 점을 사용하여 프로그래밍 언어 방식으로 작동합니다.


0

내 해결책은 다음과 같습니다.

  • 주요 활동에서 :

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

  • xml 파일에서 : android:imeOptions="flagNoFullscreen" android:inputType="numberDecimal"

그리고 editText에서 두 배를 String으로 가져갔습니다.


0

제안 된 수정 프로그램이 Samsung IME (적어도 S6 및 S9) 및 LG에서는 작동하지 않음을 확인할 수 있습니다. 로캘에 관계없이 점을 소수점 구분 기호로 표시합니다. Google의 IME로 전환하면이 문제가 해결되지만 대부분의 개발자에게는 거의 옵션이 아닙니다.

이 키보드는 Oreo에서 수정되지 않았으므로 Samsung 및 / 또는 LG 가해 야 할 수정 사항이므로 고대 핸드셋까지 푸시해야하기 때문입니다.

대신 숫자 키보드 프로젝트를 포크 하고 IME처럼 동작하는 모드를 추가했습니다 : fork . 자세한 내용은 프로젝트 샘플을 참조하십시오. 이것은 나를 위해 잘 작동하고 은행 응용 프로그램에서 볼 수있는 많은 "PIN 항목"위조 IME와 유사합니다.

샘플 앱 스크린 샷


0

8 년이 지났지 만 놀랍습니다.이 문제는 아직 해결되지 않았습니다 ... @Martin이 가장 많이 대답 한 답변으로 여러 구분 기호를 입력 할 수
있기 때문에이 간단한 문제로 어려움을 겪었습니다 . 즉, 사용자는 "12, ,,, 12,1,, 21,2, "
또한 두 번째 문제는 일부 기기에서 쉼표로 숫자 키보드에 도시되지 않는다 (또는 도트 버튼을 누르면 여러 필요)

여기에 언급 된 문제를 해결하고 사용자가 '.'를 입력 할 수있는 해결 방법이 있습니다. 및 ','이지만 EditText에는 현재 로케일에 해당하는 유일한 소수점 구분 기호가 표시됩니다.

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

그리고 텍스트 감시자 :

  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

간단한 솔루션, 맞춤형 컨트롤 만들기. (이것은 Xamarin 안드로이드에서 만들어졌지만 자바로 쉽게 포팅해야합니다)

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

을 사용할 수 inputType="phone"있지만이 경우 여러 ,개 를 처리 하거나 .존재해야하므로 추가 유효성 검사가 필요합니다.


-1

이 솔루션은 여기에 작성된 다른 솔루션보다 덜 복잡하다고 생각합니다.

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

이렇게하면 '.'을 누를 수 있습니다. 소프트 키보드에서는 아무 일도 일어나지 않습니다. 숫자와 쉼표 만 허용됩니다.


4
이 작업을 수행하면 '.'를 사용하는 모든 로케일이 중단됩니다. 대신에.
Nick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.