summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/method/LinkMovementMethod.java99
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java36
2 files changed, 86 insertions, 49 deletions
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index e60377b46e7d..549f8b3953dd 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -25,6 +25,7 @@ import android.text.style.ClickableSpan;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.textclassifier.TextLinks.TextLinkSpan;
import android.widget.TextView;
/**
@@ -130,64 +131,70 @@ public class LinkMovementMethod extends ScrollingMovementMethod {
selStart = selEnd = -1;
switch (what) {
- case CLICK:
- if (selStart == selEnd) {
- return false;
- }
+ case CLICK:
+ if (selStart == selEnd) {
+ return false;
+ }
- ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);
+ ClickableSpan[] links = buffer.getSpans(selStart, selEnd, ClickableSpan.class);
- if (link.length != 1)
- return false;
+ if (links.length != 1) {
+ return false;
+ }
- link[0].onClick(widget);
- break;
+ ClickableSpan link = links[0];
+ if (link instanceof TextLinkSpan) {
+ ((TextLinkSpan) link).onClick(widget, TextLinkSpan.INVOCATION_METHOD_KEYBOARD);
+ } else {
+ link.onClick(widget);
+ }
+ break;
- case UP:
- int bestStart, bestEnd;
+ case UP:
+ int bestStart, bestEnd;
- bestStart = -1;
- bestEnd = -1;
+ bestStart = -1;
+ bestEnd = -1;
- for (int i = 0; i < candidates.length; i++) {
- int end = buffer.getSpanEnd(candidates[i]);
+ for (int i = 0; i < candidates.length; i++) {
+ int end = buffer.getSpanEnd(candidates[i]);
- if (end < selEnd || selStart == selEnd) {
- if (end > bestEnd) {
- bestStart = buffer.getSpanStart(candidates[i]);
- bestEnd = end;
+ if (end < selEnd || selStart == selEnd) {
+ if (end > bestEnd) {
+ bestStart = buffer.getSpanStart(candidates[i]);
+ bestEnd = end;
+ }
}
}
- }
- if (bestStart >= 0) {
- Selection.setSelection(buffer, bestEnd, bestStart);
- return true;
- }
+ if (bestStart >= 0) {
+ Selection.setSelection(buffer, bestEnd, bestStart);
+ return true;
+ }
- break;
+ break;
- case DOWN:
- bestStart = Integer.MAX_VALUE;
- bestEnd = Integer.MAX_VALUE;
+ case DOWN:
+ bestStart = Integer.MAX_VALUE;
+ bestEnd = Integer.MAX_VALUE;
- for (int i = 0; i < candidates.length; i++) {
- int start = buffer.getSpanStart(candidates[i]);
+ for (int i = 0; i < candidates.length; i++) {
+ int start = buffer.getSpanStart(candidates[i]);
- if (start > selStart || selStart == selEnd) {
- if (start < bestStart) {
- bestStart = start;
- bestEnd = buffer.getSpanEnd(candidates[i]);
+ if (start > selStart || selStart == selEnd) {
+ if (start < bestStart) {
+ bestStart = start;
+ bestEnd = buffer.getSpanEnd(candidates[i]);
+ }
}
}
- }
- if (bestEnd < Integer.MAX_VALUE) {
- Selection.setSelection(buffer, bestStart, bestEnd);
- return true;
- }
+ if (bestEnd < Integer.MAX_VALUE) {
+ Selection.setSelection(buffer, bestStart, bestEnd);
+ return true;
+ }
- break;
+ break;
}
return false;
@@ -215,8 +222,14 @@ public class LinkMovementMethod extends ScrollingMovementMethod {
ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);
if (links.length != 0) {
+ ClickableSpan link = links[0];
if (action == MotionEvent.ACTION_UP) {
- links[0].onClick(widget);
+ if (link instanceof TextLinkSpan) {
+ ((TextLinkSpan) link).onClick(
+ widget, TextLinkSpan.INVOCATION_METHOD_TOUCH);
+ } else {
+ link.onClick(widget);
+ }
} else if (action == MotionEvent.ACTION_DOWN) {
if (widget.getContext().getApplicationInfo().targetSdkVersion
>= Build.VERSION_CODES.P) {
@@ -225,8 +238,8 @@ public class LinkMovementMethod extends ScrollingMovementMethod {
widget.hideFloatingToolbar(HIDE_FLOATING_TOOLBAR_DELAY_MS);
}
Selection.setSelection(buffer,
- buffer.getSpanStart(links[0]),
- buffer.getSpanEnd(links[0]));
+ buffer.getSpanStart(link),
+ buffer.getSpanEnd(link));
}
return true;
} else {
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 851b2c9be29b..e7faf142c55d 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -503,6 +503,22 @@ public final class TextLinks implements Parcelable {
*/
public static class TextLinkSpan extends ClickableSpan {
+ /**
+ * How the clickspan is triggered.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({INVOCATION_METHOD_UNSPECIFIED, INVOCATION_METHOD_TOUCH,
+ INVOCATION_METHOD_KEYBOARD})
+ public @interface InvocationMethod {}
+
+ /** @hide */
+ public static final int INVOCATION_METHOD_UNSPECIFIED = -1;
+ /** @hide */
+ public static final int INVOCATION_METHOD_TOUCH = 0;
+ /** @hide */
+ public static final int INVOCATION_METHOD_KEYBOARD = 1;
+
private final TextLink mTextLink;
public TextLinkSpan(@NonNull TextLink textLink) {
@@ -511,16 +527,24 @@ public final class TextLinks implements Parcelable {
@Override
public void onClick(View widget) {
+ onClick(widget, INVOCATION_METHOD_UNSPECIFIED);
+ }
+
+ /** @hide */
+ public final void onClick(View widget, @InvocationMethod int invocationMethod) {
if (widget instanceof TextView) {
final TextView textView = (TextView) widget;
final Context context = textView.getContext();
if (TextClassificationManager.getSettings(context).isSmartLinkifyEnabled()) {
- if (textView.requestFocus()) {
- textView.requestActionMode(this);
- } else {
- // If textView can not take focus, then simply handle the click as it will
- // be difficult to get rid of the floating action mode.
- textView.handleClick(this);
+ switch (invocationMethod) {
+ case INVOCATION_METHOD_TOUCH:
+ textView.requestActionMode(this);
+ break;
+ case INVOCATION_METHOD_KEYBOARD:// fall though
+ case INVOCATION_METHOD_UNSPECIFIED: // fall through
+ default:
+ textView.handleClick(this);
+ break;
}
} else {
if (mTextLink.mUrlSpan != null) {