Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7fc4fbcc authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "Automatic persistent text selection for ListViews" into jb-dev

parents 0ae107ff 057a585f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;
+42 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -151,6 +156,8 @@ public class Editor {

    boolean mInBatchEditControllers;
    boolean mShowSoftInputOnFocus = true;
    boolean mPreserveDetachedSelection;
    boolean mTemporaryDetach;

    SuggestionsPopupWindow mSuggestionsPopupWindow;
    SuggestionRangeSpan mSuggestionRangeSpan;
@@ -190,6 +197,7 @@ public class Editor {
            showError();
            mShowErrorAfterAttach = false;
        }
        mTemporaryDetach = false;

        final ViewTreeObserver observer = mTextView.getViewTreeObserver();
        // No need to create the controller.
@@ -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() {
@@ -234,7 +254,10 @@ public class Editor {
            mSpellChecker = null;
        }

        mPreserveDetachedSelection = true;
        hideControllers();
        mPreserveDetachedSelection = false;
        mTemporaryDetach = false;
    }

    private void showError() {
@@ -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();
            }

@@ -2679,6 +2704,7 @@ public class Editor {

            if (menu.hasVisibleItems() || mode.getCustomView() != null) {
                getSelectionController().show();
                mTextView.setHasTransientState(true);
                return true;
            } else {
                return false;
@@ -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();
+4 −4
Original line number Diff line number Diff line
@@ -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
@@ -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