Loading core/java/android/widget/Editor.java +104 −69 Original line number Diff line number Diff line Loading @@ -215,7 +215,7 @@ public class Editor { boolean mInBatchEditControllers; boolean mShowSoftInputOnFocus = true; boolean mPreserveDetachedSelection; private boolean mPreserveDetachedSelection; boolean mTemporaryDetach; boolean mIsBeingLongClicked; Loading Loading @@ -352,7 +352,6 @@ public class Editor { void replace() { int middle = (mTextView.getSelectionStart() + mTextView.getSelectionEnd()) / 2; stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), middle); showSuggestions(); } Loading Loading @@ -429,10 +428,8 @@ public class Editor { mSpellChecker = null; } mPreserveDetachedSelection = true; hideCursorAndSpanControllers(); stopTextActionMode(); mPreserveDetachedSelection = false; stopTextActionModeWithPreservingSelection(); mTemporaryDetach = false; } Loading Loading @@ -1104,7 +1101,6 @@ public class Editor { mInsertionControllerEnabled) { final int offset = mTextView.getOffsetForPosition(mLastDownPositionX, mLastDownPositionY); stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), offset); getInsertionController().show(); mIsInsertionActionModeStartPending = true; Loading Loading @@ -1208,18 +1204,15 @@ public class Editor { mTextView.onEndBatchEdit(); if (mTextView.isInExtractedMode()) { // terminateTextSelectionMode removes selection, which we want to keep when // ExtractEditText goes out of focus. final int selStart = mTextView.getSelectionStart(); final int selEnd = mTextView.getSelectionEnd(); hideCursorAndSpanControllers(); stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), selStart, selEnd); stopTextActionModeWithPreservingSelection(); } else { if (mTemporaryDetach) mPreserveDetachedSelection = true; hideCursorAndSpanControllers(); if (mTemporaryDetach) { stopTextActionModeWithPreservingSelection(); } else { stopTextActionMode(); if (mTemporaryDetach) mPreserveDetachedSelection = false; } downgradeEasyCorrectionSpans(); } // No need to create the controller Loading Loading @@ -1290,10 +1283,8 @@ public class Editor { makeBlink(); } final InputMethodManager imm = InputMethodManager.peekInstance(); final boolean immFullScreen = (imm != null && imm.isFullscreenMode()); if (mSelectionModifierCursorController != null && mTextView.hasSelection() && !immFullScreen && mTextActionMode != null) { mSelectionModifierCursorController.show(); if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) { startSelectionActionMode(); } } else { if (mBlink != null) { Loading @@ -1304,9 +1295,7 @@ public class Editor { } // Order matters! Must be done before onParentLostFocus to rely on isShowingUp hideCursorAndSpanControllers(); if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); } stopTextActionModeWithPreservingSelection(); if (mSuggestionsPopupWindow != null) { mSuggestionsPopupWindow.onParentLostFocus(); } Loading Loading @@ -1856,6 +1845,38 @@ public class Editor { } } void refreshTextActionMode() { if (extractedTextModeWillBeStarted()) { return; } final boolean hasSelection = mTextView.hasSelection(); final SelectionModifierCursorController selectionController = getSelectionController(); final InsertionPointCursorController insertionController = getInsertionController(); if ((selectionController != null && selectionController.isCursorBeingModified()) || (insertionController != null && insertionController.isCursorBeingModified())) { // ActionMode should be managed by the currently active cursor controller. return; } if (hasSelection) { if (mTextActionMode == null || selectionController == null || !selectionController.isActive()) { // Avoid dismissing the selection if it exists. stopTextActionModeWithPreservingSelection(); startSelectionActionMode(); } else { mTextActionMode.invalidateContentRect(); } } else { // Insertion action mode is started only when insertion controller is explicitly // activated. if (insertionController == null || !insertionController.isActive()) { stopTextActionMode(); } else if (mTextActionMode != null) { mTextActionMode.invalidateContentRect(); } } } /** * Start an Insertion action mode. */ Loading @@ -1879,17 +1900,15 @@ public class Editor { /** * Starts a Selection Action Mode with the current selection and ensures the selection handles * are shown if there is a selection, otherwise the insertion handle is shown. This should be * used when the mode is started from a non-touch event. * are shown if there is a selection. This should be used when the mode is started from a * non-touch event. * * @return true if the selection mode was actually started. */ boolean startSelectionActionMode() { private boolean startSelectionActionMode() { boolean selectionStarted = startSelectionActionModeInternal(); if (selectionStarted) { getSelectionController().show(); } else if (getInsertionController() != null) { getInsertionController().show(); } return selectionStarted; } Loading @@ -1907,66 +1926,52 @@ public class Editor { if (extractedTextModeWillBeStarted()) { return false; } if (mTextActionMode != null) { mTextActionMode.finish(); if (!checkField()) { return false; } if (!checkFieldAndSelectCurrentWord()) { if (!mTextView.hasSelection() && !selectCurrentWord()) { // No selection and cannot select a word. return false; } // Avoid dismissing the selection if it exists. mPreserveDetachedSelection = true; stopTextActionMode(); mPreserveDetachedSelection = false; stopTextActionModeWithPreservingSelection(); getSelectionController().enterDrag( SelectionModifierCursorController.DRAG_ACCELERATOR_MODE_WORD); return true; } /** * Checks whether a selection can be performed on the current TextView and if so selects * the current word. * Checks whether a selection can be performed on the current TextView. * * @return true if there already was a selection or if the current word was selected. * @return true if a selection can be performed */ boolean checkFieldAndSelectCurrentWord() { boolean checkField() { if (!mTextView.canSelectText() || !mTextView.requestFocus()) { Log.w(TextView.LOG_TAG, "TextView does not support text selection. Selection cancelled."); return false; } if (!mTextView.hasSelection()) { // There may already be a selection on device rotation return selectCurrentWord(); } return true; } private boolean startSelectionActionModeInternal() { if (extractedTextModeWillBeStarted()) { return false; } if (mTextActionMode != null) { // Text action mode is already started mTextActionMode.invalidate(); return false; } if (!checkFieldAndSelectCurrentWord()) { if (!checkField() || !mTextView.hasSelection()) { return false; } boolean willExtract = extractedTextModeWillBeStarted(); // Do not start the action mode when extracted text will show up full screen, which would // immediately hide the newly created action bar and would be visually distracting. if (!willExtract) { ActionMode.Callback actionModeCallback = new TextActionModeCallback(true /* hasSelection */); mTextActionMode = mTextView.startActionMode( actionModeCallback, ActionMode.TYPE_FLOATING); } mTextActionMode = mTextView.startActionMode(actionModeCallback, ActionMode.TYPE_FLOATING); final boolean selectionStarted = mTextActionMode != null || willExtract; final boolean selectionStarted = mTextActionMode != null; if (selectionStarted && !mTextView.isTextSelectable() && mShowSoftInputOnFocus) { // Show the IME to be able to replace text, except when selecting non editable text. final InputMethodManager imm = InputMethodManager.peekInstance(); Loading Loading @@ -2107,6 +2112,12 @@ public class Editor { } } private void stopTextActionModeWithPreservingSelection() { mPreserveDetachedSelection = true; stopTextActionMode(); mPreserveDetachedSelection = false; } /** * @return True if this view supports insertion handles. */ Loading Loading @@ -2436,16 +2447,14 @@ public class Editor { if (offset == -1) { return; } mPreserveDetachedSelection = true; stopTextActionMode(); mPreserveDetachedSelection = false; stopTextActionModeWithPreservingSelection(); final boolean isOnSelection = mTextView.hasSelection() && offset >= mTextView.getSelectionStart() && offset <= mTextView.getSelectionEnd(); if (!isOnSelection) { // Right clicked position is not on the selection. Remove the selection and move the // cursor to the right clicked position. stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), offset); stopTextActionMode(); } if (shouldOfferToShowSuggestions()) { Loading Loading @@ -3488,7 +3497,6 @@ public class Editor { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Editable editable = (Editable) mTextView.getText(); SuggestionInfo suggestionInfo = mSuggestionInfos[position]; final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan); final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan); if (spanStart < 0 || spanEnd <= spanStart) { Loading Loading @@ -4391,7 +4399,7 @@ public class Editor { if (distanceSquared < touchSlop * touchSlop) { // Tapping on the handle toggles the insertion action mode. if (mTextActionMode != null) { mTextActionMode.finish(); stopTextActionMode(); } else { startInsertionActionMode(); } Loading Loading @@ -4808,6 +4816,10 @@ public class Editor { * preventing the activity from being recycled. */ public void onDetached(); public boolean isCursorBeingModified(); public boolean isActive(); } private class InsertionPointCursorController implements CursorController { Loading Loading @@ -4851,6 +4863,16 @@ public class Editor { if (mHandle != null) mHandle.onDetached(); } @Override public boolean isCursorBeingModified() { return mHandle != null && mHandle.isDragging(); } @Override public boolean isActive() { return mHandle != null && mHandle.isShowing(); } } class SelectionModifierCursorController implements CursorController { Loading Loading @@ -5040,9 +5062,7 @@ public class Editor { if (mStartOffset != offset) { // Start character based drag accelerator. if (mTextActionMode != null) { mTextActionMode.finish(); } stopTextActionMode(); enterDrag(DRAG_ACCELERATOR_MODE_CHARACTER); mDiscardNextActionUp = true; mHaventMovedEnoughToStartDrag = false; Loading Loading @@ -5116,9 +5136,7 @@ public class Editor { if (mInsertionActionModeRunnable != null) { mTextView.removeCallbacks(mInsertionActionModeRunnable); } if (mTextActionMode != null) { mTextActionMode.finish(); } stopTextActionMode(); if (!selectCurrentParagraph()) { return false; } Loading Loading @@ -5227,6 +5245,12 @@ public class Editor { mStartOffset = -1; mDragAcceleratorMode = DRAG_ACCELERATOR_MODE_INACTIVE; mSwitchedLines = false; final int selectionStart = mTextView.getSelectionStart(); final int selectionEnd = mTextView.getSelectionEnd(); if (selectionStart > selectionEnd) { Selection.setSelection((Spannable) mTextView.getText(), selectionEnd, selectionStart); } } /** Loading @@ -5236,6 +5260,12 @@ public class Editor { return mStartHandle != null && mStartHandle.isDragging(); } @Override public boolean isCursorBeingModified() { return isDragAcceleratorActive() || isSelectionStartDragged() || (mEndHandle != null && mEndHandle.isDragging()); } /** * @return true if the user is selecting text using the drag accelerator. */ Loading @@ -5257,6 +5287,11 @@ public class Editor { if (mStartHandle != null) mStartHandle.onDetached(); if (mEndHandle != null) mEndHandle.onDetached(); } @Override public boolean isActive() { return mStartHandle != null && mStartHandle.isShowing(); } } private class CorrectionHighlighter { Loading core/java/android/widget/TextView.java +18 −39 Original line number Diff line number Diff line Loading @@ -1511,6 +1511,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (result != null) { if (isTextEditable()) { replaceSelectionWithText(result); if (mEditor != null) { mEditor.refreshTextActionMode(); } } else { if (result.length() > 0) { Toast.makeText(getContext(), String.valueOf(result), Toast.LENGTH_LONG) Loading @@ -1520,12 +1523,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } else if (mText instanceof Spannable) { // Reset the selection. stopTextActionMode(); Selection.setSelection((Spannable) mText, getSelectionStart(), getSelectionEnd()); } if (mEditor.hasSelectionController()) { mEditor.startSelectionActionMode(); Selection.setSelection((Spannable) mText, getSelectionEnd()); } } } Loading Loading @@ -5393,11 +5391,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // - onFocusChanged cannot start it when focus is given to a view with selected text (after // a screen rotation) since layout is not yet initialized at that point. if (mEditor != null && mEditor.mCreatedWithASelection) { if (mEditor.extractedTextModeWillBeStarted()) { mEditor.checkFieldAndSelectCurrentWord(); } else { mEditor.startSelectionActionMode(); } mEditor.refreshTextActionMode(); mEditor.mCreatedWithASelection = false; } Loading Loading @@ -6594,6 +6588,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // in the extracted view. mEditor.hideCursorAndSpanControllers(); stopTextActionMode(); if (mEditor.mSelectionModifierCursorController != null) { mEditor.mSelectionModifierCursorController.resetTouchOffsets(); } } /** Loading Loading @@ -8289,6 +8286,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (newSelEnd < 0) { newSelEnd = Selection.getSelectionEnd(buf); } if (mEditor != null) { mEditor.refreshTextActionMode(); } onSelectionChanged(newSelStart, newSelEnd); } } Loading Loading @@ -9199,10 +9199,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (start >= 0 && start <= end && end <= text.length()) { Selection.setSelection((Spannable) text, start, end); // Make sure selection mode is engaged. if (mEditor != null) { mEditor.startSelectionActionMode(); } return true; } } Loading Loading @@ -9393,16 +9389,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (id) { case ID_SELECT_ALL: // This starts an action mode if triggered from another action mode. Text is // highlighted, so that it can be bulk edited, like selectAllOnFocus does. Returns // true even if text is empty. boolean shouldRestartActionMode = mEditor != null && mEditor.mTextActionMode != null; stopTextActionMode(); selectAllText(); if (shouldRestartActionMode) { mEditor.startSelectionActionMode(); } return true; case ID_UNDO: Loading @@ -9428,7 +9415,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case ID_CUT: setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max))); deleteText_internal(min, max); stopTextActionMode(); return true; case ID_COPY: Loading Loading @@ -9684,12 +9670,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } boolean selectAllText() { // Need to hide insert point cursor controller before settings selection, otherwise insert // point cursor controller obtains cursor update event and update cursor with cancelling // selection. if (mEditor != null) { mEditor.hideInsertionPointCursorController(); } final int length = mText.length(); Selection.setSelection((Spannable) mText, 0, length); return length > 0; Loading Loading @@ -9728,7 +9708,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } } stopTextActionMode(); sLastCutCopyOrTextChangedTime = 0; } } Loading @@ -9741,7 +9720,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT); sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText); getContext().startActivity(Intent.createChooser(sharingIntent, null)); stopTextActionMode(); Selection.setSelection((Spannable) mText, getSelectionEnd()); } } Loading Loading @@ -10059,6 +10038,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener && getAccessibilitySelectionEnd() == end) { return; } CharSequence text = getIterableTextForAccessibility(); if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) { Selection.setSelection((Spannable) text, start, end); } else { Selection.removeSelection((Spannable) text); } // Hide all selection controllers used for adjusting selection // since we are doing so explicitlty by other means and these // controllers interact with how selection behaves. Loading @@ -10066,12 +10051,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mEditor.hideCursorAndSpanControllers(); mEditor.stopTextActionMode(); } CharSequence text = getIterableTextForAccessibility(); if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) { Selection.setSelection((Spannable) text, start, end); } else { Selection.removeSelection((Spannable) text); } } /** @hide */ Loading Loading
core/java/android/widget/Editor.java +104 −69 Original line number Diff line number Diff line Loading @@ -215,7 +215,7 @@ public class Editor { boolean mInBatchEditControllers; boolean mShowSoftInputOnFocus = true; boolean mPreserveDetachedSelection; private boolean mPreserveDetachedSelection; boolean mTemporaryDetach; boolean mIsBeingLongClicked; Loading Loading @@ -352,7 +352,6 @@ public class Editor { void replace() { int middle = (mTextView.getSelectionStart() + mTextView.getSelectionEnd()) / 2; stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), middle); showSuggestions(); } Loading Loading @@ -429,10 +428,8 @@ public class Editor { mSpellChecker = null; } mPreserveDetachedSelection = true; hideCursorAndSpanControllers(); stopTextActionMode(); mPreserveDetachedSelection = false; stopTextActionModeWithPreservingSelection(); mTemporaryDetach = false; } Loading Loading @@ -1104,7 +1101,6 @@ public class Editor { mInsertionControllerEnabled) { final int offset = mTextView.getOffsetForPosition(mLastDownPositionX, mLastDownPositionY); stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), offset); getInsertionController().show(); mIsInsertionActionModeStartPending = true; Loading Loading @@ -1208,18 +1204,15 @@ public class Editor { mTextView.onEndBatchEdit(); if (mTextView.isInExtractedMode()) { // terminateTextSelectionMode removes selection, which we want to keep when // ExtractEditText goes out of focus. final int selStart = mTextView.getSelectionStart(); final int selEnd = mTextView.getSelectionEnd(); hideCursorAndSpanControllers(); stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), selStart, selEnd); stopTextActionModeWithPreservingSelection(); } else { if (mTemporaryDetach) mPreserveDetachedSelection = true; hideCursorAndSpanControllers(); if (mTemporaryDetach) { stopTextActionModeWithPreservingSelection(); } else { stopTextActionMode(); if (mTemporaryDetach) mPreserveDetachedSelection = false; } downgradeEasyCorrectionSpans(); } // No need to create the controller Loading Loading @@ -1290,10 +1283,8 @@ public class Editor { makeBlink(); } final InputMethodManager imm = InputMethodManager.peekInstance(); final boolean immFullScreen = (imm != null && imm.isFullscreenMode()); if (mSelectionModifierCursorController != null && mTextView.hasSelection() && !immFullScreen && mTextActionMode != null) { mSelectionModifierCursorController.show(); if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) { startSelectionActionMode(); } } else { if (mBlink != null) { Loading @@ -1304,9 +1295,7 @@ public class Editor { } // Order matters! Must be done before onParentLostFocus to rely on isShowingUp hideCursorAndSpanControllers(); if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); } stopTextActionModeWithPreservingSelection(); if (mSuggestionsPopupWindow != null) { mSuggestionsPopupWindow.onParentLostFocus(); } Loading Loading @@ -1856,6 +1845,38 @@ public class Editor { } } void refreshTextActionMode() { if (extractedTextModeWillBeStarted()) { return; } final boolean hasSelection = mTextView.hasSelection(); final SelectionModifierCursorController selectionController = getSelectionController(); final InsertionPointCursorController insertionController = getInsertionController(); if ((selectionController != null && selectionController.isCursorBeingModified()) || (insertionController != null && insertionController.isCursorBeingModified())) { // ActionMode should be managed by the currently active cursor controller. return; } if (hasSelection) { if (mTextActionMode == null || selectionController == null || !selectionController.isActive()) { // Avoid dismissing the selection if it exists. stopTextActionModeWithPreservingSelection(); startSelectionActionMode(); } else { mTextActionMode.invalidateContentRect(); } } else { // Insertion action mode is started only when insertion controller is explicitly // activated. if (insertionController == null || !insertionController.isActive()) { stopTextActionMode(); } else if (mTextActionMode != null) { mTextActionMode.invalidateContentRect(); } } } /** * Start an Insertion action mode. */ Loading @@ -1879,17 +1900,15 @@ public class Editor { /** * Starts a Selection Action Mode with the current selection and ensures the selection handles * are shown if there is a selection, otherwise the insertion handle is shown. This should be * used when the mode is started from a non-touch event. * are shown if there is a selection. This should be used when the mode is started from a * non-touch event. * * @return true if the selection mode was actually started. */ boolean startSelectionActionMode() { private boolean startSelectionActionMode() { boolean selectionStarted = startSelectionActionModeInternal(); if (selectionStarted) { getSelectionController().show(); } else if (getInsertionController() != null) { getInsertionController().show(); } return selectionStarted; } Loading @@ -1907,66 +1926,52 @@ public class Editor { if (extractedTextModeWillBeStarted()) { return false; } if (mTextActionMode != null) { mTextActionMode.finish(); if (!checkField()) { return false; } if (!checkFieldAndSelectCurrentWord()) { if (!mTextView.hasSelection() && !selectCurrentWord()) { // No selection and cannot select a word. return false; } // Avoid dismissing the selection if it exists. mPreserveDetachedSelection = true; stopTextActionMode(); mPreserveDetachedSelection = false; stopTextActionModeWithPreservingSelection(); getSelectionController().enterDrag( SelectionModifierCursorController.DRAG_ACCELERATOR_MODE_WORD); return true; } /** * Checks whether a selection can be performed on the current TextView and if so selects * the current word. * Checks whether a selection can be performed on the current TextView. * * @return true if there already was a selection or if the current word was selected. * @return true if a selection can be performed */ boolean checkFieldAndSelectCurrentWord() { boolean checkField() { if (!mTextView.canSelectText() || !mTextView.requestFocus()) { Log.w(TextView.LOG_TAG, "TextView does not support text selection. Selection cancelled."); return false; } if (!mTextView.hasSelection()) { // There may already be a selection on device rotation return selectCurrentWord(); } return true; } private boolean startSelectionActionModeInternal() { if (extractedTextModeWillBeStarted()) { return false; } if (mTextActionMode != null) { // Text action mode is already started mTextActionMode.invalidate(); return false; } if (!checkFieldAndSelectCurrentWord()) { if (!checkField() || !mTextView.hasSelection()) { return false; } boolean willExtract = extractedTextModeWillBeStarted(); // Do not start the action mode when extracted text will show up full screen, which would // immediately hide the newly created action bar and would be visually distracting. if (!willExtract) { ActionMode.Callback actionModeCallback = new TextActionModeCallback(true /* hasSelection */); mTextActionMode = mTextView.startActionMode( actionModeCallback, ActionMode.TYPE_FLOATING); } mTextActionMode = mTextView.startActionMode(actionModeCallback, ActionMode.TYPE_FLOATING); final boolean selectionStarted = mTextActionMode != null || willExtract; final boolean selectionStarted = mTextActionMode != null; if (selectionStarted && !mTextView.isTextSelectable() && mShowSoftInputOnFocus) { // Show the IME to be able to replace text, except when selecting non editable text. final InputMethodManager imm = InputMethodManager.peekInstance(); Loading Loading @@ -2107,6 +2112,12 @@ public class Editor { } } private void stopTextActionModeWithPreservingSelection() { mPreserveDetachedSelection = true; stopTextActionMode(); mPreserveDetachedSelection = false; } /** * @return True if this view supports insertion handles. */ Loading Loading @@ -2436,16 +2447,14 @@ public class Editor { if (offset == -1) { return; } mPreserveDetachedSelection = true; stopTextActionMode(); mPreserveDetachedSelection = false; stopTextActionModeWithPreservingSelection(); final boolean isOnSelection = mTextView.hasSelection() && offset >= mTextView.getSelectionStart() && offset <= mTextView.getSelectionEnd(); if (!isOnSelection) { // Right clicked position is not on the selection. Remove the selection and move the // cursor to the right clicked position. stopTextActionMode(); Selection.setSelection((Spannable) mTextView.getText(), offset); stopTextActionMode(); } if (shouldOfferToShowSuggestions()) { Loading Loading @@ -3488,7 +3497,6 @@ public class Editor { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Editable editable = (Editable) mTextView.getText(); SuggestionInfo suggestionInfo = mSuggestionInfos[position]; final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan); final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan); if (spanStart < 0 || spanEnd <= spanStart) { Loading Loading @@ -4391,7 +4399,7 @@ public class Editor { if (distanceSquared < touchSlop * touchSlop) { // Tapping on the handle toggles the insertion action mode. if (mTextActionMode != null) { mTextActionMode.finish(); stopTextActionMode(); } else { startInsertionActionMode(); } Loading Loading @@ -4808,6 +4816,10 @@ public class Editor { * preventing the activity from being recycled. */ public void onDetached(); public boolean isCursorBeingModified(); public boolean isActive(); } private class InsertionPointCursorController implements CursorController { Loading Loading @@ -4851,6 +4863,16 @@ public class Editor { if (mHandle != null) mHandle.onDetached(); } @Override public boolean isCursorBeingModified() { return mHandle != null && mHandle.isDragging(); } @Override public boolean isActive() { return mHandle != null && mHandle.isShowing(); } } class SelectionModifierCursorController implements CursorController { Loading Loading @@ -5040,9 +5062,7 @@ public class Editor { if (mStartOffset != offset) { // Start character based drag accelerator. if (mTextActionMode != null) { mTextActionMode.finish(); } stopTextActionMode(); enterDrag(DRAG_ACCELERATOR_MODE_CHARACTER); mDiscardNextActionUp = true; mHaventMovedEnoughToStartDrag = false; Loading Loading @@ -5116,9 +5136,7 @@ public class Editor { if (mInsertionActionModeRunnable != null) { mTextView.removeCallbacks(mInsertionActionModeRunnable); } if (mTextActionMode != null) { mTextActionMode.finish(); } stopTextActionMode(); if (!selectCurrentParagraph()) { return false; } Loading Loading @@ -5227,6 +5245,12 @@ public class Editor { mStartOffset = -1; mDragAcceleratorMode = DRAG_ACCELERATOR_MODE_INACTIVE; mSwitchedLines = false; final int selectionStart = mTextView.getSelectionStart(); final int selectionEnd = mTextView.getSelectionEnd(); if (selectionStart > selectionEnd) { Selection.setSelection((Spannable) mTextView.getText(), selectionEnd, selectionStart); } } /** Loading @@ -5236,6 +5260,12 @@ public class Editor { return mStartHandle != null && mStartHandle.isDragging(); } @Override public boolean isCursorBeingModified() { return isDragAcceleratorActive() || isSelectionStartDragged() || (mEndHandle != null && mEndHandle.isDragging()); } /** * @return true if the user is selecting text using the drag accelerator. */ Loading @@ -5257,6 +5287,11 @@ public class Editor { if (mStartHandle != null) mStartHandle.onDetached(); if (mEndHandle != null) mEndHandle.onDetached(); } @Override public boolean isActive() { return mStartHandle != null && mStartHandle.isShowing(); } } private class CorrectionHighlighter { Loading
core/java/android/widget/TextView.java +18 −39 Original line number Diff line number Diff line Loading @@ -1511,6 +1511,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (result != null) { if (isTextEditable()) { replaceSelectionWithText(result); if (mEditor != null) { mEditor.refreshTextActionMode(); } } else { if (result.length() > 0) { Toast.makeText(getContext(), String.valueOf(result), Toast.LENGTH_LONG) Loading @@ -1520,12 +1523,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } else if (mText instanceof Spannable) { // Reset the selection. stopTextActionMode(); Selection.setSelection((Spannable) mText, getSelectionStart(), getSelectionEnd()); } if (mEditor.hasSelectionController()) { mEditor.startSelectionActionMode(); Selection.setSelection((Spannable) mText, getSelectionEnd()); } } } Loading Loading @@ -5393,11 +5391,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // - onFocusChanged cannot start it when focus is given to a view with selected text (after // a screen rotation) since layout is not yet initialized at that point. if (mEditor != null && mEditor.mCreatedWithASelection) { if (mEditor.extractedTextModeWillBeStarted()) { mEditor.checkFieldAndSelectCurrentWord(); } else { mEditor.startSelectionActionMode(); } mEditor.refreshTextActionMode(); mEditor.mCreatedWithASelection = false; } Loading Loading @@ -6594,6 +6588,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // in the extracted view. mEditor.hideCursorAndSpanControllers(); stopTextActionMode(); if (mEditor.mSelectionModifierCursorController != null) { mEditor.mSelectionModifierCursorController.resetTouchOffsets(); } } /** Loading Loading @@ -8289,6 +8286,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (newSelEnd < 0) { newSelEnd = Selection.getSelectionEnd(buf); } if (mEditor != null) { mEditor.refreshTextActionMode(); } onSelectionChanged(newSelStart, newSelEnd); } } Loading Loading @@ -9199,10 +9199,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (start >= 0 && start <= end && end <= text.length()) { Selection.setSelection((Spannable) text, start, end); // Make sure selection mode is engaged. if (mEditor != null) { mEditor.startSelectionActionMode(); } return true; } } Loading Loading @@ -9393,16 +9389,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (id) { case ID_SELECT_ALL: // This starts an action mode if triggered from another action mode. Text is // highlighted, so that it can be bulk edited, like selectAllOnFocus does. Returns // true even if text is empty. boolean shouldRestartActionMode = mEditor != null && mEditor.mTextActionMode != null; stopTextActionMode(); selectAllText(); if (shouldRestartActionMode) { mEditor.startSelectionActionMode(); } return true; case ID_UNDO: Loading @@ -9428,7 +9415,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case ID_CUT: setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max))); deleteText_internal(min, max); stopTextActionMode(); return true; case ID_COPY: Loading Loading @@ -9684,12 +9670,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } boolean selectAllText() { // Need to hide insert point cursor controller before settings selection, otherwise insert // point cursor controller obtains cursor update event and update cursor with cancelling // selection. if (mEditor != null) { mEditor.hideInsertionPointCursorController(); } final int length = mText.length(); Selection.setSelection((Spannable) mText, 0, length); return length > 0; Loading Loading @@ -9728,7 +9708,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } } stopTextActionMode(); sLastCutCopyOrTextChangedTime = 0; } } Loading @@ -9741,7 +9720,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT); sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText); getContext().startActivity(Intent.createChooser(sharingIntent, null)); stopTextActionMode(); Selection.setSelection((Spannable) mText, getSelectionEnd()); } } Loading Loading @@ -10059,6 +10038,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener && getAccessibilitySelectionEnd() == end) { return; } CharSequence text = getIterableTextForAccessibility(); if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) { Selection.setSelection((Spannable) text, start, end); } else { Selection.removeSelection((Spannable) text); } // Hide all selection controllers used for adjusting selection // since we are doing so explicitlty by other means and these // controllers interact with how selection behaves. Loading @@ -10066,12 +10051,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mEditor.hideCursorAndSpanControllers(); mEditor.stopTextActionMode(); } CharSequence text = getIterableTextForAccessibility(); if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) { Selection.setSelection((Spannable) text, start, end); } else { Selection.removeSelection((Spannable) text); } } /** @hide */ Loading