그만큼 inputType
numberDecimal
에서이 EditText
점을 사용합니다 '.' 소수점 구분 기호로. 유럽에서는 쉼표 ','를 사용하는 것이 일반적입니다. 내 로캘이 독일어로 설정되어 있어도 소수점 구분 기호는 여전히 '.'입니다.
쉼표를 소수점 구분 기호로 얻는 방법이 있습니까?
그만큼 inputType
numberDecimal
에서이 EditText
점을 사용합니다 '.' 소수점 구분 기호로. 유럽에서는 쉼표 ','를 사용하는 것이 일반적입니다. 내 로캘이 독일어로 설정되어 있어도 소수점 구분 기호는 여전히 '.'입니다.
쉼표를 소수점 구분 기호로 얻는 방법이 있습니까?
답변:
해결 방법은 (구글이이 버그를 해결 될 때까지)을 사용하는 것입니다 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
}
여기에 제공되는 '숫자'솔루션의 변형 :
char separator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));
로캘 구분 기호를 고려합니다.
,
있습니다. 예 : 삼성 키보드 (KitKat)
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;
}
});
프로그래밍 방식으로 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;
}
}
}
다른 로케일에 대해 다음을 사용할 수 있습니다
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));
}
});
}
다음 해결 방법을 사용하여 쉼표를 유효한 입력으로 포함 할 수도 있습니다.
XML을 통해 :
<EditText
android:inputType="number"
android:digits="0123456789.," />
프로그래밍 방식으로 :
EditText input = new EditText(THE_CONTEXT);
input.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));
이런 식으로 안드로이드 시스템은 숫자의 키보드를 보여주고 쉼표 입력을 허용합니다. 이것이 질문에 대답하기를 바랍니다 :)
다음을 수행 할 수 있습니다.
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;
}
}
이 문제에 대한 가장 좋은 방법은 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)});
입력 사용을 현지화하려면 :
char sep = DecimalFormatSymbols.getInstance().getDecimalSeparator();
다음을 추가하십시오.
textEdit.setKeyListener(DigitsKeyListener.getInstance("0123456789" + sep));
","를 "."로 바꾸는 것을 잊지 마십시오. Float 또는 Double은 오류없이 구문 분석 할 수 있습니다.
여기에있는 다른 모든 게시물에는 큰 구멍이 있었으므로 다음과 같은 해결책이 있습니다.
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");
}
}
안드로이드에는 숫자 포맷터가 내장되어 있습니다.
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;
}
편집하는 동안에 만 쉼표를 점으로 변경하기로 결정했습니다. 내 까다 롭고 상대적으로 간단한 해결 방법은 다음과 같습니다.
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는 로케일에 따라 쉼표 또는 점을 사용합니다.
귀하의 답변이 왜 그렇게 복잡한 지 모르겠습니다. SDK에 버그가 있으면이를 재정의하거나 해결해야합니다.
그 문제를 해결하기 위해 두 번째 방법을 선택했습니다. 문자열을 형식화 Locale.ENGLISH
한 다음 EditText
빈 문자열로도 넣습니다 . 예:
String.format(Locale.ENGLISH,"%.6f", yourFloatNumber);
해당 솔루션을 추구하면 결과가 표시된 키보드와 호환됩니다. 그런 다음 부동 및 이중 숫자는 일반적으로 쉼표 대신 점을 사용하여 프로그래밍 언어 방식으로 작동합니다.
내 해결책은 다음과 같습니다.
주요 활동에서 :
char separator =DecimalFormatSymbols.getInstance().getDecimalSeparator();
textViewPitchDeadZone.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));
xml 파일에서 :
android:imeOptions="flagNoFullscreen"
android:inputType="numberDecimal"
그리고 editText에서 두 배를 String으로 가져갔습니다.
제안 된 수정 프로그램이 Samsung IME (적어도 S6 및 S9) 및 LG에서는 작동하지 않음을 확인할 수 있습니다. 로캘에 관계없이 점을 소수점 구분 기호로 표시합니다. Google의 IME로 전환하면이 문제가 해결되지만 대부분의 개발자에게는 거의 옵션이 아닙니다.
이 키보드는 Oreo에서 수정되지 않았으므로 Samsung 및 / 또는 LG 가해 야 할 수정 사항이므로 고대 핸드셋까지 푸시해야하기 때문입니다.
대신 숫자 키보드 프로젝트를 포크 하고 IME처럼 동작하는 모드를 추가했습니다 : fork . 자세한 내용은 프로젝트 샘플을 참조하십시오. 이것은 나를 위해 잘 작동하고 은행 응용 프로그램에서 볼 수있는 많은 "PIN 항목"위조 IME와 유사합니다.
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(""))
}
}
}
간단한 솔루션, 맞춤형 컨트롤 만들기. (이것은 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);
}
}
}
}
을 사용할 수 inputType="phone"
있지만이 경우 여러 ,
개 를 처리 하거나 .
존재해야하므로 추가 유효성 검사가 필요합니다.
이 솔루션은 여기에 작성된 다른 솔루션보다 덜 복잡하다고 생각합니다.
<EditText
android:inputType="numberDecimal"
android:digits="0123456789," />
이렇게하면 '.'을 누를 수 있습니다. 소프트 키보드에서는 아무 일도 일어나지 않습니다. 숫자와 쉼표 만 허용됩니다.