Chrome自定义标签页和文本视图

bpzcxfmw  于 12个月前  发布在  Go
关注(0)|答案(3)|浏览(103)

我有一个文本视图,里面有一个链接。在代码中,我调用setMovementMethod来在用户单击文本时打开链接。但它会在默认浏览器或浏览器选择器中打开它。
如何使用Chrome自定义标签页和可点击的文本视图?

mwg9r5ms

mwg9r5ms1#

这是因为TextView为每个链接文本模式创建URLSpan,即ClickableSpan。一旦MovementMethod找到url,它就会调用URLSpanonClick方法。此事件启动ACTION_VIEW Intent,这就是为什么您会看到默认浏览器启动。
您可以做的是编写自己的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#.ig1chpbbe

9cbw7uwe

9cbw7uwe2#

我已经改变了尼古拉的答案,所以它仍然适用于其他linkify选项。
我添加了Patterns.WEB_URL.matcher()和一个构造函数来设置你想要的linkify选项。
使用方法:

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) {

    }
}
f45qwnt8

f45qwnt83#

下面是一个基于Nikola答案的Kotlin变体。我还在Chrome自定义选项卡中添加了URL处理:

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?
    ) {}
}

相关问题