Пользовательские вкладки Chrome и просмотр текста
У меня есть текстовое представление со ссылкой внутри. В коде я называю setMovementMethod
открыть ссылку, когда пользователь нажимает на текст. Но он открывает его в браузере по умолчанию или в браузере.
Как использовать пользовательские вкладки Chrome с интерактивным просмотром текста?
3 ответа
Это потому что TextView
создает URLSpan
который ClickableSpan
для каждого шаблона текста ссылки. Однажды MovementMethod
находит URL это звонки onClick
метод URLSpan
, Это событие начинает ACTION_VIEW
намерение, поэтому вы видите, что браузер по умолчанию запускается вместо этого.
Что вы можете сделать, это написать свою собственную реализацию URLSpan
где вы переопределите метод onClick и запустите CustomTabs
сервис оттуда.
Сначала создайте кастом URLSpan
это переопределит onClick
метод:
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);
}
}
Создайте собственный метод преобразования, который установит интервалы для ссылок:
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
Я немного изменил ответ Никола, чтобы он все еще работал и для других опций линковки.
я добавил Patterns.WEB_URL.matcher()
и конструктор, чтобы установить, какие параметры ссылок вы хотите.
Использование:
textView.setTransformationMethod(new LinkTransformationMethod(Linkify.WEB_URLS |
Linkify.EMAIL_ADDRESSES |
Linkify.PHONE_NUMBERS));
Сам полный класс:
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) {
}
}
Вот вариант Котлина, основанный на ответе Николы. Я также позволил себе добавить обработку URL-адресов в пользовательской вкладке Chrome:
import android.graphics.Rect
import android.net.Uri
import android.os.Parcel
import android.text.Spannable
import android.text.Spanned
import android.text.method.TransformationMethod
import android.text.style.URLSpan
import android.text.util.Linkify
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.browser.customtabs.CustomTabsIntent
class LinkTransformationMethod : TransformationMethod {
private val TAG = LinkTransformationMethod::class.java.simpleName
inner class CustomTabsURLSpan : URLSpan {
constructor(url: String?) : super(url)
constructor(src: Parcel?) : super(src!!)
override fun onClick(widget: View) {
try {
CustomTabsIntent.Builder()
.build()
.launchUrl(widget.context, Uri.parse(url))
} catch (exception: Exception) {
Log.e(TAG, "Failed to open link in custom tab!", exception)
super.onClick(widget)
}
}
}
override fun getTransformation(source: CharSequence?, view: View?): CharSequence? {
if (view is TextView) {
Linkify.addLinks(view, Linkify.WEB_URLS)
if (view.text == null || view.text !is Spannable) {
return source
}
val text = view.text as Spannable
val spans = text.getSpans(0, view.length(), URLSpan::class.java)
spans.indices.reversed().forEach {
val oldSpan = spans[it]
val start = text.getSpanStart(oldSpan)
val end = text.getSpanEnd(oldSpan)
val url = oldSpan.url
text.removeSpan(oldSpan)
text.setSpan(CustomTabsURLSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return text
}
return source
}
override fun onFocusChanged(
view: View?,
sourceText: CharSequence?,
focused: Boolean,
direction: Int,
previouslyFocusedRect: Rect?
) {}
}