@@ -297,6 +297,9 @@ class InputMethodState {
297297 Drawable mSelectHandleRight ;
298298 Drawable mSelectHandleCenter ;
299299
300+ // Set when this TextView gained focus with some text selected. Will start selection mode.
301+ private boolean mCreatedWithASelection = false ;
302+
300303 /*
301304 * Kick-start the font cache for the zygote process (to pay the cost of
302305 * initializing freetype for our default font only once).
@@ -3758,8 +3761,10 @@ public boolean onPreDraw() {
37583761 // - ExtractEditText does not call onFocus when it is displayed. Fixing this issue would
37593762 // allow to test for hasSelection in onFocusChanged, which would trigger a
37603763 // startTextSelectionMode here. TODO
3761- if (this instanceof ExtractEditText && selectionController != null && hasSelection ()) {
3764+ if (mCreatedWithASelection ||
3765+ (this instanceof ExtractEditText && selectionController != null && hasSelection ())) {
37623766 startTextSelectionMode ();
3767+ mCreatedWithASelection = false ;
37633768 }
37643769
37653770 mPreDrawState = PREDRAW_DONE ;
@@ -4175,6 +4180,7 @@ protected void updateCursorControllerPositions() {
41754180 mInsertionPointCursorController .isShowing ()) {
41764181 mInsertionPointCursorController .updatePosition ();
41774182 }
4183+
41784184 if (mSelectionModifierCursorController != null &&
41794185 mSelectionModifierCursorController .isShowing ()) {
41804186 mSelectionModifierCursorController .updatePosition ();
@@ -6580,6 +6586,12 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc
65806586 int selStart = getSelectionStart ();
65816587 int selEnd = getSelectionEnd ();
65826588
6589+ // SelectAllOnFocus fields are highlighted and not selected. Do not start text selection
6590+ // mode for these, unless there was a specific selection already started.
6591+ final boolean isFocusHighlighted = mSelectAllOnFocus && selStart == 0 &&
6592+ selEnd == mText .length ();
6593+ mCreatedWithASelection = mFrozenWithFocus && hasSelection () && !isFocusHighlighted ;
6594+
65836595 if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0 )) {
65846596 // If a tap was used to give focus to that view, move cursor at tap position.
65856597 // Has to be done before onTakeFocus, which can be overloaded.
@@ -6592,10 +6604,6 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc
65926604 mMovement .onTakeFocus (this , (Spannable ) mText , direction );
65936605 }
65946606
6595- if (mSelectAllOnFocus ) {
6596- Selection .setSelection ((Spannable ) mText , 0 , mText .length ());
6597- }
6598-
65996607 // The DecorView does not have focus when the 'Done' ExtractEditText button is
66006608 // pressed. Since it is the ViewRoot's mView, it requests focus before
66016609 // ExtractEditText clears focus, which gives focus to the ExtractEditText.
@@ -6614,6 +6622,11 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc
66146622 */
66156623 Selection .setSelection ((Spannable ) mText , selStart , selEnd );
66166624 }
6625+
6626+ if (mSelectAllOnFocus ) {
6627+ Selection .setSelection ((Spannable ) mText , 0 , mText .length ());
6628+ }
6629+
66176630 mTouchFocusSelected = true ;
66186631 }
66196632
@@ -6643,7 +6656,7 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc
66436656 // ExtractEditText goes out of focus.
66446657 mIsInTextSelectionMode = false ;
66456658 } else {
6646- terminateTextSelectionMode ();
6659+ stopTextSelectionMode ();
66476660 }
66486661
66496662 if (mSelectionModifierCursorController != null ) {
@@ -6745,29 +6758,23 @@ private void onTapUpEvent(int prevStart, int prevEnd) {
67456758 final int end = getSelectionEnd ();
67466759
67476760 if (start == end ) {
6748- if (start >= prevStart && start < prevEnd ) {
6761+ boolean tapInsideSelectAllOnFocus = mSelectAllOnFocus && prevStart == 0 &&
6762+ prevEnd == mText .length ();
6763+ if (start >= prevStart && start < prevEnd && !tapInsideSelectAllOnFocus ) {
67496764 // Restore previous selection
67506765 Selection .setSelection ((Spannable )mText , prevStart , prevEnd );
67516766
6752- if (hasSelectionController () && !getSelectionController ().isShowing ()) {
6753- // If the anchors aren't showing, revive them.
6754- getSelectionController ().show ();
6755- } else {
6756- // Tapping inside the selection displays the cut/copy/paste context menu
6757- // as long as the anchors are already showing.
6758- showContextMenu ();
6759- }
6760- return ;
6767+ // Tapping inside the selection displays the cut/copy/paste context menu
6768+ showContextMenu ();
67616769 } else {
67626770 // Tapping outside stops selection mode, if any
67636771 stopTextSelectionMode ();
67646772
6765- if (hasInsertionController () && mText .length () > 0 ) {
6773+ boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected ;
6774+ if (hasInsertionController () && !selectAllGotFocus ) {
67666775 getInsertionController ().show ();
67676776 }
67686777 }
6769- } else if (hasSelection () && hasSelectionController ()) {
6770- getSelectionController ().show ();
67716778 }
67726779 }
67736780
@@ -6790,7 +6797,8 @@ protected void onReceiveResult(int resultCode, Bundle resultData) {
67906797 int end = Math .min (len , mPrevEnd );
67916798 Selection .setSelection ((Spannable )mText , start , end );
67926799
6793- if (hasSelection ()) {
6800+ boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected ;
6801+ if (hasSelection () && !selectAllGotFocus ) {
67946802 startTextSelectionMode ();
67956803 }
67966804 }
@@ -7147,7 +7155,7 @@ public boolean onKeyShortcut(int keyCode, KeyEvent event) {
71477155 }
71487156
71497157 private boolean canSelectText () {
7150- return textCanBeSelected () && mText .length () != 0 ;
7158+ return hasSelectionController () && mText .length () != 0 ;
71517159 }
71527160
71537161 private boolean textCanBeSelected () {
@@ -7317,7 +7325,7 @@ private void selectCurrentWord() {
73177325 }
73187326
73197327 int selectionStart , selectionEnd ;
7320-
7328+
73217329 long wordLimits = getWordLimitsAt (minOffset );
73227330 if (wordLimits >= 0 ) {
73237331 selectionStart = extractRangeStartFromLong (wordLimits );
@@ -7476,6 +7484,7 @@ protected void onCreateContextMenu(ContextMenu menu) {
74767484 }
74777485
74787486 if (added ) {
7487+ hideControllers ();
74797488 menu .setHeaderTitle (com .android .internal .R .string .editTextMenuTitle );
74807489 }
74817490 }
@@ -7652,29 +7661,18 @@ private void startTextSelectionMode() {
76527661 return ;
76537662 }
76547663
7655- if (!requestFocus ()) {
7664+ if (!canSelectText () || ! requestFocus ()) {
76567665 return ;
76577666 }
76587667
76597668 selectCurrentWord ();
7669+ getSelectionController ().show ();
7670+ final InputMethodManager imm = (InputMethodManager )
7671+ getContext ().getSystemService (Context .INPUT_METHOD_SERVICE );
7672+ imm .showSoftInput (this , 0 , null );
76607673 mIsInTextSelectionMode = true ;
76617674 }
76627675 }
7663-
7664- /**
7665- * Same as {@link #stopTextSelectionMode()}, except that there is no cursor controller
7666- * fade out animation. Needed since the drawable and their alpha values are shared by all
7667- * TextViews. Switching from one TextView to another would fade the cursor controllers in the
7668- * new one otherwise.
7669- */
7670- private void terminateTextSelectionMode () {
7671- stopTextSelectionMode ();
7672- if (mSelectionModifierCursorController != null ) {
7673- SelectionModifierCursorController selectionModifierCursorController =
7674- (SelectionModifierCursorController ) mSelectionModifierCursorController ;
7675- selectionModifierCursorController .cancelFadeOutAnimation ();
7676- }
7677- }
76787676
76797677 private void stopTextSelectionMode () {
76807678 if (mIsInTextSelectionMode ) {
@@ -8052,14 +8050,6 @@ private class SelectionModifierCursorController implements CursorController {
80528050 // Whether selection anchors are active
80538051 private boolean mIsShowing ;
80548052
8055- private static final int DELAY_BEFORE_FADE_OUT = 4100 ;
8056-
8057- private final Runnable mHider = new Runnable () {
8058- public void run () {
8059- hide ();
8060- }
8061- };
8062-
80638053 SelectionModifierCursorController () {
80648054 mStartHandle = new HandleView (this , HandleView .LEFT );
80658055 mEndHandle = new HandleView (this , HandleView .RIGHT );
@@ -8076,29 +8066,18 @@ public void show() {
80768066 mStartHandle .show ();
80778067 mEndHandle .show ();
80788068 hideInsertionPointCursorController ();
8079- hideDelayed (DELAY_BEFORE_FADE_OUT );
80808069 }
80818070
80828071 public void hide () {
80838072 mStartHandle .hide ();
80848073 mEndHandle .hide ();
80858074 mIsShowing = false ;
8086- removeCallbacks (mHider );
8087- }
8088-
8089- private void hideDelayed (int delay ) {
8090- removeCallbacks (mHider );
8091- postDelayed (mHider , delay );
80928075 }
80938076
80948077 public boolean isShowing () {
80958078 return mIsShowing ;
80968079 }
80978080
8098- public void cancelFadeOutAnimation () {
8099- hide ();
8100- }
8101-
81028081 public void updatePosition (HandleView handle , int x , int y ) {
81038082 int selectionStart = getSelectionStart ();
81048083 int selectionEnd = getSelectionEnd ();
@@ -8150,7 +8129,6 @@ public void updatePosition() {
81508129
81518130 mStartHandle .positionAtCursor (selectionStart , true );
81528131 mEndHandle .positionAtCursor (selectionEnd , true );
8153- hideDelayed (DELAY_BEFORE_FADE_OUT );
81548132 }
81558133
81568134 public boolean onTouchEvent (MotionEvent event ) {
0 commit comments