demand :EditTtext You need to limit the number of characters you enter , What a Chinese character occupies is 2 Characters , One English character occupies 1 Characters . Monitor the number of characters entered in real time , The length of the content of exceeding character prompt exceeds the limit

Realization ideas : adopt EditText Of InputFilter Filter implementation .

1, see InputFilter This class , There is a well implemented static class that limits the length of input text LengthFilter, The source code is as follows :
/** * This filter will constrain edits not to make the length of the text *
greater than the specified length. */ public static class LengthFilter
implements InputFilter { private final int mMax; public LengthFilter(int max) {
mMax = max; } public CharSequence filter(CharSequence source, int start, int
end, Spanned dest, int dstart, int dend) { int keep = mMax - (dest.length() -
(dend - dstart)); if (keep <= 0) { return ""; } else if (keep >= end - start) {
return null; // keep original } else { keep += start; if
(Character.isHighSurrogate(source.charAt(keep - 1))) { --keep; if (keep ==
start) { return ""; } } return source.subSequence(start, keep); } } /** *
@return the maximum length enforced by this input filter */ public int getMax()
{ return mMax; } }
The core code is there
public CharSequence filter(CharSequence source, int start, int end, Spanned
dest, int dstart, int dend)

In the above method source Represents the character to be written ,start Represents the first and last subscript of the input character ,end Represents the end subscript of the input character ,dest Represents a character that already exists in a text box ,dstart Indicates the starting position where the input character will be inserted ,dend Indicates the end position where the input character will be inserted .( Because it's possible that you insert characters that already exist in the text box , Or you can select a few characters to paste , So the starting and ending positions may be different )
// This line calculates the length of the characters you can enter int keep = mMax - (dest.length() - (dend - dstart));
// If the characters that can be entered are less than or equal to 0, You will not be able to enter characters if (keep <= 0) { return "";
// If the length that can be entered is greater than or equal to the length of the character to be entered , It doesn't matter } else if (keep >= end - start) { return null; //
keep original } else { // If the input character is in the middle of the input character length // Set the subscript of the last character of the input character first keep += start;
// If the last character is in (\uD800-\uDBFF) between if (Character.isHighSurrogate(source.charAt(keep -
1))) { --keep; // Subscript minus 1 If it is equal to the start position, the input is not allowed if (keep == start) { return ""; } } return
source.subSequence(start, keep); }
The above one can set the maximum number of characters to be entered , But he calculated all the characters as one character in one length . So we have to realize it 1 Chinese characters 2 Characters ,1 If one character occupies one character, it is necessary to determine the type of character

2, Achieve demand effect , The specific logic is as follows
override fun filter(source: CharSequence? start: Int, end: Int, dest:
Spanned? dstart: Int, dend: Int): CharSequence? { // Limit the number of characters var dindex = 0 var
count = 0 var currentLength = 0.0 // Calculates the length of characters that already exist in the text box while (count <= maxLength
&& dindex < dest?.length!!) { val c = dest[dindex++]
// Here is the basis ACSII Value to determine the Chinese and English , Among them, Chinese and Chinese symbols ACSII Values are greater than 128 Of if (c.toInt() <= 128) { count +=
1 if(count<=maxLength) { currentLength += 0.5 } } else { count += 2
if(count<=maxLength) { currentLength++ } } } if (count > maxLength) {
UtilDialog.showToast(context.getString(R.string.core_content_byound_max),
Gravity.CENTER) callback?.invoke(Math.ceil(currentLength).toInt()) return
dest?.subSequence(0, dindex - 1) } // Calculate the character length of the input var sindex = 0 while (count <=
maxLength && sindex < source?.length!!) { val c = source[sindex++] if(c.toInt()
<= 128){ count+=1 if(count<=maxLength) { currentLength += 0.5 } }else{ count+=2
if(count<=maxLength) { currentLength++ } } } if (count > maxLength) {
UtilDialog.showToast(context.getString(R.string.core_content_byound_max),
Gravity.CENTER) sindex-- } // Calculates the length of deleted characters if (start == 0 && end == 0) { val
delete = dest?.subSequence(dstart, dend) ?: "" for (deleteIndext in 0 until
delete.length) { val c = delete[deleteIndext] if (c.toInt() <= 128) {
currentLength -= 0.5 } else { currentLength-- } } }
callback?.invoke(Math.ceil(currentLength).toInt()) return
source?.subSequence(0, sindex) }
 

Technology