11

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

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

该字符串myText包含部分格式化的 html 数据。例如,它可能有字体标签,但没有任何使用<a href=...>标签格式化的 url 链接。我希望使用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正确转换 url。

或者,如果我在没有 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 布局中?

4

3 回答 3

21

这是因为在处理文本Html.fromHtml之前Linkify.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;
}
于 2013-06-19T21:08:10.637 回答
2

You can try this one:

First set the text in to your TextView.

tv.setText(myText);

Convert the links with Linkify

Linkify.addLinks(tv, Linkify.ALL);

and finally replace the text with Html.fromHtml but using the Linkified text from your EditText.

tv.setText(Html.fromHtml(tv.getText().toString()));
于 2015-04-24T15:21:17.303 回答
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)))
}

创建可跨越的构建器并链接它

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
于 2018-06-11T12:46:16.063 回答