Android: How to Use the HTML.Taghandler

Android: How to use the Html.TagHandler?

So, i finally figured it out by myself.

public class MyHtmlTagHandler implements TagHandler {

public void handleTag(boolean opening, String tag, Editable output,
XMLReader xmlReader) {
if(tag.equalsIgnoreCase("strike") || tag.equals("s")) {
processStrike(opening, output);
}
}

private void processStrike(boolean opening, Editable output) {
int len = output.length();
if(opening) {
output.setSpan(new StrikethroughSpan(), len, len, Spannable.SPAN_MARK_MARK);
} else {
Object obj = getLast(output, StrikethroughSpan.class);
int where = output.getSpanStart(obj);

output.removeSpan(obj);

if (where != len) {
output.setSpan(new StrikethroughSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}

private Object getLast(Editable text, Class kind) {
Object[] objs = text.getSpans(0, text.length(), kind);

if (objs.length == 0) {
return null;
} else {
for(int i = objs.length;i>0;i--) {
if(text.getSpanFlags(objs[i-1]) == Spannable.SPAN_MARK_MARK) {
return objs[i-1];
}
}
return null;
}
}


}

And for your TextView you can call this like:

myTextView.setText (Html.fromHtml(text.toString(), null, new MyHtmlTagHandler()));

if anybody needs it.

Cheers

Html Tag Handler not called in Android N for ul , li

It is evident from the source of Html.java that, TagHandler.handleTag() is called only if the framework doesn't process it, itself.

Currently, the framework doesn't seem to process it well.
Android N li tag handling

But even if it did it well, you would want to customize it anyway. The best way to deal with this is to replace the default ul, li tags with your own tags. Since the framework won't process your custom tags, your TagHandler will be asked to handle it.

public static String customizeListTags(@Nullable String html) {
if (html == null) {
return null;
}
html = html.replace("<ul", "<" + UL);
html = html.replace("</ul>", "</" + UL + ">");
html = html.replace("<ol", "<" + OL);
html = html.replace("</ol>", "</" + OL + ">");
html = html.replace("<dd", "<" + DD);
html = html.replace("</dd>", "</" + DD + ">");
html = html.replace("<li", "<" + LI);
html = html.replace("</li>", "</" + LI + ">");
return html;
}

And then you can process your html string like

html = customizeListTags(html);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(html,Html.FROM_HTML_MODE_LEGACY, null, new CustomTagHandler());
} else {
//noinspection deprecation
result = Html.fromHtml(html, null, new CustomTagHandler());
}

How to use XMLReader in TagHandler.handleTag(...)

The XMLReader is actually only an interface, and the methods it defines can be read from the API documentation.

The ContentHandler that's used to handle the SAX events in the Html class is known as Html.HtmlToSpannedConverter, which, in turn, uses its private handleStartTag(String,Attributes) method to handle the starting tags of HTML elements. Thus the list of out-of-the-box supported elements seems to be br, p, div, em, b, strong, cite, dfn, i, big, small, font, blockquote, tt, a, u, sup, sub, h1...h6 and img. Finally, if the tag is not recognized, the TagHandler given as a parameter to the HtmlToSpannedConverter is used, if it's not null.

The idea of a SAX handler is that you only get events from it: here's a start tag, here's a CDATA block, here's an end tag, etc etc. The other way of handling an XML document is by using a DocumentBuilder to create a Document object of it. SAX parsers are used when you might have a large input stream which might not fit well into the memory, when you need to parse a document quickly or when you are receiving data from somewhere and want to parse it on the fly, before you have received all of it. Thus it is not possible to jump back and forth in an XML stream when using a SAX handler. So, to summarize an answer to your question "Is it possible to get all <li> data for <ul>": no, unfortunately not.

In your TagHandler you will probably want to emit a linebreak when you encounter a opening "ul" tag, then a "•" when you enter an opening "li" tag, and again linebreaks when you encounter a closing "li" or "ul" tag.

If you need to support nested lists, you could add a counter to your TagHandler so that it increments each time you encounter an opening "ul" and decrements when a closing "ul" is encountered. Then you can add different amounts of indentation for the bullet points based on the counter of nested lists.

Another way would be to create a stack of elements by adding an element to it when encountering an opening tag and removing it when encountering a closing tag. By going through the stack it would be easy to count the number of ancestor "ul" elements at any given time.

Html List tag not working in android textview. What can I do?

As you can see in the Html class source code, Html.fromHtml(String) does not support all HTML tags. In this very case, <ul> and <li> are not supported.

From the source code I have built a list of allowed HTML tags:

  • br
  • p
  • div
  • em
  • b
  • strong
  • cite
  • dfn
  • i
  • big
  • small
  • font
  • blockquote
  • tt
  • monospace
  • a
  • u
  • sup
  • sub

So you better use WebView and its loadDataWithBaseURL method. Try something like this:

String str="<html><body>A dressy take on classic gingham in a soft, textured weave of stripes that resembles twill.  Take a closer look at this one.<ul><li>Trim, tailored fit for a bespoke feel</li><li>Medium spread collar, one-button mitered barrel cuffs</li><li>Applied placket with genuine mother-of-pearl buttons</li><li>;Split back yoke, rear side pleats</li><li>Made in the U.S.A. of 100% imported cotton.</li></ul></body></html>";
webView.loadDataWithBaseURL(null, str, "text/html", "utf-8", null);


Related Topics



Leave a reply



Submit