使用Linkify.addLinks与Html.fromHtml结合使用

时间:2013-01-26 14:57:57

标签: java android html linkify

我有TextView通过调用它来获取数据集:

tv.setText(Html.fromHtml(myText));

字符串myText包含部​​分格式化的html数据。例如,它可能包含字体标记,但没有使用<a href=...>标记格式化的任何网址链接。我希望使用Linkify.addLinks(...)来做到这一点,因为我的文本可以包含Linkify将为我适当转换的其他类型的链接。所以我写了我的代码看起来像这样:

String myText = "<font color=\"red\">Red text</font> and Url: www.google.com";
tv.setText(Html.fromHtml(myText));
Linkify.addLinks(tv, Linkify.ALL);
tv.setMovementMethod(LinkMovementMethod.getInstance());

这不能正常工作。这意味着它处理字体标记但Linkify不会正确地将网址转换为UrlSpan

或者,如果我在没有Html.fromHtml(..)的情况下调用setText(),Linkify可以正常工作但是我丢失了所有从html字体标签格式化的文本。不知怎的,他们似乎都是冲突的,我只能有一个或另一个。

现在这里是我不理解的有趣部分。如果我从java中删除Linkify代码并转到我的布局xml并在其中放入以下行,所有似乎都在工作(Linkify和fromHtml最终都在一起玩得很好......不知何故)

<TextView
    ... 
    android:autoLink="all"
    android:linksClickable="true"
    ...
/>

有人可以向我解释为什么会让一切都有效吗?

我查看了TextView的setMovementMethod()的源代码,最终最终调用:

setFocusable(true);
setClickable(true);
setLongClickable(true);

理论上,这应该使一切工作和行为与xml布局代码相同。我尝试在java代码中切换Linkify.addLinks(..)之前调用setText(Html.fromHtml(..))的顺序,但这并没有什么区别。

关于为什么在java中组合Linkify.addLinks()和Html.fromHtml()会导致此行为的任何想法......但不在xml布局中?

3 个答案:

答案 0 :(得分:13)

这是因为Html.fromHtmlLinkify.addLinks在处理文本之前删除了之前的跨度。

使用此代码使其正常工作:

public static Spannable linkifyHtml(String html, int linkifyMask) {
    Spanned text = Html.fromHtml(html);
    URLSpan[] currentSpans = text.getSpans(0, text.length(), URLSpan.class);

    SpannableString buffer = new SpannableString(text);
    Linkify.addLinks(buffer, linkifyMask);

    for (URLSpan span : currentSpans) {
        int end = text.getSpanEnd(span);
        int start = text.getSpanStart(span);
        buffer.setSpan(span, start, end, 0);
    }
    return buffer;
}

答案 1 :(得分:0)

你可以尝试这个:

首先将文本设置为TextView。

tv.setText(myText);

使用Linkify转换链接

Linkify.addLinks(tv, Linkify.ALL);

最后用Html.fromHtml替换文本,但使用EditText中的Linkified文本。

tv.setText(Html.fromHtml(tv.getText().toString()));

答案 2 :(得分:0)

100%工作解决方案(kotlin)。

在Linkify之前为商店HtmlLink创建类

class HtmlLink(val urlSpan: URLSpan, val spanStart: Int, val spanEnd: Int)

创建跨区html(两种格式以供测试)

val spanned = Html.fromHtml("https://google.com" +
                "<br><a href=\"https://google.com\">Google</a>")

存储html

val htmlLinks = ArrayList<HtmlLink>()
spanned.getSpans(0, spanned.length, URLSpan::class.java).forEach { urlSpan ->
    htmlLinks.add(HtmlLink(urlSpan, 
                  spanned.getSpanStart(urlSpan),
                  spanned.getSpanEnd(urlSpan)))
}

创建spannable构建器并将其链接

val builder = SpannableString(spanned)
Linkify.addLinks(builder, Linkify.WEB_URLS)

恢复范围。

htmlLinks.forEach { htmlLink ->
    builder.setSpan(URLSpan(htmlLink.urlSpan.url), htmlLink.spanStart, htmlLink.spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}

设置最终文本

scrollContent.text = builder