diff options
| -rw-r--r-- | core/java/android/text/method/LinkMovementMethod.java | 99 | ||||
| -rw-r--r-- | core/java/android/view/textclassifier/TextLinks.java | 36 |
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) { |