diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 012352d0a0f53..7517b805da69d 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3790,7 +3790,7 @@ public class Editor { } public SuggestionsPopupWindow() { - mCursorWasVisibleBeforeSuggestions = mCursorVisible; + mCursorWasVisibleBeforeSuggestions = mTextView.isCursorVisibleFromAttr(); } @Override @@ -3957,7 +3957,7 @@ public class Editor { } if (updateSuggestions()) { - mCursorWasVisibleBeforeSuggestions = mCursorVisible; + mCursorWasVisibleBeforeSuggestions = mTextView.isCursorVisibleFromAttr(); mTextView.setCursorVisible(false); mIsShowingUp = true; super.show(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 0f2089a5463f7..66d7463cf267d 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -500,7 +500,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mImeIsConsumingInput; // Whether cursor is visible without regard to {@link mImeConsumesInput}. - // {code true} is the default value. + // {@code true} is the default value. private boolean mCursorVisibleFromAttr = true; static class Drawables { @@ -10564,6 +10564,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mEditor == null ? true : mEditor.mCursorVisible; } + /** + * @return whether cursor is visible without regard to {@code mImeIsConsumingInput}. + * {@code true} is the default value. + * + * @see #setCursorVisible(boolean) + * @hide + */ + public boolean isCursorVisibleFromAttr() { + return mCursorVisibleFromAttr; + } + private boolean canMarquee() { int width = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(); return width > 0 && (mLayout.getLineWidth(0) > width diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java index f6e02bc1f48ae..28f9ccc101350 100644 --- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java +++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java @@ -41,7 +41,9 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import android.content.res.TypedArray; import android.text.Selection; @@ -356,4 +358,71 @@ public class SuggestionsPopupWindowTest { .perform(clearText()); } } + + @Test + public void testCursorVisibility() { + final TextView textView = getActivity().findViewById(R.id.textview); + final String text = "abc"; + + assertTrue(textView.isCursorVisible()); + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"ABC"}, SuggestionSpan.FLAG_AUTO_CORRECTION); + setSuggestionSpan(suggestionSpan, text.indexOf('a'), text.indexOf('c') + 1); + showSuggestionsPopup(); + + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("ABC"); + assertFalse(textView.isCursorVisible()); + + // Delete an item. + clickSuggestionsPopupItem( + getActivity().getString(com.android.internal.R.string.delete)); + assertSuggestionsPopupIsNotDisplayed(); + assertTrue(textView.isCursorVisible()); + } + + @Test + public void testCursorVisibilityWhenImeConsumesInput() { + final TextView textView = getActivity().findViewById(R.id.textview); + final String text = "abc"; + + assertTrue(textView.isCursorVisible()); + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + setImeConsumesInputWithExpect(textView, true /* imeConsumesInput */, + false /* expectedCursorVisibility */); + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"ABC"}, SuggestionSpan.FLAG_AUTO_CORRECTION); + setSuggestionSpan(suggestionSpan, text.indexOf('a'), text.indexOf('c') + 1); + showSuggestionsPopup(); + + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("ABC"); + assertFalse(textView.isCursorVisible()); + + // Delete an item. + clickSuggestionsPopupItem( + getActivity().getString(com.android.internal.R.string.delete)); + assertSuggestionsPopupIsNotDisplayed(); + assertFalse(textView.isCursorVisible()); + + // Set IME not consumes input, cursor should be back to visible. + setImeConsumesInputWithExpect(textView, false /* imeConsumesInput */, + true /* expectedCursorVisibility */); + } + + private void setImeConsumesInputWithExpect( + final TextView textView, boolean imeConsumesInput, boolean expectedCursorVisibility) { + textView.post(() -> textView.setImeConsumesInput(imeConsumesInput)); + getInstrumentation().waitForIdleSync(); + if (expectedCursorVisibility) { + assertTrue(textView.isCursorVisible()); + } else { + assertFalse(textView.isCursorVisible()); + } + } }