Make Linkify links clickable in nonselectable text.
Test: bit FrameworksCoreTests:android.widget.TextViewActivityTest\#testToolbarAppearsAfterLinkClickedNonselectable
Bug: b/67629726
Change-Id: I94452116453fff1a36f5d567b3a686e92e97a34f
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 05d18d1..bddba07 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2095,14 +2095,7 @@
if (!(mTextView.getText() instanceof Spannable)) {
return;
}
- Spannable text = (Spannable) mTextView.getText();
stopTextActionMode();
- if (mTextView.isTextSelectable()) {
- Selection.setSelection((Spannable) text, link.getStart(), link.getEnd());
- } else {
- //TODO: Nonselectable text
- }
-
getSelectionActionModeHelper().startLinkActionModeAsync(link);
}
@@ -2179,7 +2172,8 @@
return false;
}
- if (!checkField() || !mTextView.hasSelection()) {
+ if (actionMode != TextActionMode.TEXT_LINK
+ && (!checkField() || !mTextView.hasSelection())) {
return false;
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 2c6466c..3bfa520 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -235,10 +235,13 @@
@Editor.TextActionMode int actionMode, @Nullable SelectionResult result) {
final CharSequence text = getText(mTextView);
if (result != null && text instanceof Spannable
- && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
+ && (mTextView.isTextSelectable()
+ || mTextView.isTextEditable()
+ || actionMode == Editor.TextActionMode.TEXT_LINK)) {
// Do not change the selection if TextClassifier should be dark launched.
if (!mTextView.getTextClassifier().getSettings().isDarkLaunch()) {
Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
+ mTextView.invalidate();
}
mTextClassification = result.mClassification;
} else {
@@ -250,8 +253,17 @@
&& (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
controller.show();
}
- if (result != null && actionMode == Editor.TextActionMode.SELECTION) {
- mSelectionTracker.onSmartSelection(result);
+ if (result != null) {
+ switch (actionMode) {
+ case Editor.TextActionMode.SELECTION:
+ mSelectionTracker.onSmartSelection(result);
+ break;
+ case Editor.TextActionMode.TEXT_LINK:
+ mSelectionTracker.onLinkSelected(result);
+ break;
+ default:
+ break;
+ }
}
}
mEditor.setRestartActionModeOnNextRefresh(false);
@@ -486,12 +498,24 @@
* Called when selection action mode is started and the results come from a classifier.
*/
public void onSmartSelection(SelectionResult result) {
+ onClassifiedSelection(result);
+ mLogger.logSelectionModified(
+ result.mStart, result.mEnd, result.mClassification, result.mSelection);
+ }
+
+ /**
+ * Called when link action mode is started and the classification comes from a classifier.
+ */
+ public void onLinkSelected(SelectionResult result) {
+ onClassifiedSelection(result);
+ // TODO: log (b/70246800)
+ }
+
+ private void onClassifiedSelection(SelectionResult result) {
if (isSelectionStarted()) {
mSelectionStart = result.mStart;
mSelectionEnd = result.mEnd;
mAllowReset = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
- mLogger.logSelectionModified(
- result.mStart, result.mEnd, result.mClassification, result.mSelection);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1e17f34..18933fe 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11164,11 +11164,9 @@
*/
public boolean requestActionMode(@NonNull TextLinks.TextLink link) {
Preconditions.checkNotNull(link);
- if (mEditor != null) {
- mEditor.startLinkActionModeAsync(link);
- return true;
- }
- return false;
+ createEditorIfNeeded();
+ mEditor.startLinkActionModeAsync(link);
+ return true;
}
/**
* @hide
diff --git a/core/tests/coretests/res/layout/activity_text_view.xml b/core/tests/coretests/res/layout/activity_text_view.xml
index e795c10..dca1656 100644
--- a/core/tests/coretests/res/layout/activity_text_view.xml
+++ b/core/tests/coretests/res/layout/activity_text_view.xml
@@ -25,4 +25,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/nonselectable_textview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
</LinearLayout>
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 1a654f4..bbca12f 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -311,11 +311,20 @@
@Test
public void testToolbarAppearsAfterLinkClicked() throws Throwable {
+ runToolbarAppearsAfterLinkClickedTest(R.id.textview);
+ }
+
+ @Test
+ public void testToolbarAppearsAfterLinkClickedNonselectable() throws Throwable {
+ runToolbarAppearsAfterLinkClickedTest(R.id.nonselectable_textview);
+ }
+
+ private void runToolbarAppearsAfterLinkClickedTest(int id) throws Throwable {
+ TextView textView = mActivity.findViewById(id);
useSystemDefaultTextClassifier();
TextClassificationManager textClassificationManager =
mActivity.getSystemService(TextClassificationManager.class);
TextClassifier textClassifier = textClassificationManager.getTextClassifier();
- final TextView textView = mActivity.findViewById(R.id.textview);
SpannableString content = new SpannableString("Call me at +19148277737");
TextLinks links = textClassifier.generateLinks(content);
links.apply(content, null);
@@ -331,7 +340,7 @@
TextLinks.TextLink textLink = links.getLinks().iterator().next();
int position = (textLink.getStart() + textLink.getEnd()) / 2;
- onView(withId(R.id.textview)).perform(clickOnTextAtIndex(position));
+ onView(withId(id)).perform(clickOnTextAtIndex(position));
sleepForFloatingToolbarPopup();
assertFloatingToolbarIsDisplayed();
}