Chrome 自定义标签和文本视图
Chrome custom tabs and textview
我有一个文本视图,里面有一个 link。在代码中,当用户单击文本时,我调用 setMovementMethod
来打开 link。但它会在默认浏览器或浏览器选择器中打开它。
如何将 chrome 自定义标签与可点击的文本视图一起使用?
这是因为 TextView
为每个 link 文本模式创建了 URLSpan
,即 ClickableSpan
。一旦 MovementMethod
找到 url,它就会调用 URLSpan
的 onClick
方法。此事件启动 ACTION_VIEW
意图,这就是为什么您会看到默认浏览器启动的原因。
您可以编写自己的 URLSpan
实现,您可以在其中覆盖 onClick 方法并从那里启动 CustomTabs
服务。
首先创建将覆盖 onClick
方法的自定义 URLSpan
:
public class CustomTabsURLSpan extends URLSpan {
public CustomTabsURLSpan(String url) {
super(url);
}
public CustomTabsURLSpan(Parcel src) {
super(src);
}
@Override
public void onClick(View widget) {
String url = getUrl();
//attempt to open in CustomTabs, if that fails call super.onClick(widget);
}
}
创建自定义转换方法,将跨度设置为 links:
public class LinkTransformationMethod implements TransformationMethod {
@Override
public CharSequence getTransformation(CharSequence source, View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
Linkify.addLinks(textView, Linkify.WEB_URLS);
String stringText = textView.getText().toString();
Spannable text = (Spannable) textView.getText();
URLSpan[] spans = text.getSpans(0, textView.length(), URLSpan.class);
for (int i = spans.length - 1; i >= 0; i--) {
URLSpan oldSpan = spans[i];
text.removeSpan(oldSpan);
String url = oldSpan.getURL();
int startIndex = stringText.indexOf(url);
int lastIndex = startIndex + url.length();
text.setSpan(new CustomTabsURLSpan(url), startIndex, lastIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return text;
}
return source;
}
@Override
public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect) {
}
}
下面是快速解释:https://medium.com/@nullthemall/make-textview-open-links-in-customtabs-12fdcf4bb684#.ig1chpbbe
我对 Nikola 的回答做了一些改动,因此它仍然适用于其他 linkify 选项。
我添加了 Patterns.WEB_URL.matcher()
和一个构造函数来设置您想要的链接选项。
用法:
textView.setTransformationMethod(new LinkTransformationMethod(Linkify.WEB_URLS |
Linkify.EMAIL_ADDRESSES |
Linkify.PHONE_NUMBERS));
完整的 class 本身:
public class LinkTransformationMethod implements TransformationMethod {
private final int linkifyOptions;
public LinkTransformationMethod(int linkifyOptions) {
this.linkifyOptions = linkifyOptions;
}
@Override
public CharSequence getTransformation(CharSequence source, View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
Linkify.addLinks(textView, linkifyOptions);
if (textView.getText() == null || !(textView.getText() instanceof Spannable)) {
return source;
}
Spannable text = (Spannable) textView.getText();
URLSpan[] spans = text.getSpans(0, textView.length(), URLSpan.class);
for (int i = spans.length - 1; i >= 0; i--) {
URLSpan oldSpan = spans[i];
int start = text.getSpanStart(oldSpan);
int end = text.getSpanEnd(oldSpan);
String url = oldSpan.getURL();
if (!Patterns.WEB_URL.matcher(url).matches()) {
continue;
}
text.removeSpan(oldSpan);
text.setSpan(new ChromeTabsUrlSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return text;
}
return source;
}
@Override
public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect) {
}
}
我有一个文本视图,里面有一个 link。在代码中,当用户单击文本时,我调用 setMovementMethod
来打开 link。但它会在默认浏览器或浏览器选择器中打开它。
如何将 chrome 自定义标签与可点击的文本视图一起使用?
这是因为 TextView
为每个 link 文本模式创建了 URLSpan
,即 ClickableSpan
。一旦 MovementMethod
找到 url,它就会调用 URLSpan
的 onClick
方法。此事件启动 ACTION_VIEW
意图,这就是为什么您会看到默认浏览器启动的原因。
您可以编写自己的 URLSpan
实现,您可以在其中覆盖 onClick 方法并从那里启动 CustomTabs
服务。
首先创建将覆盖 onClick
方法的自定义 URLSpan
:
public class CustomTabsURLSpan extends URLSpan {
public CustomTabsURLSpan(String url) {
super(url);
}
public CustomTabsURLSpan(Parcel src) {
super(src);
}
@Override
public void onClick(View widget) {
String url = getUrl();
//attempt to open in CustomTabs, if that fails call super.onClick(widget);
}
}
创建自定义转换方法,将跨度设置为 links:
public class LinkTransformationMethod implements TransformationMethod {
@Override
public CharSequence getTransformation(CharSequence source, View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
Linkify.addLinks(textView, Linkify.WEB_URLS);
String stringText = textView.getText().toString();
Spannable text = (Spannable) textView.getText();
URLSpan[] spans = text.getSpans(0, textView.length(), URLSpan.class);
for (int i = spans.length - 1; i >= 0; i--) {
URLSpan oldSpan = spans[i];
text.removeSpan(oldSpan);
String url = oldSpan.getURL();
int startIndex = stringText.indexOf(url);
int lastIndex = startIndex + url.length();
text.setSpan(new CustomTabsURLSpan(url), startIndex, lastIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return text;
}
return source;
}
@Override
public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect) {
}
}
下面是快速解释:https://medium.com/@nullthemall/make-textview-open-links-in-customtabs-12fdcf4bb684#.ig1chpbbe
我对 Nikola 的回答做了一些改动,因此它仍然适用于其他 linkify 选项。
我添加了 Patterns.WEB_URL.matcher()
和一个构造函数来设置您想要的链接选项。
用法:
textView.setTransformationMethod(new LinkTransformationMethod(Linkify.WEB_URLS |
Linkify.EMAIL_ADDRESSES |
Linkify.PHONE_NUMBERS));
完整的 class 本身:
public class LinkTransformationMethod implements TransformationMethod {
private final int linkifyOptions;
public LinkTransformationMethod(int linkifyOptions) {
this.linkifyOptions = linkifyOptions;
}
@Override
public CharSequence getTransformation(CharSequence source, View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
Linkify.addLinks(textView, linkifyOptions);
if (textView.getText() == null || !(textView.getText() instanceof Spannable)) {
return source;
}
Spannable text = (Spannable) textView.getText();
URLSpan[] spans = text.getSpans(0, textView.length(), URLSpan.class);
for (int i = spans.length - 1; i >= 0; i--) {
URLSpan oldSpan = spans[i];
int start = text.getSpanStart(oldSpan);
int end = text.getSpanEnd(oldSpan);
String url = oldSpan.getURL();
if (!Patterns.WEB_URL.matcher(url).matches()) {
continue;
}
text.removeSpan(oldSpan);
text.setSpan(new ChromeTabsUrlSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return text;
}
return source;
}
@Override
public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect) {
}
}