EditText에서 numberDecimal inputType이있는 10 진 구분 기호 쉼표 ( ',')
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));
로캘 구분 기호를 고려합니다.
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;
}
});
이것은 Android SDK 의 알려진 버그 입니다. 유일한 해결 방법은 고유 한 소프트 키보드를 만드는 것입니다. 여기서 구현 예제를 찾을 수 있습니다 .
프로그래밍 방식으로 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;
}
}
}
다음 해결 방법을 사용하여 쉼표를 유효한 입력으로 포함 할 수도 있습니다.
XML을 통해 :
<EditText
android:inputType="number"
android:digits="0123456789.," />
프로그래밍 방식으로 :
EditText input = new EditText(THE_CONTEXT);
input.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));
이런 식으로 안드로이드 시스템은 숫자의 키보드를 보여주고 쉼표 입력을 허용합니다. 이것이 질문에 대답하기를 바랍니다 :)
모노 (Droid) 솔루션의 경우 :
decimal decimalValue = decimal.Parse(input.Text.Replace(",", ".") , CultureInfo.InvariantCulture);
다른 로케일에 대해 다음을 사용할 수 있습니다
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));
}
});
}
다음을 수행 할 수 있습니다.
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은 오류없이 구문 분석 할 수 있습니다.
안드로이드에는 숫자 포맷터가 내장되어 있습니다.
당신은 당신이를 추가 할 수 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 entry"가짜 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);
}
}
}
}
여기에있는 다른 모든 게시물에는 큰 구멍이 있었으므로 다음과 같은 해결책이 있습니다.
- 지역을 기준으로 쉼표 또는 마침표를 적용하면 반대의 마침표를 입력 할 수 없습니다.
- 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");
}
}
이 솔루션은 여기에 작성된 다른 솔루션보다 덜 복잡하다고 생각합니다.
<EditText
android:inputType="numberDecimal"
android:digits="0123456789," />
이렇게하면 '.'을 누를 수 있습니다. 소프트 키보드에서는 아무 일도 일어나지 않습니다. 숫자와 쉼표 만 허용됩니다.
'programing tip' 카테고리의 다른 글
8 비트 정수에서 8 비트보다 큰 값을 얻으려면 어떻게해야합니까? (0) | 2020.07.17 |
---|---|
Bitbucket에서 두 개정판을 비교하는 방법은 무엇입니까? (0) | 2020.07.17 |
Java 제네릭 클래스를 만들 때 꺾쇠 괄호로 묶은 의미는 무엇입니까? (0) | 2020.07.17 |
LINQ를 사용하여 시퀀스에서 마지막 요소를 제외한 모든 요소를 가져 오는 방법은 무엇입니까? (0) | 2020.07.17 |
CSS에서 display : inline-block vs float : left 사용의 장점 (0) | 2020.07.17 |