EditText
ボックスがあり、ユーザーは最大7つの数字と小数点以下2桁を入力できます。 7桁を入力した後、1桁追加することはできませんが、小数点以下2桁まで入力できます。小数点以下2桁に10進数フィルターを使用し、このコードをXMLで使用しています
Android:maxLength="7"
Android:imeOptions="actionDone"
Android:inputType="numberDecimal"
しかし、EditText
はenter
8桁を許可しています。これをどのように解決できますか?
onCreateでお試しください
youreditText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,1)});
これはプログラムの任意の場所
public class DecimalDigitsInputFilter implements InputFilter {
Pattern mPattern;
public DecimalDigitsInputFilter(int digitsBeforeZero,int digitsAfterZero) {
mPattern=Pattern.compile("[0-9]{0," + (digitsBeforeZero-1) + "}+((\\.[0-9]{0," + (digitsAfterZero-1) + "})?)||(\\.)?");
}
@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;
}
}
この入力フィルターを使用して問題を解決できます。 フィルターを設定するには:
mEditText.setFilters(new InputFilter[]{new DigitsInputFilter(maxDigitsBeforeDot, maxDigitsAfterDot, maxValue)});
ドットの前後の桁数を制限したくない場合Integer.MAX_VALUE
を最大値の制限を無効にするに使用する場合は、Double.POSITIVE_INFINITY
を使用します。
このフィルタは、数値または数値とテキストを入力するテキストフィールドに使用できます。
public class DigitsInputFilter implements InputFilter {
private final String DOT = ".";
private int mMaxIntegerDigitsLength;
private int mMaxDigitsAfterLength;
private double mMax;
public DigitsInputFilter(int maxDigitsBeforeDot, int maxDigitsAfterDot, double maxValue) {
mMaxIntegerDigitsLength = maxDigitsBeforeDot;
mMaxDigitsAfterLength = maxDigitsAfterDot;
mMax = maxValue;
}
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String allText = getAllText(source, dest, dstart);
String onlyDigitsText = getOnlyDigitsPart(allText);
if (allText.isEmpty()) {
return null;
} else {
double enteredValue;
try {
enteredValue = Double.parseDouble(onlyDigitsText);
} catch (NumberFormatException e) {
return "";
}
return checkMaxValueRule(enteredValue, onlyDigitsText);
}
}
private CharSequence checkMaxValueRule(double enteredValue, String onlyDigitsText) {
if (enteredValue > mMax) {
return "";
} else {
return handleInputRules(onlyDigitsText);
}
}
private CharSequence handleInputRules(String onlyDigitsText) {
if (isDecimalDigit(onlyDigitsText)) {
return checkRuleForDecimalDigits(onlyDigitsText);
} else {
return checkRuleForIntegerDigits(onlyDigitsText.length());
}
}
private boolean isDecimalDigit(String onlyDigitsText) {
return onlyDigitsText.contains(DOT);
}
private CharSequence checkRuleForDecimalDigits(String onlyDigitsPart) {
String afterDotPart = onlyDigitsPart.substring(onlyDigitsPart.indexOf(DOT), onlyDigitsPart.length() - 1);
if (afterDotPart.length() > mMaxDigitsAfterLength) {
return "";
}
return null;
}
private CharSequence checkRuleForIntegerDigits(int allTextLength) {
if (allTextLength > mMaxIntegerDigitsLength) {
return "";
}
return null;
}
private String getOnlyDigitsPart(String text) {
return text.replaceAll("[^0-9?!\\.]", "");
}
private String getAllText(CharSequence source, Spanned dest, int dstart) {
String allText = "";
if (!dest.toString().isEmpty()) {
if (source.toString().isEmpty()) {
allText = deleteCharAtIndex(dest, dstart);
} else {
allText = new StringBuilder(dest).insert(dstart, source).toString();
}
}
return allText;
}
private String deleteCharAtIndex(Spanned dest, int dstart) {
StringBuilder builder = new StringBuilder(dest);
builder.deleteCharAt(dstart);
return builder.toString();
}
}
お役に立てば幸いです。
edittext.setFilters(new InputFilter[] { new DigitsKeyListener(
Boolean.FALSE, Boolean.TRUE) {
int beforeDecimal = 7, afterDecimal = 2;
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
String etText = edittext.getText().toString();
if (etText.isEmpty()){
return null;
}
String temp = edittext.getText() + source.toString();
if (temp.equals(".")) {
return "0.";
} else if (temp.toString().indexOf(".") == -1) {
// no decimal point placed yet
if (temp.length() > beforeDecimal) {
return "";
}
} else {
int dotPosition ;
int cursorPositon = edittext.getSelectionStart();
if (etText.indexOf(".") == -1) {
Log.i("First time Dot", etText.toString().indexOf(".")+" "+etText);
dotPosition = temp.indexOf(".");
Log.i("dot Positon", cursorPositon+"");
Log.i("dot Positon", etText+"");
Log.i("dot Positon", dotPosition+"");
}else{
dotPosition = etText.indexOf(".");
Log.i("dot Positon", cursorPositon+"");
Log.i("dot Positon", etText+"");
Log.i("dot Positon", dotPosition+"");
}
if(cursorPositon <= dotPosition){
Log.i("cursor position", "in left");
String beforeDot = etText.substring(0, dotPosition);
if(beforeDot.length()<beforeDecimal){
return source;
}else{
if(source.toString().equalsIgnoreCase(".")){
return source;
}else{
return "";
}
}
}else{
Log.i("cursor position", "in right");
temp = temp.substring(temp.indexOf(".") + 1);
if (temp.length() > afterDecimal) {
return "";
}
}
}
return super.filter(source, start, end, dest, dstart, dend);
}
} });
public class DecimalDigitsInputFilter implements InputFilter {
Pattern mPattern;
int digitsBeforeZero;
public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
this.digitsBeforeZero = digitsBeforeZero;
mPattern = Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}+((\\.[0-9]{0," + (digitsAfterZero - 1) + "})?)||(\\.)?");
}
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
Matcher matcher = mPattern.matcher(dest);
if (!matcher.matches()) {
if (dest.toString().contains(".")) {
if (dest.toString().substring(dest.toString().indexOf(".")).length() > 2) {
return "";
}
return null;
} else if (!Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}").matcher(dest).matches()) {
if (!dest.toString().contains(".")) {
if (source.toString().equalsIgnoreCase(".")) {
return null;
}
}
return "";
} else {
return null;
}
}
return null;
}
}
この入力フィルターを使用して問題を解決できます。フィルターを設定するには:4桁と2つの小数点
public class DecimalDigitsInputFilter implements InputFilter {
Pattern mPattern;
public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
mPattern = Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}+((\\.[0-9]{0," + (digitsAfterZero - 1) + "})?)||(\\.)?");
}
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String s = Html.toHtml(dest).replaceAll("\\<.*?>","").replaceAll("\n","");
Matcher matcher = mPattern.matcher(dest);
if (!matcher.matches())
return "";
try {
if(Double.parseDouble(s)<9999.99 && s.contains(".")) {
return null;
}else if ((Double.parseDouble(s)<1000 && !s.contains("."))||source.equals(".")) {
return null;
}else {
return "";
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
editText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(7, 2)});
次のようにAndroid databindingを使用すると、この機能を強化できます。
カスタムバインディングアダプターを定義します。
@BindingAdapter({"digitsBeforeZero", "digitsAfterZero"})
public void bindAmountInputFilter(EditText view, int digitsBeforeZero, int digitsAfterZero) {
view.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(digitsBeforeZero, digitsAfterZero)});
}
EditTextに属性を追加します。
app:digitsBeforeZero="@{7}"
app:digitsAfterZero="@{2}"
edittextの入力フィルターを自動的に設定します
editText.addTextChangedListener(new TextWatcher() {
String firstString;
String beforeInt = "";
String beforeDec = "";
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
txtAmt.setText("");
firstString = charSequence.toString();
String[] rupee = firstString.split("\\.");
if ( rupee.length > 0 )
beforeInt = rupee[0];
if ( rupee.length > 1 )
beforeDec = rupee[1];
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
try {
String amount = charSequence.toString().replaceAll(",","");
if ( txtAmt != null && !amount.isEmpty()){
String[] rupee = amount.split("\\.");
if ( rupee.length == 0 )
return;
String intPart = rupee[0];
int arrayLength = rupee.length;
if ( arrayLength == 2 ){
String decPart = rupee[1];
if ( decPart.length() == 1 )
decPart += "0";
if ( intPart.length() > 6 || decPart.length() > 2 ){
editText.removeTextChangedListener(this);
firstString = beforeInt;
if ( !beforeDec.isEmpty() )
firstString += "."+beforeDec;
editText.setText( firstString );
editText.setSelection( firstString.length());
editText.addTextChangedListener( this );
}
}
}
}catch (Exception e){
//Do nothing
}
}
@Override
public void afterTextChanged(Editable s) {
//Do nothing
}
});
直接的な解決策ではありませんが、TextWatcher
を使用して、IMEからEditTextに移動するすべての文字を制御できます。
SO TextWatcher
の使用方法に関するQ&Aの1つは here
TextWatcher
の詳細は ここ
入力を検証するには、 浮動小数点の精度と一致する正規表現 & パターンマッチャー の助けが必要になる場合があります。