Apply max char length when setSingleLine is called.

Bug: 145128646
Test: atest android.widget.cts.EditTextTest
Change-Id: I1f2fd6c97c5cdeb7be5017d4c6aeb19fd269e939
This commit is contained in:
Seigo Nonaka
2020-06-12 19:10:40 -07:00
parent ac34fffda5
commit 459f35ac86

View File

@@ -398,6 +398,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Maximum text length for single line input. // Maximum text length for single line input.
private static final int MAX_LENGTH_FOR_SINGLE_LINE_EDIT_TEXT = 5000; private static final int MAX_LENGTH_FOR_SINGLE_LINE_EDIT_TEXT = 5000;
private InputFilter.LengthFilter mSingleLineLengthFilter = null;
private static final RectF TEMP_RECTF = new RectF(); private static final RectF TEMP_RECTF = new RectF();
@@ -1602,7 +1603,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Same as setSingleLine(), but make sure the transformation method and the maximum number // Same as setSingleLine(), but make sure the transformation method and the maximum number
// of lines of height are unchanged for multi-line TextViews. // of lines of height are unchanged for multi-line TextViews.
setInputTypeSingleLine(singleLine); setInputTypeSingleLine(singleLine);
applySingleLine(singleLine, singleLine, singleLine); applySingleLine(singleLine, singleLine, singleLine,
// Does not apply automated max length filter since length filter will be resolved
// later in this function.
false
);
if (singleLine && getKeyListener() == null && ellipsize == ELLIPSIZE_NOT_SET) { if (singleLine && getKeyListener() == null && ellipsize == ELLIPSIZE_NOT_SET) {
ellipsize = ELLIPSIZE_END; ellipsize = ELLIPSIZE_END;
@@ -1649,10 +1654,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// For addressing b/145128646 // For addressing b/145128646
// For the performance reason, we limit characters for single line text field. // For the performance reason, we limit characters for single line text field.
if (bufferType == BufferType.EDITABLE && singleLine && maxlength == -1) { if (bufferType == BufferType.EDITABLE && singleLine && maxlength == -1) {
maxlength = MAX_LENGTH_FOR_SINGLE_LINE_EDIT_TEXT; mSingleLineLengthFilter = new InputFilter.LengthFilter(
MAX_LENGTH_FOR_SINGLE_LINE_EDIT_TEXT);
} }
if (maxlength >= 0) { if (mSingleLineLengthFilter != null) {
setFilters(new InputFilter[] { mSingleLineLengthFilter });
} else if (maxlength >= 0) {
setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) }); setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });
} else { } else {
setFilters(NO_FILTERS); setFilters(NO_FILTERS);
@@ -6610,7 +6618,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mSingleLine != singleLine || forceUpdate) { if (mSingleLine != singleLine || forceUpdate) {
// Change single line mode, but only change the transformation if // Change single line mode, but only change the transformation if
// we are not in password mode. // we are not in password mode.
applySingleLine(singleLine, !isPassword, true); applySingleLine(singleLine, !isPassword, true, true);
} }
if (!isSuggestionsEnabled()) { if (!isSuggestionsEnabled()) {
@@ -10254,6 +10262,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* Note that the default conditions are not necessarily those that were in effect prior this * Note that the default conditions are not necessarily those that were in effect prior this
* method, and you may want to reset these properties to your custom values. * method, and you may want to reset these properties to your custom values.
* *
* Note that due to performance reasons, by setting single line for the EditText, the maximum
* text length is set to 5000 if no other character limitation are applied.
*
* @attr ref android.R.styleable#TextView_singleLine * @attr ref android.R.styleable#TextView_singleLine
*/ */
@android.view.RemotableViewMethod @android.view.RemotableViewMethod
@@ -10261,7 +10272,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Could be used, but may break backward compatibility. // Could be used, but may break backward compatibility.
// if (mSingleLine == singleLine) return; // if (mSingleLine == singleLine) return;
setInputTypeSingleLine(singleLine); setInputTypeSingleLine(singleLine);
applySingleLine(singleLine, true, true); applySingleLine(singleLine, true, true, true);
} }
/** /**
@@ -10281,14 +10292,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} }
private void applySingleLine(boolean singleLine, boolean applyTransformation, private void applySingleLine(boolean singleLine, boolean applyTransformation,
boolean changeMaxLines) { boolean changeMaxLines, boolean changeMaxLength) {
mSingleLine = singleLine; mSingleLine = singleLine;
if (singleLine) { if (singleLine) {
setLines(1); setLines(1);
setHorizontallyScrolling(true); setHorizontallyScrolling(true);
if (applyTransformation) { if (applyTransformation) {
setTransformationMethod(SingleLineTransformationMethod.getInstance()); setTransformationMethod(SingleLineTransformationMethod.getInstance());
} }
if (!changeMaxLength) return;
// Single line length filter is only applicable editable text.
if (mBufferType != BufferType.EDITABLE) return;
final InputFilter[] prevFilters = getFilters();
for (InputFilter filter: getFilters()) {
// We don't add LengthFilter if already there.
if (filter instanceof InputFilter.LengthFilter) return;
}
if (mSingleLineLengthFilter == null) {
mSingleLineLengthFilter = new InputFilter.LengthFilter(
MAX_LENGTH_FOR_SINGLE_LINE_EDIT_TEXT);
}
final InputFilter[] newFilters = new InputFilter[prevFilters.length + 1];
System.arraycopy(prevFilters, 0, newFilters, 0, prevFilters.length);
newFilters[prevFilters.length] = mSingleLineLengthFilter;
setFilters(newFilters);
// Since filter doesn't apply to existing text, trigger filter by setting text.
setText(getText());
} else { } else {
if (changeMaxLines) { if (changeMaxLines) {
setMaxLines(Integer.MAX_VALUE); setMaxLines(Integer.MAX_VALUE);
@@ -10297,6 +10334,47 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (applyTransformation) { if (applyTransformation) {
setTransformationMethod(null); setTransformationMethod(null);
} }
if (!changeMaxLength) return;
// Single line length filter is only applicable editable text.
if (mBufferType != BufferType.EDITABLE) return;
final InputFilter[] prevFilters = getFilters();
if (prevFilters.length == 0) return;
// Short Circuit: if mSingleLineLengthFilter is not allocated, nobody sets automated
// single line char limit filter.
if (mSingleLineLengthFilter == null) return;
// If we need to remove mSingleLineLengthFilter, we need to allocate another array.
// Since filter list is expected to be small and want to avoid unnecessary array
// allocation, check if there is mSingleLengthFilter first.
int targetIndex = -1;
for (int i = 0; i < prevFilters.length; ++i) {
if (prevFilters[i] == mSingleLineLengthFilter) {
targetIndex = i;
break;
}
}
if (targetIndex == -1) return; // not found. Do nothing.
if (prevFilters.length == 1) {
setFilters(NO_FILTERS);
return;
}
// Create new array which doesn't include mSingleLengthFilter.
final InputFilter[] newFilters = new InputFilter[prevFilters.length - 1];
System.arraycopy(prevFilters, 0, newFilters, 0, targetIndex);
System.arraycopy(
prevFilters,
targetIndex + 1,
newFilters,
targetIndex,
prevFilters.length - targetIndex - 1);
setFilters(newFilters);
mSingleLineLengthFilter = null;
} }
} }