Loading core/java/android/view/View.java +1 −1 Original line number Diff line number Diff line Loading @@ -5584,7 +5584,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal "unmatched pair of setHasTransientState calls"); } if ((hasTransientState && mTransientStateCount == 1) || (hasTransientState && mTransientStateCount == 0)) { (!hasTransientState && mTransientStateCount == 0)) { // update flag if we've just incremented up from 0 or decremented down to 0 mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) | (hasTransientState ? HAS_TRANSIENT_STATE : 0); Loading core/java/android/widget/AbsListView.java +1 −0 Original line number Diff line number Diff line Loading @@ -6317,6 +6317,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (mTransientStateViews == null) { mTransientStateViews = new SparseArray<View>(); } scrap.dispatchStartTemporaryDetach(); mTransientStateViews.put(position, scrap); } return; Loading core/java/android/widget/Editor.java +42 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.widget; import com.android.internal.util.ArrayUtils; import com.android.internal.widget.EditableInputConnection; import android.R; import android.content.ClipData; import android.content.ClipData.Item; Loading Loading @@ -70,10 +73,10 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.View.DragShadowBuilder; import android.view.View.OnClickListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; import android.view.ViewTreeObserver; Loading @@ -85,12 +88,12 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView.OnItemClickListener; import android.widget.Editor.InputContentType; import android.widget.Editor.InputMethodState; import android.widget.Editor.SelectionModifierCursorController; import android.widget.TextView.Drawables; import android.widget.TextView.OnEditorActionListener; import com.android.internal.util.ArrayUtils; import com.android.internal.widget.EditableInputConnection; import java.text.BreakIterator; import java.util.Arrays; import java.util.Comparator; Loading @@ -102,6 +105,8 @@ import java.util.HashMap; * @hide */ public class Editor { private static final String TAG = "Editor"; static final int BLINK = 500; private static final float[] TEMP_POSITION = new float[2]; private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20; Loading Loading @@ -151,6 +156,8 @@ public class Editor { boolean mInBatchEditControllers; boolean mShowSoftInputOnFocus = true; boolean mPreserveDetachedSelection; boolean mTemporaryDetach; SuggestionsPopupWindow mSuggestionsPopupWindow; SuggestionRangeSpan mSuggestionRangeSpan; Loading Loading @@ -190,6 +197,7 @@ public class Editor { showError(); mShowErrorAfterAttach = false; } mTemporaryDetach = false; final ViewTreeObserver observer = mTextView.getViewTreeObserver(); // No need to create the controller. Loading @@ -198,10 +206,22 @@ public class Editor { observer.addOnTouchModeChangeListener(mInsertionPointCursorController); } if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.resetTouchOffsets(); observer.addOnTouchModeChangeListener(mSelectionModifierCursorController); } updateSpellCheckSpans(0, mTextView.getText().length(), true /* create the spell checker if needed */); if (mTextView.hasTransientState() && mTextView.getSelectionStart() != mTextView.getSelectionEnd()) { // Since transient state is reference counted make sure it stays matched // with our own calls to it for managing selection. // The action mode callback will set this back again when/if the action mode starts. mTextView.setHasTransientState(false); // We had an active selection from before, start the selection mode. startSelectionActionMode(); } } void onDetachedFromWindow() { Loading Loading @@ -234,7 +254,10 @@ public class Editor { mSpellChecker = null; } mPreserveDetachedSelection = true; hideControllers(); mPreserveDetachedSelection = false; mTemporaryDetach = false; } private void showError() { Loading Loading @@ -877,7 +900,9 @@ public class Editor { hideControllers(); Selection.setSelection((Spannable) mTextView.getText(), selStart, selEnd); } else { if (mTemporaryDetach) mPreserveDetachedSelection = true; hideControllers(); if (mTemporaryDetach) mPreserveDetachedSelection = false; downgradeEasyCorrectionSpans(); } Loading Loading @@ -2679,6 +2704,7 @@ public class Editor { if (menu.hasVisibleItems() || mode.getCustomView() != null) { getSelectionController().show(); mTextView.setHasTransientState(true); return true; } else { return false; Loading Loading @@ -2707,7 +2733,17 @@ public class Editor { if (mCustomSelectionActionModeCallback != null) { mCustomSelectionActionModeCallback.onDestroyActionMode(mode); } Selection.setSelection((Spannable) mTextView.getText(), mTextView.getSelectionEnd()); /* * If we're ending this mode because we're detaching from a window, * we still have selection state to preserve. Don't clear it, we'll * bring back the selection mode when (if) we get reattached. */ if (!mPreserveDetachedSelection) { Selection.setSelection((Spannable) mTextView.getText(), mTextView.getSelectionEnd()); mTextView.setHasTransientState(false); } if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); Loading core/java/android/widget/TextView.java +4 −4 Original line number Diff line number Diff line Loading @@ -7257,10 +7257,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // usually because this instance is an editable field in a list if (!mDispatchTemporaryDetach) mTemporaryDetach = true; // Because of View recycling in ListView, there is no easy way to know when a TextView with // selection becomes visible again. Until a better solution is found, stop text selection // mode (if any) as soon as this TextView is recycled. if (mEditor != null) mEditor.hideControllers(); // Tell the editor that we are temporarily detached. It can use this to preserve // selection state as needed. if (mEditor != null) mEditor.mTemporaryDetach = true; } @Override Loading @@ -7269,6 +7268,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Only track when onStartTemporaryDetach() is called directly, // usually because this instance is an editable field in a list if (!mDispatchTemporaryDetach) mTemporaryDetach = false; if (mEditor != null) mEditor.mTemporaryDetach = false; } @Override Loading Loading
core/java/android/view/View.java +1 −1 Original line number Diff line number Diff line Loading @@ -5584,7 +5584,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal "unmatched pair of setHasTransientState calls"); } if ((hasTransientState && mTransientStateCount == 1) || (hasTransientState && mTransientStateCount == 0)) { (!hasTransientState && mTransientStateCount == 0)) { // update flag if we've just incremented up from 0 or decremented down to 0 mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) | (hasTransientState ? HAS_TRANSIENT_STATE : 0); Loading
core/java/android/widget/AbsListView.java +1 −0 Original line number Diff line number Diff line Loading @@ -6317,6 +6317,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (mTransientStateViews == null) { mTransientStateViews = new SparseArray<View>(); } scrap.dispatchStartTemporaryDetach(); mTransientStateViews.put(position, scrap); } return; Loading
core/java/android/widget/Editor.java +42 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.widget; import com.android.internal.util.ArrayUtils; import com.android.internal.widget.EditableInputConnection; import android.R; import android.content.ClipData; import android.content.ClipData.Item; Loading Loading @@ -70,10 +73,10 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.View.DragShadowBuilder; import android.view.View.OnClickListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; import android.view.ViewTreeObserver; Loading @@ -85,12 +88,12 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView.OnItemClickListener; import android.widget.Editor.InputContentType; import android.widget.Editor.InputMethodState; import android.widget.Editor.SelectionModifierCursorController; import android.widget.TextView.Drawables; import android.widget.TextView.OnEditorActionListener; import com.android.internal.util.ArrayUtils; import com.android.internal.widget.EditableInputConnection; import java.text.BreakIterator; import java.util.Arrays; import java.util.Comparator; Loading @@ -102,6 +105,8 @@ import java.util.HashMap; * @hide */ public class Editor { private static final String TAG = "Editor"; static final int BLINK = 500; private static final float[] TEMP_POSITION = new float[2]; private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20; Loading Loading @@ -151,6 +156,8 @@ public class Editor { boolean mInBatchEditControllers; boolean mShowSoftInputOnFocus = true; boolean mPreserveDetachedSelection; boolean mTemporaryDetach; SuggestionsPopupWindow mSuggestionsPopupWindow; SuggestionRangeSpan mSuggestionRangeSpan; Loading Loading @@ -190,6 +197,7 @@ public class Editor { showError(); mShowErrorAfterAttach = false; } mTemporaryDetach = false; final ViewTreeObserver observer = mTextView.getViewTreeObserver(); // No need to create the controller. Loading @@ -198,10 +206,22 @@ public class Editor { observer.addOnTouchModeChangeListener(mInsertionPointCursorController); } if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.resetTouchOffsets(); observer.addOnTouchModeChangeListener(mSelectionModifierCursorController); } updateSpellCheckSpans(0, mTextView.getText().length(), true /* create the spell checker if needed */); if (mTextView.hasTransientState() && mTextView.getSelectionStart() != mTextView.getSelectionEnd()) { // Since transient state is reference counted make sure it stays matched // with our own calls to it for managing selection. // The action mode callback will set this back again when/if the action mode starts. mTextView.setHasTransientState(false); // We had an active selection from before, start the selection mode. startSelectionActionMode(); } } void onDetachedFromWindow() { Loading Loading @@ -234,7 +254,10 @@ public class Editor { mSpellChecker = null; } mPreserveDetachedSelection = true; hideControllers(); mPreserveDetachedSelection = false; mTemporaryDetach = false; } private void showError() { Loading Loading @@ -877,7 +900,9 @@ public class Editor { hideControllers(); Selection.setSelection((Spannable) mTextView.getText(), selStart, selEnd); } else { if (mTemporaryDetach) mPreserveDetachedSelection = true; hideControllers(); if (mTemporaryDetach) mPreserveDetachedSelection = false; downgradeEasyCorrectionSpans(); } Loading Loading @@ -2679,6 +2704,7 @@ public class Editor { if (menu.hasVisibleItems() || mode.getCustomView() != null) { getSelectionController().show(); mTextView.setHasTransientState(true); return true; } else { return false; Loading Loading @@ -2707,7 +2733,17 @@ public class Editor { if (mCustomSelectionActionModeCallback != null) { mCustomSelectionActionModeCallback.onDestroyActionMode(mode); } Selection.setSelection((Spannable) mTextView.getText(), mTextView.getSelectionEnd()); /* * If we're ending this mode because we're detaching from a window, * we still have selection state to preserve. Don't clear it, we'll * bring back the selection mode when (if) we get reattached. */ if (!mPreserveDetachedSelection) { Selection.setSelection((Spannable) mTextView.getText(), mTextView.getSelectionEnd()); mTextView.setHasTransientState(false); } if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); Loading
core/java/android/widget/TextView.java +4 −4 Original line number Diff line number Diff line Loading @@ -7257,10 +7257,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // usually because this instance is an editable field in a list if (!mDispatchTemporaryDetach) mTemporaryDetach = true; // Because of View recycling in ListView, there is no easy way to know when a TextView with // selection becomes visible again. Until a better solution is found, stop text selection // mode (if any) as soon as this TextView is recycled. if (mEditor != null) mEditor.hideControllers(); // Tell the editor that we are temporarily detached. It can use this to preserve // selection state as needed. if (mEditor != null) mEditor.mTemporaryDetach = true; } @Override Loading @@ -7269,6 +7268,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Only track when onStartTemporaryDetach() is called directly, // usually because this instance is an editable field in a list if (!mDispatchTemporaryDetach) mTemporaryDetach = false; if (mEditor != null) mEditor.mTemporaryDetach = false; } @Override Loading