diff options
| author | 2015-12-21 18:01:40 +0900 | |
|---|---|---|
| committer | 2015-12-21 18:01:40 +0900 | |
| commit | 1cd8aac4ea660e78d872e47b7a6e4cd93ea10c4b (patch) | |
| tree | db5e036cf9f258e164a22e5484fcf316bb444a08 | |
| parent | b9ffa3f26b4b8810f90d91924042f951d0ae8dbf (diff) | |
TextView: Offer suggestions in context menu.
- Extract SuggestionInfo fetching code as SuggestionHelper and use it for
both context menu and existing suggestion popup.
- Show suggestion in "Replace..." sub menu.
Bug: 19397276
Change-Id: I20a86c1bdeb3616863b846237be55fa1a9b6ffdd
| -rw-r--r-- | core/java/android/widget/Editor.java | 441 |
1 files changed, 255 insertions, 186 deletions
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 15cea772d418..1576877a6ed5 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -82,6 +82,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.RenderNode; +import android.view.SubMenu; import android.view.View; import android.view.View.DragShadowBuilder; import android.view.View.OnClickListener; @@ -285,6 +286,9 @@ public class Editor { boolean mIsInsertionActionModeStartPending = false; + private final SuggestionHelper mSuggestionHelper = new SuggestionHelper(); + private SuggestionInfo[] mSuggestionInfosInContextMenu; + Editor(TextView textView) { mTextView = textView; // Synchronize the filter list, which places the undo input filter at the end. @@ -2369,6 +2373,9 @@ public class Editor { if (offset == -1) { return; } + mPreserveDetachedSelection = true; + stopTextActionMode(); + mPreserveDetachedSelection = false; final boolean isOnSelection = mTextView.hasSelection() && offset >= mTextView.getSelectionStart() && offset <= mTextView.getSelectionEnd(); if (!isOnSelection) { @@ -2378,7 +2385,24 @@ public class Editor { Selection.setSelection((Spannable) mTextView.getText(), offset); } - // TODO: Add suggestions in the context menu. + if (shouldOfferToShowSuggestions()) { + if (mSuggestionInfosInContextMenu == null) { + mSuggestionInfosInContextMenu = + new SuggestionInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE]; + for (int i = 0; i < mSuggestionInfosInContextMenu.length; i++) { + mSuggestionInfosInContextMenu[i] = new SuggestionInfo(); + } + } + final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE, + com.android.internal.R.string.replace); + mSuggestionHelper.getSuggestionInfo(mSuggestionInfosInContextMenu); + int i = 0; + for (final SuggestionInfo info : mSuggestionInfosInContextMenu) { + info.mSuggestionEnd = info.mText.length(); + subMenu.add(Menu.NONE, Menu.NONE, i++, info.mText) + .setOnMenuItemClickListener(mOnContextMenuReplaceItemClickListener); + } + } menu.add(Menu.NONE, TextView.ID_UNDO, MENU_ITEM_ORDER_UNDO, com.android.internal.R.string.undo) @@ -2422,6 +2446,61 @@ public class Editor { mPreserveDetachedSelection = true; } + private void replaceWithSuggestion(SuggestionInfo suggestionInfo, int spanStart, int spanEnd) { + final Editable editable = (Editable) mTextView.getText(); + final String originalText = TextUtils.substring(editable, spanStart, spanEnd); + // SuggestionSpans are removed by replace: save them before + SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd, + SuggestionSpan.class); + final int length = suggestionSpans.length; + int[] suggestionSpansStarts = new int[length]; + int[] suggestionSpansEnds = new int[length]; + int[] suggestionSpansFlags = new int[length]; + for (int i = 0; i < length; i++) { + final SuggestionSpan suggestionSpan = suggestionSpans[i]; + suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan); + suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan); + suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan); + + // Remove potential misspelled flags + int suggestionSpanFlags = suggestionSpan.getFlags(); + if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) != 0) { + suggestionSpanFlags &= ~SuggestionSpan.FLAG_MISSPELLED; + suggestionSpanFlags &= ~SuggestionSpan.FLAG_EASY_CORRECT; + suggestionSpan.setFlags(suggestionSpanFlags); + } + } + + // Notify source IME of the suggestion pick. Do this before swapping texts. + suggestionInfo.mSuggestionSpan.notifySelection( + mTextView.getContext(), originalText, suggestionInfo.mSuggestionIndex); + + // Swap text content between actual text and Suggestion span + final int suggestionStart = suggestionInfo.mSuggestionStart; + final int suggestionEnd = suggestionInfo.mSuggestionEnd; + final String suggestion = suggestionInfo.mText.subSequence( + suggestionStart, suggestionEnd).toString(); + mTextView.replaceText_internal(spanStart, spanEnd, suggestion); + + String[] suggestions = suggestionInfo.mSuggestionSpan.getSuggestions(); + suggestions[suggestionInfo.mSuggestionIndex] = originalText; + + // Restore previous SuggestionSpans + final int lengthDelta = suggestion.length() - (spanEnd - spanStart); + for (int i = 0; i < length; i++) { + // Only spans that include the modified region make sense after replacement + // Spans partially included in the replaced region are removed, there is no + // way to assign them a valid range after replacement + if (suggestionSpansStarts[i] <= spanStart && suggestionSpansEnds[i] >= spanEnd) { + mTextView.setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i], + suggestionSpansEnds[i] + lengthDelta, suggestionSpansFlags[i]); + } + } + // Move cursor at the end of the replaced word + final int newCursorPosition = spanEnd + lengthDelta; + mTextView.setCursorPosition_internal(newCursorPosition, newCursorPosition); + } + private final MenuItem.OnMenuItemClickListener mOnContextMenuItemClickListener = new MenuItem.OnMenuItemClickListener() { @Override @@ -2433,6 +2512,31 @@ public class Editor { } }; + private final MenuItem.OnMenuItemClickListener mOnContextMenuReplaceItemClickListener = + new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + int index = item.getOrder(); + if (index < 0 || index >= mSuggestionInfosInContextMenu.length) { + clear(); + return false; + } + final Spannable spannable = (Spannable) mTextView.getText(); + final SuggestionSpan suggestionSpan = + mSuggestionInfosInContextMenu[index].mSuggestionSpan; + replaceWithSuggestion(mSuggestionInfosInContextMenu[index], + spannable.getSpanStart(suggestionSpan), spannable.getSpanEnd(suggestionSpan)); + clear(); + return true; + } + + private void clear() { + for (final SuggestionInfo info : mSuggestionInfosInContextMenu) { + info.clear(); + } + } + }; + /** * Controls the {@link EasyEditSpan} monitoring when it is added, and when the related * pop-up should be displayed. @@ -2849,6 +2953,131 @@ public class Editor { } } + private static class SuggestionInfo { + // Range of actual suggestion within text + int mSuggestionStart, mSuggestionEnd; + + // The SuggestionSpan that this TextView represents + @Nullable + SuggestionSpan mSuggestionSpan; + + // The index of this suggestion inside suggestionSpan + int mSuggestionIndex; + + final SpannableStringBuilder mText = new SpannableStringBuilder(); + + void clear() { + mSuggestionSpan = null; + mText.clear(); + } + } + + private class SuggestionHelper { + private final Comparator<SuggestionSpan> mSuggestionSpanComparator = + new SuggestionSpanComparator(); + private final HashMap<SuggestionSpan, Integer> mSpansLengths = + new HashMap<SuggestionSpan, Integer>(); + + private class SuggestionSpanComparator implements Comparator<SuggestionSpan> { + public int compare(SuggestionSpan span1, SuggestionSpan span2) { + final int flag1 = span1.getFlags(); + final int flag2 = span2.getFlags(); + if (flag1 != flag2) { + // The order here should match what is used in updateDrawState + final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0; + final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0; + final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0; + final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0; + if (easy1 && !misspelled1) return -1; + if (easy2 && !misspelled2) return 1; + if (misspelled1) return -1; + if (misspelled2) return 1; + } + + return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue(); + } + } + + /** + * Returns the suggestion spans that cover the current cursor position. The suggestion + * spans are sorted according to the length of text that they are attached to. + */ + private SuggestionSpan[] getSortedSuggestionSpans() { + int pos = mTextView.getSelectionStart(); + Spannable spannable = (Spannable) mTextView.getText(); + SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class); + + mSpansLengths.clear(); + for (SuggestionSpan suggestionSpan : suggestionSpans) { + int start = spannable.getSpanStart(suggestionSpan); + int end = spannable.getSpanEnd(suggestionSpan); + mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start)); + } + + // The suggestions are sorted according to their types (easy correction first, then + // misspelled) and to the length of the text that they cover (shorter first). + Arrays.sort(suggestionSpans, mSuggestionSpanComparator); + mSpansLengths.clear(); + + return suggestionSpans; + } + + /** + * Gets the SuggestionInfo list that contains suggestion information at the current cursor + * position. + * + * @param suggestionInfos SuggestionInfo array the results will be set. + * @return the number of suggestions actually fetched. + */ + public int getSuggestionInfo(SuggestionInfo[] suggestionInfos) { + final Spannable spannable = (Spannable) mTextView.getText(); + final SuggestionSpan[] suggestionSpans = getSortedSuggestionSpans(); + final int nbSpans = suggestionSpans.length; + if (nbSpans == 0) return 0; + + int numberOfSuggestions = 0; + for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) { + final SuggestionSpan suggestionSpan = suggestionSpans[spanIndex]; + final int spanStart = spannable.getSpanStart(suggestionSpan); + final int spanEnd = spannable.getSpanEnd(suggestionSpan); + + final String[] suggestions = suggestionSpan.getSuggestions(); + final int nbSuggestions = suggestions.length; + for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { + final String suggestion = suggestions[suggestionIndex]; + boolean suggestionIsDuplicate = false; + for (int i = 0; i < numberOfSuggestions; i++) { + if (suggestionInfos[i].mText.toString().equals(suggestion)) { + final SuggestionSpan otherSuggestionSpan = + suggestionInfos[i].mSuggestionSpan; + final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan); + final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan); + if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) { + suggestionIsDuplicate = true; + break; + } + } + } + + if (suggestionIsDuplicate) { + continue; + } + SuggestionInfo suggestionInfo = suggestionInfos[numberOfSuggestions]; + suggestionInfo.mSuggestionSpan = suggestionSpan; + suggestionInfo.mSuggestionIndex = suggestionIndex; + suggestionInfo.mSuggestionStart = 0; + suggestionInfo.mSuggestionEnd = suggestion.length(); + suggestionInfo.mText.replace(0, suggestionInfo.mText.length(), suggestion); + numberOfSuggestions++; + if (numberOfSuggestions >= suggestionInfos.length) { + return numberOfSuggestions; + } + } + } + return numberOfSuggestions; + } + } + @VisibleForTesting public class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener { private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE; @@ -2862,8 +3091,6 @@ public class Editor { private boolean mCursorWasVisibleBeforeSuggestions; private boolean mIsShowingUp = false; private SuggestionAdapter mSuggestionsAdapter; - private final Comparator<SuggestionSpan> mSuggestionSpanComparator; - private final HashMap<SuggestionSpan, Integer> mSpansLengths; private final TextAppearanceSpan mHighlightSpan = new TextAppearanceSpan( mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle); private TextView mAddToDictionaryButton; @@ -2895,8 +3122,6 @@ public class Editor { public SuggestionsPopupWindow() { mCursorWasVisibleBeforeSuggestions = mCursorVisible; - mSuggestionSpanComparator = new SuggestionSpanComparator(); - mSpansLengths = new HashMap<SuggestionSpan, Integer>(); } @Override @@ -2987,24 +3212,6 @@ public class Editor { mIsShowingUp = false; } - private final class SuggestionInfo { - int suggestionStart, suggestionEnd; // range of actual suggestion within text - - // the SuggestionSpan that this TextView represents - @Nullable - SuggestionSpan suggestionSpan; - - int suggestionIndex; // the index of this suggestion inside suggestionSpan - - @Nullable - final SpannableStringBuilder text = new SpannableStringBuilder(); - - void clear() { - suggestionSpan = null; - text.clear(); - } - } - private class SuggestionAdapter extends BaseAdapter { private LayoutInflater mInflater = (LayoutInflater) mTextView.getContext(). getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -3034,55 +3241,11 @@ public class Editor { } final SuggestionInfo suggestionInfo = mSuggestionInfos[position]; - textView.setText(suggestionInfo.text); + textView.setText(suggestionInfo.mText); return textView; } } - private class SuggestionSpanComparator implements Comparator<SuggestionSpan> { - public int compare(SuggestionSpan span1, SuggestionSpan span2) { - final int flag1 = span1.getFlags(); - final int flag2 = span2.getFlags(); - if (flag1 != flag2) { - // The order here should match what is used in updateDrawState - final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0; - final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0; - final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0; - final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0; - if (easy1 && !misspelled1) return -1; - if (easy2 && !misspelled2) return 1; - if (misspelled1) return -1; - if (misspelled2) return 1; - } - - return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue(); - } - } - - /** - * Returns the suggestion spans that cover the current cursor position. The suggestion - * spans are sorted according to the length of text that they are attached to. - */ - private SuggestionSpan[] getSuggestionSpans() { - int pos = mTextView.getSelectionStart(); - Spannable spannable = (Spannable) mTextView.getText(); - SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class); - - mSpansLengths.clear(); - for (SuggestionSpan suggestionSpan : suggestionSpans) { - int start = spannable.getSpanStart(suggestionSpan); - int end = spannable.getSpanEnd(suggestionSpan); - mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start)); - } - - // The suggestions are sorted according to their types (easy correction first, then - // misspelled) and to the length of the text that they cover (shorter first). - Arrays.sort(suggestionSpans, mSuggestionSpanComparator); - mSpansLengths.clear(); - - return suggestionSpans; - } - @VisibleForTesting public ViewGroup getContentViewForTesting() { return mContentView; @@ -3166,66 +3329,26 @@ public class Editor { private boolean updateSuggestions() { Spannable spannable = (Spannable) mTextView.getText(); - SuggestionSpan[] suggestionSpans = getSuggestionSpans(); - - final int nbSpans = suggestionSpans.length; - // Suggestions are shown after a delay: the underlying spans may have been removed - if (nbSpans == 0) return false; + mNumberOfSuggestions = + mSuggestionHelper.getSuggestionInfo(mSuggestionInfos); + if (mNumberOfSuggestions == 0) { + return false; + } - mNumberOfSuggestions = 0; int spanUnionStart = mTextView.getText().length(); int spanUnionEnd = 0; mMisspelledSpan = null; - int underlineColor = 0; - - for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) { - SuggestionSpan suggestionSpan = suggestionSpans[spanIndex]; - final int spanStart = spannable.getSpanStart(suggestionSpan); - final int spanEnd = spannable.getSpanEnd(suggestionSpan); - spanUnionStart = Math.min(spanStart, spanUnionStart); - spanUnionEnd = Math.max(spanEnd, spanUnionEnd); - + for (int i = 0; i < mNumberOfSuggestions; i++) { + final SuggestionInfo suggestionInfo = mSuggestionInfos[i]; + final SuggestionSpan suggestionSpan = suggestionInfo.mSuggestionSpan; if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) { mMisspelledSpan = suggestionSpan; } - - // The first span dictates the background color of the highlighted text - if (spanIndex == 0) underlineColor = suggestionSpan.getUnderlineColor(); - - String[] suggestions = suggestionSpan.getSuggestions(); - int nbSuggestions = suggestions.length; - for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { - String suggestion = suggestions[suggestionIndex]; - - boolean suggestionIsDuplicate = false; - for (int i = 0; i < mNumberOfSuggestions; i++) { - if (mSuggestionInfos[i].text.toString().equals(suggestion)) { - SuggestionSpan otherSuggestionSpan = mSuggestionInfos[i].suggestionSpan; - final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan); - final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan); - if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) { - suggestionIsDuplicate = true; - break; - } - } - } - - if (!suggestionIsDuplicate) { - SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; - suggestionInfo.suggestionSpan = suggestionSpan; - suggestionInfo.suggestionIndex = suggestionIndex; - suggestionInfo.text.replace(0, suggestionInfo.text.length(), suggestion); - - mNumberOfSuggestions++; - - if (mNumberOfSuggestions == MAX_NUMBER_SUGGESTIONS) { - // Also end outer for loop - spanIndex = nbSpans; - break; - } - } - } + final int spanStart = spannable.getSpanStart(suggestionSpan); + final int spanEnd = spannable.getSpanEnd(suggestionSpan); + spanUnionStart = Math.min(spanUnionStart, spanStart); + spanUnionEnd = Math.max(spanUnionEnd, spanEnd); } for (int i = 0; i < mNumberOfSuggestions; i++) { @@ -3244,6 +3367,7 @@ public class Editor { mAddToDictionaryButton.setVisibility(addToDictionaryButtonVisibility); if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(); + final int underlineColor = mSuggestionInfos[0].mSuggestionSpan.getUnderlineColor(); if (underlineColor == 0) { // Fallback on the default highlight color when the first span does not provide one mSuggestionRangeSpan.setBackgroundColor(mTextView.mHighlightColor); @@ -3263,21 +3387,21 @@ public class Editor { private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart, int unionEnd) { final Spannable text = (Spannable) mTextView.getText(); - final int spanStart = text.getSpanStart(suggestionInfo.suggestionSpan); - final int spanEnd = text.getSpanEnd(suggestionInfo.suggestionSpan); + final int spanStart = text.getSpanStart(suggestionInfo.mSuggestionSpan); + final int spanEnd = text.getSpanEnd(suggestionInfo.mSuggestionSpan); // Adjust the start/end of the suggestion span - suggestionInfo.suggestionStart = spanStart - unionStart; - suggestionInfo.suggestionEnd = suggestionInfo.suggestionStart - + suggestionInfo.text.length(); + suggestionInfo.mSuggestionStart = spanStart - unionStart; + suggestionInfo.mSuggestionEnd = suggestionInfo.mSuggestionStart + + suggestionInfo.mText.length(); - suggestionInfo.text.setSpan(mHighlightSpan, 0, suggestionInfo.text.length(), + suggestionInfo.mText.setSpan(mHighlightSpan, 0, suggestionInfo.mText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // Add the text before and after the span. final String textAsString = text.toString(); - suggestionInfo.text.insert(0, textAsString.substring(unionStart, spanStart)); - suggestionInfo.text.append(textAsString.substring(spanEnd, unionEnd)); + suggestionInfo.mText.insert(0, textAsString.substring(unionStart, spanStart)); + suggestionInfo.mText.append(textAsString.substring(spanEnd, unionEnd)); } @Override @@ -3285,69 +3409,14 @@ public class Editor { Editable editable = (Editable) mTextView.getText(); SuggestionInfo suggestionInfo = mSuggestionInfos[position]; - final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan); - final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan); + final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan); + final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan); if (spanStart < 0 || spanEnd <= spanStart) { // Span has been removed hideWithCleanUp(); return; } - - final String originalText = TextUtils.substring(editable, spanStart, spanEnd); - - // SuggestionSpans are removed by replace: save them before - final SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd, - SuggestionSpan.class); - final int length = suggestionSpans.length; - final int[] suggestionSpansStarts = new int[length]; - final int[] suggestionSpansEnds = new int[length]; - final int[] suggestionSpansFlags = new int[length]; - for (int i = 0; i < length; i++) { - final SuggestionSpan suggestionSpan = suggestionSpans[i]; - suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan); - suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan); - suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan); - - // Remove potential misspelled flags - int suggestionSpanFlags = suggestionSpan.getFlags(); - if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) { - suggestionSpanFlags &= ~SuggestionSpan.FLAG_MISSPELLED; - suggestionSpanFlags &= ~SuggestionSpan.FLAG_EASY_CORRECT; - suggestionSpan.setFlags(suggestionSpanFlags); - } - } - - final int suggestionStart = suggestionInfo.suggestionStart; - final int suggestionEnd = suggestionInfo.suggestionEnd; - final String suggestion = suggestionInfo.text.subSequence( - suggestionStart, suggestionEnd).toString(); - mTextView.replaceText_internal(spanStart, spanEnd, suggestion); - - // Notify source IME of the suggestion pick. Do this before - // swaping texts. - suggestionInfo.suggestionSpan.notifySelection( - mTextView.getContext(), originalText, suggestionInfo.suggestionIndex); - - // Swap text content between actual text and Suggestion span - final String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions(); - suggestions[suggestionInfo.suggestionIndex] = originalText; - - // Restore previous SuggestionSpans - final int lengthDifference = suggestion.length() - (spanEnd - spanStart); - for (int i = 0; i < length; i++) { - // Only spans that include the modified region make sense after replacement - // Spans partially included in the replaced region are removed, there is no - // way to assign them a valid range after replacement - if (suggestionSpansStarts[i] <= spanStart && - suggestionSpansEnds[i] >= spanEnd) { - mTextView.setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i], - suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); - } - } - - // Move cursor at the end of the replaced word - final int newCursorPosition = spanEnd + lengthDifference; - mTextView.setCursorPosition_internal(newCursorPosition, newCursorPosition); + replaceWithSuggestion(suggestionInfo, spanStart, spanEnd); hideWithCleanUp(); } } |