Merge "Bug 5250788: EditText gets slower has the entered text gets longer"
This commit is contained in:
committed by
Android (Google) Code Review
commit
67ed574cdb
@@ -73,10 +73,6 @@ public class WordIterator implements Selection.PositionIterator {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void forceUpdate() {
|
|
||||||
mCurrentDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCharSequence(CharSequence incoming) {
|
public void setCharSequence(CharSequence incoming) {
|
||||||
// When incoming is different object, move listeners to new sequence
|
// When incoming is different object, move listeners to new sequence
|
||||||
// and mark as dirty so we reload contents.
|
// and mark as dirty so we reload contents.
|
||||||
|
|||||||
@@ -7609,9 +7609,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
sendOnTextChanged(buffer, start, before, after);
|
sendOnTextChanged(buffer, start, before, after);
|
||||||
onTextChanged(buffer, start, before, after);
|
onTextChanged(buffer, start, before, after);
|
||||||
|
|
||||||
// The WordIterator text change listener may be called after this one.
|
|
||||||
// Make sure this changed text is rescanned before the iterator is used on it.
|
|
||||||
getWordIterator().forceUpdate();
|
|
||||||
updateSpellCheckSpans(start, start + after);
|
updateSpellCheckSpans(start, start + after);
|
||||||
|
|
||||||
// Hide the controllers if the amount of content changed
|
// Hide the controllers if the amount of content changed
|
||||||
@@ -7745,21 +7742,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
private void updateSpellCheckSpans(int start, int end) {
|
private void updateSpellCheckSpans(int start, int end) {
|
||||||
if (!isTextEditable() || !isSuggestionsEnabled() || !getSpellChecker().isSessionActive())
|
if (!isTextEditable() || !isSuggestionsEnabled() || !getSpellChecker().isSessionActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Editable text = (Editable) mText;
|
Editable text = (Editable) mText;
|
||||||
WordIterator wordIterator = getWordIterator();
|
|
||||||
wordIterator.setCharSequence(text);
|
final int shift = prepareWordIterator(start, end);
|
||||||
|
final int shiftedStart = start - shift;
|
||||||
|
final int shiftedEnd = end - shift;
|
||||||
|
|
||||||
// Move back to the beginning of the current word, if any
|
// Move back to the beginning of the current word, if any
|
||||||
int wordStart = wordIterator.preceding(start);
|
int wordStart = mWordIterator.preceding(shiftedStart);
|
||||||
int wordEnd;
|
int wordEnd;
|
||||||
if (wordStart == BreakIterator.DONE) {
|
if (wordStart == BreakIterator.DONE) {
|
||||||
wordEnd = wordIterator.following(start);
|
wordEnd = mWordIterator.following(shiftedStart);
|
||||||
if (wordEnd != BreakIterator.DONE) {
|
if (wordEnd != BreakIterator.DONE) {
|
||||||
wordStart = wordIterator.getBeginning(wordEnd);
|
wordStart = mWordIterator.getBeginning(wordEnd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wordEnd = wordIterator.getEnd(wordStart);
|
wordEnd = mWordIterator.getEnd(wordStart);
|
||||||
}
|
}
|
||||||
if (wordEnd == BreakIterator.DONE) {
|
if (wordEnd == BreakIterator.DONE) {
|
||||||
return;
|
return;
|
||||||
@@ -7772,22 +7770,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
final int numberOfSpellCheckSpans = spellCheckSpans.length;
|
final int numberOfSpellCheckSpans = spellCheckSpans.length;
|
||||||
|
|
||||||
// Iterate over the newly added text and schedule new SpellCheckSpans
|
// Iterate over the newly added text and schedule new SpellCheckSpans
|
||||||
while (wordStart <= end) {
|
while (wordStart <= shiftedEnd) {
|
||||||
if (wordEnd >= start) {
|
if (wordEnd >= shiftedStart) {
|
||||||
// A new word has been created across the interval boundaries. Remove previous spans
|
// A new word has been created across the interval boundaries. Remove previous spans
|
||||||
if (wordStart < start && wordEnd > start) {
|
if (wordStart < shiftedStart && wordEnd > shiftedStart) {
|
||||||
removeSpansAt(start, spellCheckSpans, text);
|
removeSpansAt(start, spellCheckSpans, text);
|
||||||
removeSpansAt(start, suggestionSpans, text);
|
removeSpansAt(start, suggestionSpans, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wordStart < end && wordEnd > end) {
|
if (wordStart < shiftedEnd && wordEnd > shiftedEnd) {
|
||||||
removeSpansAt(end, spellCheckSpans, text);
|
removeSpansAt(end, spellCheckSpans, text);
|
||||||
removeSpansAt(end, suggestionSpans, text);
|
removeSpansAt(end, suggestionSpans, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not create new boundary spans if they already exist
|
// Do not create new boundary spans if they already exist
|
||||||
boolean createSpellCheckSpan = true;
|
boolean createSpellCheckSpan = true;
|
||||||
if (wordEnd == start) {
|
if (wordEnd == shiftedStart) {
|
||||||
for (int i = 0; i < numberOfSpellCheckSpans; i++) {
|
for (int i = 0; i < numberOfSpellCheckSpans; i++) {
|
||||||
final int spanEnd = text.getSpanEnd(spellCheckSpans[i]);
|
final int spanEnd = text.getSpanEnd(spellCheckSpans[i]);
|
||||||
if (spanEnd == start) {
|
if (spanEnd == start) {
|
||||||
@@ -7797,9 +7795,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wordStart == end) {
|
if (wordStart == shiftedEnd) {
|
||||||
for (int i = 0; i < numberOfSpellCheckSpans; i++) {
|
for (int i = 0; i < numberOfSpellCheckSpans; i++) {
|
||||||
final int spanStart = text.getSpanEnd(spellCheckSpans[i]);
|
final int spanStart = text.getSpanStart(spellCheckSpans[i]);
|
||||||
if (spanStart == end) {
|
if (spanStart == end) {
|
||||||
createSpellCheckSpan = false;
|
createSpellCheckSpan = false;
|
||||||
break;
|
break;
|
||||||
@@ -7808,16 +7806,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (createSpellCheckSpan) {
|
if (createSpellCheckSpan) {
|
||||||
mSpellChecker.addSpellCheckSpan(wordStart, wordEnd);
|
mSpellChecker.addSpellCheckSpan(wordStart + shift, wordEnd + shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate word by word
|
// iterate word by word
|
||||||
wordEnd = wordIterator.following(wordEnd);
|
wordEnd = mWordIterator.following(wordEnd);
|
||||||
if (wordEnd == BreakIterator.DONE) break;
|
if (wordEnd == BreakIterator.DONE) break;
|
||||||
wordStart = wordIterator.getBeginning(wordEnd);
|
wordStart = mWordIterator.getBeginning(wordEnd);
|
||||||
if (wordStart == BreakIterator.DONE) {
|
if (wordStart == BreakIterator.DONE) {
|
||||||
Log.e(LOG_TAG, "Unable to find word beginning from " + wordEnd + "in " + mText);
|
Log.e(LOG_TAG, "No word beginning from " + (wordEnd + shift) + "in " + mText);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8941,26 +8939,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
selectionStart = ((Spanned) mText).getSpanStart(url);
|
selectionStart = ((Spanned) mText).getSpanStart(url);
|
||||||
selectionEnd = ((Spanned) mText).getSpanEnd(url);
|
selectionEnd = ((Spanned) mText).getSpanEnd(url);
|
||||||
} else {
|
} else {
|
||||||
WordIterator wordIterator = getWordIterator();
|
final int shift = prepareWordIterator(minOffset, maxOffset);
|
||||||
// WordIterator handles text changes, this is a no-op if text in unchanged.
|
|
||||||
wordIterator.setCharSequence(mText);
|
|
||||||
|
|
||||||
selectionStart = wordIterator.getBeginning(minOffset);
|
selectionStart = mWordIterator.getBeginning(minOffset - shift);
|
||||||
if (selectionStart == BreakIterator.DONE) return false;
|
if (selectionStart == BreakIterator.DONE) return false;
|
||||||
|
selectionStart += shift;
|
||||||
|
|
||||||
selectionEnd = wordIterator.getEnd(maxOffset);
|
selectionEnd = mWordIterator.getEnd(maxOffset - shift);
|
||||||
if (selectionEnd == BreakIterator.DONE) return false;
|
if (selectionEnd == BreakIterator.DONE) return false;
|
||||||
|
selectionEnd += shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
|
Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WordIterator getWordIterator() {
|
int prepareWordIterator(int start, int end) {
|
||||||
if (mWordIterator == null) {
|
if (mWordIterator == null) {
|
||||||
mWordIterator = new WordIterator();
|
mWordIterator = new WordIterator();
|
||||||
}
|
}
|
||||||
return mWordIterator;
|
|
||||||
|
final int TEXT_WINDOW_WIDTH = 50; // Should be larger than the longest word's length
|
||||||
|
final int windowStart = Math.max(0, start - TEXT_WINDOW_WIDTH);
|
||||||
|
final int windowEnd = Math.min(mText.length(), end + TEXT_WINDOW_WIDTH);
|
||||||
|
mWordIterator.setCharSequence(mText.subSequence(windowStart, windowEnd));
|
||||||
|
|
||||||
|
return windowStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpellChecker getSpellChecker() {
|
private SpellChecker getSpellChecker() {
|
||||||
|
|||||||
Reference in New Issue
Block a user