Used to may be the best XXX, may be the best XXXX, today I also use this title, ha ha. Don’t spray me. Of course I brag. There’s a lot of good ways to do that.
This article is mainly used to explain the use of InputFilter.
The general amount of input requirements are more, we here with the amount of input box as an example. The same applies to other similar requirements for text, upper and lower case letters.
One day product manager A came to me with A kitchen knife and said:
First encounter
A: Small B, the amount of money input box of this interface is at most two decimal points, that is, at most to points, and this place of that interface, fill in the amount is also accurate to points.
Yes, I’ll get it done.
1. Control of decimal places:
Because there are so many interfaces to use, we’ve got a class that we’re going to control, and we know that we’re going to control the EditText and control its input, which is essentially filtering it, so we’re going to have our class implement the InputFilter interface.
public class PointLengthFilter implements InputFilter {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
returnnull; }}Copy the code
We must implement the filter method. We must implement the filter method. We must implement the filter method.
field | type | content |
---|---|---|
source | CharSequence | Is the string to be entered |
start | int | Start of source, where start is 0 |
end | int | End of source, because start is 0, end can also be understood as the source length |
dest | Spanned | The original contents of the input box |
dstart | int | The starting position to replace or add, where the cursor is |
dend | int | The terminating beginning position to replace or add, or the position in dest of the last character of the selected string, if changed to select a string |
For example, if we type 12345 on the keyboard, we can see the corresponding value:
source:1,start:0,end:1,dest:,dstart:0,dend:0
source:2,start:0,end:1,dest:1,dstart:1,dend:1
source:3,start:0,end:1,dest:12,dstart:2,dend:2
source:4,start:0,end:1,dest:123,dstart:3,dend:3
source:5,start:0,end:1,dest:1234,dstart:4,dend:4Copy the code
You might notice that start is always 0, end is always 1, because we’re typing it in sequence, so if you copy three characters, and you paste and copy them into your EditText, then instead of 0 and 1, it’s 0,3.
So for this decimal point requirement, let’s start with the first version of Filter.
public class PointLengthFilter implements InputFilter { private static final int DECIMAL_DIGITS = 2; @override public CharSequence filter(CharSequence filter)source, int start, int end, Spanned dest, int dstart, int dend)if ("".equals(source.toString())) {
returnnull; String dValue = dest.toString(); [] splitArray = dvalue.split ()"\ \.");
if(splitarray. length > 1) {String dotValue = splitArray[1]; // If the number of digits behind the decimal point is greater than or equal to 2, return the value"";
if (dotValue.length() >= DECIMAL_DIGITS) {
return ""; }}returnnull; }}Copy the code
Then set it in our Activity:
EditText editText = (EditText) findViewById(R.id.et_money);
editText.setFilters(new InputFilter[]{new PointInputFilter()});Copy the code
PS: You can separate the filter criteria into several files, because the InputFilter array is passed in.
Like this. We finally have digit control behind the decimal point.
As shown in the figure below, we enter 12345.67 and then enter other characters. By default, an empty string “” is returned in filter, so nothing else is entered.
Second encounter:
Product manager A stormed over with A kitchen knife.
A: Do you know there is something wrong with your input? Can’t you even test it yourself?
Humble me: impossible, I tested, the number behind the decimal point of the number of digits will not exceed 2 ah.
A: It’s true that the number of digits is no more than 2, but try changing the number before the decimal point.
I took the phone to try, such as the above we have entered 12345.67, this time I want to add a number in front of the decimal point, or the front 12345 I deleted a few, and then input other numbers are not good. Because the number of digits after the decimal point is always 2, when we modify the content before the decimal point, we will always trigger:
String[] splitArray = dValue.split("\ \.");
if(splitarray. length > 1) {String dotValue = splitArray[1]; // If the number of digits behind the decimal point is greater than or equal to 2, return the value"";
if (dotValue.length() >= DECIMAL_DIGITS) {
return ""; }}Copy the code
So it keeps returning an empty string, so you can’t change the number before the decimal point.
2. Change the number before the decimal point while controlling the number of decimal points:
We just need to change the logic that controls the decimal point:
String dValue = dest.toString();
String[] splitArray = dValue.split("\ \.");
if(splitArray.length > 1) { String dotValue = splitArray[1]; // Get the decimal point ". Int dotIndex = dvalue.indexof ("."); / added a conditional judgment: the input cursor is after the decimal pointif (dotValue.length() >= DECIMAL_DIGITS && dstart > dotIndex) {
return ""; }}Copy the code
I tried it. As expected, the number in front of the decimal point can be added or deleted at will. Ha ha. I submitted it again to my satisfaction.
Third clash:
The product manager came back this time with a machete.
A: You can input A lot of numbers in front of the decimal point of the input amount, I have considered the requirements of the decimal point in front of the maximum input 6, the total maximum input value is 999999.99 yuan. That means no more than a million dollars. Make sure it’s done by the end of the day.
A little angry me: ok. Your satisfaction is guaranteed.
3. Limit the number of digits before the decimal point:
In fact, we also know that it is not difficult, as long as the number of digits in front of the decimal point increase control on the line:
public class PointInputFilter1 implements InputFilter { private static final int DECIMAL_DIGITS = 2; Private static final int INTEGER_DIGITS = 5; Private static final int TOTAL_DIGITS = 5; Private int currentLimitDigits = INTEGER_DIGITS; @override public CharSequence filter(CharSequence filter)source, int start, int end, Spanned dest, int dstart, int dend)if ("".equals(source.toString())) {
return null;
}
String dValue = dest.toString();
String[] splitArray = dValue.split("\ \.");
switch (splitArray.length) {
caseIf there is a decimal point, change the control digit to TOTAL_DIGITS(as long as it is greater than the integer digit +1).if (dValue.indexOf(".") != -1) {
currentLimitDigits = TOTAL_DIGITS;
} elseCurrentLimitDigits = INTEGER_DIGITS; } /** if we input 999999 directly, we can not press any other number, otherwise it would be more than a million, but this time if we input a decimal point, we can display the decimal point in the input box. And at this point, the current number limit has been increased, so you can enter other numbers, and then jump to the bottomcase2. * * /if(splitArray[0].length() >= currentLimitDigits && !".".equals(source.toString())){
return "";
}
break;
case 2:
String integerValue = splitArray[0];
String dotValue = splitArray[1];
int dotIndex = dValue.indexOf(".");
if (integerValue.length() >= INTEGER_DIGITS && dstart <= dotIndex) {
return "";
}
if (dotValue.length() >= DECIMAL_DIGITS && dstart > dotIndex) {
return "";
}
break;
default:
break;
}
returnnull; }}Copy the code
Well, now we’re ready to meet. Then smugly released the results of a version, happy to wait for the end of the day.
The fourth clash:
The product manager came up again with the cannon,
A: There is something wrong with your input. You see, I have entered millions.
Me: impossible ah, I tested ah, I show you, here. There’s no way you can lose.
A: I didn’t type it on the keyboard. I just copied multiple digits somewhere else and pasted them in.
I:…
A: I don’t care. You’re not going home until you finish.
I secretly said: MMP
4. Process input by pasting and copying
Here we can handle it in two ways:
- Just don’t let multiple digits paste in at all.
- For a number of numbers assigned to paste to handle.
<1> Do not copy and paste multiple digits:
This is very simple. If the customer copied a number and pasted it in, it would be the same as typing with a keyboard, so there’s no special processing required. All we care about is let’s say it’s 999.99, he just pasted 99999 in front of it. It becomes 99999999.99, which is out of our range. We can directly disable the pasting and copying of multiple digits, the code is very simple:
// Add an extra judgment at the front, which returns an empty string if the input character is multi-digit. // Because through the keyboard input we are all one bit input, and the multi-bit case is usually copied and pasted in.if(source.length() > 1){
return "";
}Copy the code
<2> Handle the input of the paste copy mode:
Let’s assume these scenarios:
(1) The content in the input box is an integer, such as 1234, and then we copy the integer 9999 into it, which should be 123499. (2) The content in the input box is an integer, such as 1234, and then we copy the integer 999.999 into it, which should be 123499.99. (3) The content in the input box is a decimal, such as 1234.1, and then we copy the integer 999 into it. If the copy is in front of the decimal point, it should be 123499.1. If the copy is behind the decimal point, it should be 1234.1. (4) The content in the input box is a decimal, such as 1234.1, and then we copied it into a decimal, such as 9.9, we pasted it in front of the decimal point, so it changed to 123499.1. Because there is only one decimal point in the input box by default, we copied 9.9 into the integer part as 99. If you add it to the decimal point it becomes 1234.19. (5) Input box is empty content, we input 12345678.87654321; Beyond the decimal point, beyond the decimal point, take the valid part and change it to 123456.87.
PS: Each person may have different requirements in specific business, mainly according to the actual business. In my case, when the pasted number is too large, I cut the number of digits that can be put down. You can also find that the pasted number exceeds the limit after adding it. Returns an empty string.
Attach the final code:
PointInputFilter. Java:
public class PointInputFilter implements InputFilter { private static final int DECIMAL_DIGITS = 2; Private static final int INTEGER_DIGITS = 5; Private static final int TOTAL_DIGITS = 5; Private int currentLimitDigits = INTEGER_DIGITS; @Override public CharSequence filter(CharSequencesource, int start, int end, Spanned dest, int dstart, int dend)if ("".equals(source.toString())) {
returnnull; } /* If you want to disallow copying and pasting multiple numbers directly, do this directly.if(source.length() > 1){
return "";
}*/
String dValue = dest.toString();
String[] splitArray = dValue.split("\ \.");
switch (splitArray.length) {
case 1:
if (dValue.indexOf(".") != -1) {
currentLimitDigits = TOTAL_DIGITS;
} else {
currentLimitDigits = INTEGER_DIGITS;
}
if (source.length() > 1) {
String sValue = source.toString();
String[] subSplitArray = sValue.split("\ \.");
switch (subSplitArray.length) {
case 1:
if (source.length() + dest.length() > currentLimitDigits) {
return source.subSequence(0, currentLimitDigits - dest.length());
}
break;
case 2:
String content = "";
if (dstart == dest.length()) {
if (subSplitArray[0].length() + dest.length() > INTEGER_DIGITS) {
content += subSplitArray[0].subSequence(0, INTEGER_DIGITS - dest.length());
} else {
content += subSplitArray[0];
}
if (subSplitArray[1].length() > DECIMAL_DIGITS) {
content += "."+ subSplitArray[1].substring(0, DECIMAL_DIGITS);
} else {
content += "."+ subSplitArray[1];
}
return content;
} else {
if (subSplitArray[0].length() + dest.length() > INTEGER_DIGITS) {
content += subSplitArray[0].subSequence(0, INTEGER_DIGITS - dest.length());
} else{ content += subSplitArray[0]; }}return content;
default:
break; }}if (splitArray[0].length() >= currentLimitDigits && !".".equals(source.toString())) {
return "";
}
break;
case 2:
String integerValue = splitArray[0];
String dotValue = splitArray[1];
int dotIndex = dValue.indexOf(".");
if (dstart <= dotIndex) {
if (integerValue.length() >= INTEGER_DIGITS) {
return "";
} else if (source.length() + integerValue.length() >= INTEGER_DIGITS) {
return source.subSequence(0, INTEGER_DIGITS - integerValue.length()); }}else {
if (dotValue.length() >= DECIMAL_DIGITS) {
return "";
} else if (source.length() + dotValue.length() >= DECIMAL_DIGITS) {
returnsource.subSequence(0, DECIMAL_DIGITS - dotValue.length()); }}break;
default:
break;
}
returnnull; }}Copy the code
Conclusion:
To complete. I can finally leave work in peace. Haha…