问题
I have a TextView
that gets it's data set by calling this:
tv.setText(Html.fromHtml(myText));
The string myText
contains partially formatted html data. For example, it might have font tags, but not have any url links formatted using <a href=...>
tags. I was hoping to use the Linkify.addLinks(...)
to do that since my text could include other types of links that Linkify would convert for me appropriately. So I wrote my code to look like this:
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());
This does not work properly. Meaning that it processes the font tags but Linkify does not convert urls to UrlSpan
properly.
Alternatively, if I call setText() without the Html.fromHtml(..), Linkify works but then I lose all the text formatted from the html font tags. Somehow they both seem to be conflicting and I can have only one or the other.
Now here's the interesting part that I dont understand. If I remove the Linkify code from java and go to my layout xml and put the following lines in there, all seems to be working (Linkify and fromHtml both end up playing nice together... somehow)
<TextView
...
android:autoLink="all"
android:linksClickable="true"
...
/>
Can someone explain to me why that would make everything work??
I looked into the source code for TextView's setMovementMethod()
and it eventually ends up calling:
setFocusable(true);
setClickable(true);
setLongClickable(true);
That should theoretically make everything work and behave the same as the xml layout code. I tried switching the order of calling Linkify.addLinks(..)
before setText(Html.fromHtml(..))
in the java code, but that didn't make a difference.
Any ideas as to why combining Linkify.addLinks() and Html.fromHtml() in java would cause this behavior... but not in the xml layout?
回答1:
It's because Html.fromHtml
and Linkify.addLinks
removes previous spans before processing the text.
Use this code to get it work:
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;
}
回答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()));
回答3:
100% works solution (kotlin).
Create class for store HtmlLink before Linkify
class HtmlLink(val urlSpan: URLSpan, val spanStart: Int, val spanEnd: Int)
Create spanned html (both formats for test)
val spanned = Html.fromHtml("https://google.com" +
"<br><a href=\"https://google.com\">Google</a>")
Store 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)))
}
Create spannable builder and Linkify it
val builder = SpannableString(spanned)
Linkify.addLinks(builder, Linkify.WEB_URLS)
Restore spans.
htmlLinks.forEach { htmlLink ->
builder.setSpan(URLSpan(htmlLink.urlSpan.url), htmlLink.spanStart, htmlLink.spanEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
Set finally text
scrollContent.text = builder
来源:https://stackoverflow.com/questions/14538113/using-linkify-addlinks-combine-with-html-fromhtml