You can use String. format("%. 2f", d) , your double will be rounded automatically.
You can use android:inputType="number" in the XML file. You can specify other values such as numberDecimal as well. Also, you might additionally want to use android:singleLine="true" for a single line Edittext .
More elegant way would be using a regular expression ( regex ) as follows:
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;
}
}
To use it do:
editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});
Simpler solution without using regex:
import android.text.InputFilter;
import android.text.Spanned;
/**
* Input filter that limits the number of decimal digits that are allowed to be
* entered.
*/
public class DecimalDigitsInputFilter implements InputFilter {
private final int decimalDigits;
/**
* Constructor.
*
* @param decimalDigits maximum decimal digits
*/
public DecimalDigitsInputFilter(int decimalDigits) {
this.decimalDigits = decimalDigits;
}
@Override
public CharSequence filter(CharSequence source,
int start,
int end,
Spanned dest,
int dstart,
int dend) {
int dotPos = -1;
int len = dest.length();
for (int i = 0; i < len; i++) {
char c = dest.charAt(i);
if (c == '.' || c == ',') {
dotPos = i;
break;
}
}
if (dotPos >= 0) {
// protects against many dots
if (source.equals(".") || source.equals(","))
{
return "";
}
// if the text is entered before the dot
if (dend <= dotPos) {
return null;
}
if (len - dotPos > decimalDigits) {
return "";
}
}
return null;
}
}
To use:
editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(2)});
This implementation of InputFilter
solves the problem.
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.DigitsKeyListener;
public class MoneyValueFilter extends DigitsKeyListener {
public MoneyValueFilter() {
super(false, true);
}
private int digits = 2;
public void setDigits(int d) {
digits = d;
}
@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 changed, replace the source
if (out != null) {
source = out;
start = 0;
end = out.length();
}
int len = end - start;
// if deleting, source is empty
// and deleting can't break anything
if (len == 0) {
return source;
}
int dlen = dest.length();
// Find the position of the decimal .
for (int i = 0; i < dstart; i++) {
if (dest.charAt(i) == '.') {
// being here means, that a number has
// been inserted after the dot
// check if the amount of digits is right
return (dlen-(i+1) + len > digits) ?
"" :
new SpannableStringBuilder(source, start, end);
}
}
for (int i = start; i < end; ++i) {
if (source.charAt(i) == '.') {
// being here means, dot has been inserted
// check if the amount of digits is right
if ((dlen-dend) + (end-(i + 1)) > digits)
return "";
else
break; // return new SpannableStringBuilder(source, start, end);
}
}
// if the dot is after the inserted part,
// nothing can break
return new SpannableStringBuilder(source, start, end);
}
}
Here is a sample InputFilter which only allows max 4 digits before the decimal point and max 1 digit after that.
Values that edittext allows: 555.2, 555, .2
Values that edittext blocks: 55555.2, 055.2, 555.42
InputFilter filter = new InputFilter() {
final int maxDigitsBeforeDecimalPoint=4;
final int maxDigitsAfterDecimalPoint=1;
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
StringBuilder builder = new StringBuilder(dest);
builder.replace(dstart, dend, source
.subSequence(start, end).toString());
if (!builder.toString().matches(
"(([1-9]{1})([0-9]{0,"+(maxDigitsBeforeDecimalPoint-1)+"})?)?(\\.[0-9]{0,"+maxDigitsAfterDecimalPoint+"})?"
)) {
if(source.length()==0)
return dest.subSequence(dstart, dend);
return "";
}
return null;
}
};
mEdittext.setFilters(new InputFilter[] { filter });
I made some fixes for @Pinhassi solution. It handles some cases:
1.you can move cursor anywhere
2.minus sign handling
3.digitsbefore = 2 and digitsafter = 4 and you enter 12.4545. Then if you want to remove ".", it will not allow.
public class DecimalDigitsInputFilter implements InputFilter {
private int mDigitsBeforeZero;
private int mDigitsAfterZero;
private Pattern mPattern;
private static final int DIGITS_BEFORE_ZERO_DEFAULT = 100;
private static final int DIGITS_AFTER_ZERO_DEFAULT = 100;
public DecimalDigitsInputFilter(Integer digitsBeforeZero, Integer digitsAfterZero) {
this.mDigitsBeforeZero = (digitsBeforeZero != null ? digitsBeforeZero : DIGITS_BEFORE_ZERO_DEFAULT);
this.mDigitsAfterZero = (digitsAfterZero != null ? digitsAfterZero : DIGITS_AFTER_ZERO_DEFAULT);
mPattern = Pattern.compile("-?[0-9]{0," + (mDigitsBeforeZero) + "}+((\\.[0-9]{0," + (mDigitsAfterZero)
+ "})?)||(\\.)?");
}
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String replacement = source.subSequence(start, end).toString();
String newVal = dest.subSequence(0, dstart).toString() + replacement
+ dest.subSequence(dend, dest.length()).toString();
Matcher matcher = mPattern.matcher(newVal);
if (matcher.matches())
return null;
if (TextUtils.isEmpty(source))
return dest.subSequence(dstart, dend);
else
return "";
}
}
I don't like the other solution and I created my own. With this solution you can't enter more than MAX_BEFORE_POINT digit before the point and the decimals can't be more than MAX_DECIMAL.
You just can't type the digit in excess, no other effects! In additional if you write "." it types "0."
Set the EditText in the layout to:
android:inputType="numberDecimal"
Add the Listener in your onCreate. If you want modify the number of digits before and after the point edit the call to PerfectDecimal(str, NUMBER_BEFORE_POINT, NUMBER_DECIMALS), here is set to 3 and 2
EditText targetEditText = (EditText)findViewById(R.id.targetEditTextLayoutId);
targetEditText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
public void afterTextChanged(Editable arg0) {
String str = targetEditText.getText().toString();
if (str.isEmpty()) return;
String str2 = PerfectDecimal(str, 3, 2);
if (!str2.equals(str)) {
targetEditText.setText(str2);
targetEditText.setSelection(str2.length());
}
}
});
Include this Funcion:
public String PerfectDecimal(String str, int MAX_BEFORE_POINT, int MAX_DECIMAL){
if(str.charAt(0) == '.') str = "0"+str;
int max = str.length();
String rFinal = "";
boolean after = false;
int i = 0, up = 0, decimal = 0; char t;
while(i < max){
t = str.charAt(i);
if(t != '.' && after == false){
up++;
if(up > MAX_BEFORE_POINT) return rFinal;
}else if(t == '.'){
after = true;
}else{
decimal++;
if(decimal > MAX_DECIMAL)
return rFinal;
}
rFinal = rFinal + t;
i++;
}return rFinal;
}
And it's done!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With