HTML List Tag funktioniert nicht in Android Textansicht. Was kann ich tun?

99

HTML List Tag funktioniert nicht in Android TextView. Dies ist mein String-Inhalt:

String str="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>";

Ich habe es in einer Textansicht wie folgt geladen:

textview.setText(Html.fromHtml(str));

Die Ausgabe sieht aus wie ein Absatz. Was kann ich tun? Gibt es eine Lösung dafür?

Bearbeiten:

webview.loadData(str,"text/html","utf-8");
Praveen
quelle
1
Sollte text / html sein, nicht texl / html.
Chloe

Antworten:

156

Wie Sie in der sehen HtmlKlasse Quellcode , Html.fromHtml(String)unterstützt nicht alle HTML - Tags. In diesem Fall <ul>und <li>werden nicht unterstützt.

Aus dem Quellcode habe ich eine Liste der zulässigen HTML-Tags erstellt:

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

Also besser nutzen WebViewund seine loadDataWithBaseURLMethode. Versuchen Sie so etwas:

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);
Cristian
quelle
Was kann ich dann tun, um das Problem zu beheben?
Praveen
2
Es ist sehr wichtig zu beachten, dass einige Attribute dieser "erlaubten" Tags ebenfalls nicht unterstützt werden. : = (
Jorgesys
2
Beruhige dich ... Ich habe meine Antwort bearbeitet, bitte lass mich wissen, ob es funktioniert.
Cristian
6
Sie können ein WebView nicht auf die gleiche Weise verwenden, daher ist dies keine Lösung für das Problem.
Brill Pappin
11
Wie ist das eine Lösung? Sie können nicht einfach ein WebView verwenden, es ist ein sehr teures Widget im Vergleich zu einem TextView. Sie können nicht einfach eine WebView für jeden formatierten Text verwenden, den Sie haben.
SpaceMonkey
135

Ich habe das gleiche Problem. Ich habe den Standard- TagHandler überschrieben . Dieser hat für mich gearbeitet.

public class MyTagHandler implements TagHandler {

    boolean first = true;
    String parent = null;
    int index = 1;
    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {

        if (tag.equals("ul")) {
            parent = "ul";
        } else if (tag.equals("ol")) {
            parent = "ol";
        }

        if (tag.equals("li")) {
            if (parent.equals("ul")) {
                if (first) {
                    output.append("\n\t•");
                    first = false;
                } else {
                    first = true;
                }
            } else{
                if (first) {
                    output.append("\n\t"+index+". ");
                    first = false;
                    index++;
                } else {
                    first = true;
                }
            }   
        }
    }
}

und zum Anzeigen des Textes ...

myTextView.setText(Html.fromHtml("<ul><li>I am an Android developer</li><li>Another Item</li></ul>", null, new MyTagHandler()));

[Bearbeiten]

Kuitsi hat auch eine wirklich gute Bibliothek gepostet , die das Gleiche tut und diese über diesen SO-Link erhalten hat .

Aman Gautam
quelle
Wir haben diesen Ansatz am Ende verwendet. Nicht unterstützte HTML-Tags werden von uns selbst in Text codiert. Im Moment ist es nur ol und ul, aber wir haben Stapel hinzugefügt, um das Verschachteln von Listen und das Speichern von Indizes beim Verschachteln von ol zu handhaben. Zusätzlich können Sie den öffnenden booleschen Parameter als Ersatz für first verwenden.
JonWillis
6
@Aman Gautam sehr genial danke dafür! Haben Sie eine Idee, wie Sie den Text mit Tabulatoren versehen können, wenn er mehr als eine Zeile umschließt? Mit diesem Code nach der 2. Zeile wird der Text an der Nummer ausgerichtet und nicht mit Registerkarten versehen, um die Nummer getrennt zu halten. Ich habe ein paar Dinge versucht, aber ich konnte es nicht herausfinden
RyanG
Das Gleiche gilt für Zeilenumbrüche in einer Liste, die bei diesem Ansatz zu Problemen führen.
Andreas Rudolph
Anstatt das eingefügte Aufzählungszeichen zu verwenden, ist es möglicherweise besser, das Unicode-Zeichen zu verwenden: output.append ("\ n \ t \ u2022");
Matt McMinn
Vielen Dank für diesen netten Code, aber ich kann ihn nicht verwenden, bis wir eine Lösung finden, wie die
mehrzeilige
68

Das vollständige Beispielprojekt finden Sie unter https://bitbucket.org/Kuitsi/android-textview-html-list .
Ein Beispielbild finden Sie unter https://kuitsi.bitbucket.io/stackoverflow3150400_screen.png

Diese Lösung kommt der Antwort von Mascha am nächsten . Ein Teil des Codes stammt auch aus der inneren Klasse android.text.Html.HtmlToSpannedConverter. Es unterstützt verschachtelte geordnete und ungeordnete Listen, aber zu lange Texte in geordneten Listen werden weiterhin an der Artikelnummer und nicht am Text ausgerichtet. Gemischte Listen (ol und ul) benötigen ebenfalls einige Arbeit. Das Beispielprojekt enthält die Implementierung von Html.TagHandler, die an Html.fromHtml (String, ImageGetter, TagHandler) übergeben wird .

Bearbeiten: Für eine umfassendere Unterstützung von HTML-Tags ist möglicherweise auch https://github.com/NightWhistler/HtmlSpanner einen Versuch wert.

Kuitsi
quelle
Bisher die beste Lösung. Vielen Dank
Peter.bartos
Keine Problemverfolgung in BitBucket Repo, also hier output.length() > 0if (output.length() > 0 && output.charAt(output.length() - 1) != '\n')
posten
2
Um zu vermeiden, dass andere Personen 2 Stunden damit verschwenden, entfernt NightWhistler HtmlSpanner alle Zeichen mit Akzent aus unbekannten Gründen.
EpicPandaForce
@Kuitsi danke für die Lösung. Es gibt ein Problem: Wenn der HTML-Text "<ul> <li> etwas </ li> </ ul>" lautet, wird der letzte Buchstabe in "etwas" nicht in der Liste angezeigt.
Sam Berg
Dies ist eine sehr gute Lösung, ABER zwei Nachteile: 1) Es unterstützt kein Android ≥ 7 und 2) Es wird kein Starteinzug für die erste Ebene der Liste gesetzt.
Soshial
24

Eine kleine Korrektur des Aman Guatam-Codes. Die obige Funktion hat ein Problem beim Rendern von Zeilenumbrüchen. Beispiel: Wenn vor dem <li>Tag ein <p>Tag ist, werden 2 Zeilenumbruchzeichen gerendert. Hier ist aktualisierter Code:

import org.xml.sax.XMLReader;

import android.text.Editable;
import android.text.Html.TagHandler;

public class ListTagHandler implements TagHandler {
    boolean first = true;

    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {

        // TODO Auto-generated method stub
        if (tag.equals("li")) {
            char lastChar = 0;
            if (output.length() > 0)
                lastChar = output.charAt(output.length() - 1);
            if (first) {
                if (lastChar == '\n')
                    output.append("\t•  ");
                else
                    output.append("\n\t•  ");
                first = false;
            } else {
                first = true;
            }
        }
    }
}
Truong Nguyen
quelle
Einfach und doch effektiv
steven0529
Was ist mit der bestellten Liste?
Android-Entwickler
13

WARNUNG

Ab dem 10. Februar 2016 werden android.text.Htmltatsächlich grundlegende Funktionen unterstützt liund ulmarkiert und verwendet. Dies new BulletSpan()bedeutet, dass in den neuesten Versionen von Android die hier veröffentlichten Html.TagHandlerLösungen ignoriert werden

Stellen Sie sicher, dass Ihr Code diese Änderung behandelt, falls Sie ein BulletSpan mit einer größeren Lücke als der Standardeinstellung erwarten. Sie müssen über eine Lösung verfügen, die das Suchen / Ersetzen der Bereiche ermöglicht

kassim
quelle
4
Diese neue HTML-Klasse ist jedoch nur in Android Nund höher verfügbar .
Sakiboy
1
Ja - Sie müssen also berücksichtigen, dass sich verschiedene Betriebssystemversionen unterschiedlich verhalten. Daher empfehle ich eine Lösung, die BulletSpan findet und ersetzt, nachdem der HTML-Code in verschiedene Bereiche analysiert wurde. Bei der Standardimplementierung von Versionen nach N wird ein Standardrand verwendet. Sie können diesen finden und durch den gewünschten Rand ersetzen.
Kassim
Immer auf dem Laufenden bleiben.
Kai Wang
9

Andere Lösung mit LeadingMarginSpan. Behandelt geordnete und ungeordnete Listen sowie das Verschachteln.

public class ListTagHandler implements TagHandler
{
    private int                 m_index     = 0;
    private List< String >  m_parents   = new ArrayList< String >( );

    @Override
    public void handleTag( final boolean opening, final String tag, Editable output,    final XMLReader xmlReader )
    {
        if( tag.equals( "ul" ) || tag.equals( "ol" ) || tag.equals( "dd" ) )
        {
            if( opening )
            {
                m_parents.add( tag );
            }
            else m_parents.remove( tag );

            m_index = 0;
        }
        else if( tag.equals( "li" ) && !opening ) handleListTag( output );
    }

    private void handleListTag( Editable output )
    {
        if( m_parents.get(m_parents.size()-1 ).equals( "ul" ) )
        {
            output.append( "\n" );
            String[ ] split = output.toString( ).split( "\n" );

            int lastIndex = split.length - 1;
            int start = output.length( ) - split[ lastIndex ].length( ) - 1;
            output.setSpan( new BulletSpan( 15 * m_parents.size( ) ), start, output.length( ), 0 );
        }
        else if( m_parents.get(m_parents.size()-1).equals( "ol" ) )
        {
            m_index++ ;

            output.append( "\n" );
            String[ ] split = output.toString( ).split( "\n" );

            int lastIndex = split.length - 1;
            int start = output.length( ) - split[ lastIndex ].length( ) - 1;
            output.insert( start, m_index + ". " );
            output.setSpan( new LeadingMarginSpan.Standard( 15 * m_parents.size( ) ), start, output.length( ), 0 );
        }
    }
}
Mascha
quelle
5
Ich mag die Idee, Spans zu verwenden, aber ich kann keine verschachtelte Liste mit diesem Code erhalten. Beide Linien output.setSpan(...)java.lang.RuntimeException: PARAGRAPH span must start at paragraph boundary
stürzen
Danke für die schöne Lösung! Es werden auch
mehrzeilige
2
Warum verwenden Sie einen Vektor anstelle einer einfachen ArrayList? Ein Vektor ist für Multi-Threads ...
Android-Entwickler
@androiddeveloper c ++ Programmierer, mein schlechtes, zögern Sie nicht, die Antwort zu bearbeiten
Mascha
1
Ich habe als Snippet androidsnippets.com/…
Pratik Butani
8

Wenn Sie nur eine Liste formatieren müssen, halten Sie sie einfach und kopieren Sie ein Unicode-Zeichen in Ihre Textansicht, um das gleiche Ergebnis zu erzielen.

• Unicode-Zeichen 'BULLET' (U + 2022)

Naku
quelle
6

Ich bin hierher gekommen, um nach TagHandler-Implementierungen zu suchen. Die Antworten von Truong Nguyen und Aman Guatam sind sehr nett, aber ich brauchte eine gemischte Version von beiden: Ich brauchte meine Lösung, um sie nicht zu überformatieren und <ol>Tags neu auflösen zu können , da ich so etwas analysiere <h3>title</h3><ol><li>item</li><li>item</li><li>item</li></ol>.

Hier ist meine Lösung.

import org.xml.sax.XMLReader;

import android.text.Editable;
import android.text.Html.TagHandler;

public class MyTagHandler implements TagHandler {
    boolean first = true;
    String parent = null;
    int index = 1;

    public void handleTag(final boolean opening, final String tag,
            final Editable output, final XMLReader xmlReader) {

        if (tag.equals("ul")) {
            parent = "ul";
                    index = 1;
        } else if (tag.equals("ol")) {
            parent = "ol";
                    index = 1;
        }
        if (tag.equals("li")) {
            char lastChar = 0;
            if (output.length() > 0) {
                lastChar = output.charAt(output.length() - 1);
            }
            if (parent.equals("ul")) {
                if (first) {
                    if (lastChar == '\n') {
                        output.append("\t•  ");
                    } else {
                        output.append("\n\t•  ");
                    }
                    first = false;
                } else {
                    first = true;
                }
            } else {
                if (first) {
                    if (lastChar == '\n') {
                        output.append("\t" + index + ". ");
                    } else {
                        output.append("\n\t" + index + ". ");
                    }
                    first = false;
                    index++;
                } else {
                    first = true;
                }
            }
        }
    }
}

Da wir den Indexwert bei jedem Start einer neuen Liste zurücksetzen, funktioniert dies NICHT, wenn Sie Listen wie in verschachteln <ol><li>1<ol><li>1.1</li><li>1.2</li></ol><li>2</li></ol>

  1. 1
    1. 1.1
    2. 1.2
  2. 2

Mit diesem Code würden Sie 1, 1, 2, 3stattdessen bekommen 1, 1, 2, 2.

Charlie-Blake
quelle
Dieser Code funktioniert bis Version 23. Wie funktioniert er für 24 und höher?
Abhinav Tyagi
3

Sicher, es gibt eine Möglichkeit, Aufzählungszeichen in Android TextView anzuzeigen. Sie können <li>Tags durch ersetzen &#149;(dies ist HTML-Code für Aufzählungszeichen).

Wenn Sie andere Listensymbole ausprobieren möchten, verwenden Sie diesen Link aus der Tabelle.

http://www.ascii-code.com/

Taner
quelle
Hat bei mir nicht funktioniert. Stattdessen wird unter Android 7.1.1 und 6.0.1 anstelle des Aufzählungszeichens in der Textansicht ein Feld mit einem x angezeigt.
user1652110
3

Sie können das "li" einfach durch Unicodes ersetzen

    @Override
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {

    if (tag.equalsIgnoreCase("li")) {
        if (opening) {
            output.append("\u2022 ");
        } else {
            output.append("\n");
        }
    }
}
Blatt
quelle
2

Lord Voldermorts Antwort ist ein guter Ausgangspunkt. Ich benötigte jedoch ein olTag, um die geordnete Liste 1. 2. 3. ....anstelle von Aufzählungszeichen anzuzeigen . Außerdem benötigen verschachtelte Tags eine spezielle Behandlung, um ordnungsgemäß zu funktionieren.

In meinem Code habe ich beibehalten Stapel (parentList) Spur geöffnet und geschlossen zu halten ulund olTags und auch den aktuellen offenen Tag kennen. Außerdem wird a levelWiseCounterverwendet, um bei verschachtelten olTags unterschiedliche Zählwerte beizubehalten .

myTextView.setText(Html.fromHtml("your string", null, new CustomTagHandler()));

. . .

private static class CustomTagHandler implements TagHandler
   {
      int level = 0;
      private LinkedList<Tag> parentList = new LinkedList<DetailFragment.CustomTagHandler.Tag>();
      private HashMap<Integer, Integer> levelWiseCounter = new HashMap<Integer, Integer>();

      @Override
      public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader)
      {
         if (tag.equalsIgnoreCase("ul") || tag.equalsIgnoreCase("ol"))
         {
            if (opening)
            {
               if (tag.equalsIgnoreCase("ul"))
               {
                  parentList.push(Tag.UL);
               }
               else
               {
                  parentList.push(Tag.OL);
               }
               level++;
            }
            else
            {
               if (!parentList.isEmpty())
               {
                  parentList.pop();

                  //remove counter at that level, in any present.
                  levelWiseCounter.remove(level);
               }
               level--;
               if (level < 0)
               {
                  level = 0;
               }
            }
         }
         else if (tag.equalsIgnoreCase("li"))
         {
            if (opening && level > 0)
            {
               //new line check
               int length = output.toString().length();
               if (length > 0 && (output.toString().charAt(length - 1) == '\n'))
               {
               }
               else
               {
                  output.append("\n");
               }

               //add tabs as per current level of li
               for (int i = 0; i < level; i++)
               {
                  output.append("\t");
               }

               // append dot or numbers based on parent tag
               if (Tag.UL == parentList.peek())
               {
                  output.append("•");
               }
               else
               {
                  //parent is OL. Check current level and retreive counter from levelWiseCounter
                  int counter = 1;
                  if (levelWiseCounter.get(level) == null)
                  {
                     levelWiseCounter.put(level, 1);
                  }
                  else
                  {
                     counter = levelWiseCounter.get(level) + 1;
                     levelWiseCounter.put(level, counter);
                  }
                  output.append(padInt(counter) + ".");
               }

               //trailing tab
               output.append("\t");

            }
         }
      }

      /**
       * Add padding so that all numbers are aligned properly. Currently supports padding from 1-99.
       * 
       * @param num
       * @return
       */
      private static String padInt(int num)
      {
         if (num < 10)
         {
            return " " + num;
         }
         return "" + num;
      }

      private enum Tag
      {
         UL, OL
      }
   }
Kshitij
quelle
2

Wie wäre es mit dem nächsten Code (basierend auf diesem Link ):

public class TextViewHtmlTagHandler implements TagHandler
  {
  /**
   * Keeps track of lists (ol, ul). On bottom of Stack is the outermost list
   * and on top of Stack is the most nested list
   */
  Stack<String>                   lists          =new Stack<String>();
  /**
   * Tracks indexes of ordered lists so that after a nested list ends
   * we can continue with correct index of outer list
   */
  Stack<Integer>                  olNextIndex    =new Stack<Integer>();
  /**
   * List indentation in pixels. Nested lists use multiple of this.
   */
  private static final int        indent         =10;
  private static final int        listItemIndent =indent*2;
  private static final BulletSpan bullet         =new BulletSpan(indent);

  @Override
  public void handleTag(final boolean opening,final String tag,final Editable output,final XMLReader xmlReader)
    {
    if(tag.equalsIgnoreCase("ul"))
      {
      if(opening)
        lists.push(tag);
      else lists.pop();
      }
    else if(tag.equalsIgnoreCase("ol"))
      {
      if(opening)
        {
        lists.push(tag);
        olNextIndex.push(Integer.valueOf(1)).toString();// TODO: add support for lists starting other index than 1
        }
      else
        {
        lists.pop();
        olNextIndex.pop().toString();
        }
      }
    else if(tag.equalsIgnoreCase("li"))
      {
      if(opening)
        {
        if(output.length()>0&&output.charAt(output.length()-1)!='\n')
          output.append("\n");
        final String parentList=lists.peek();
        if(parentList.equalsIgnoreCase("ol"))
          {
          start(output,new Ol());
          output.append(olNextIndex.peek().toString()+". ");
          olNextIndex.push(Integer.valueOf(olNextIndex.pop().intValue()+1));
          }
        else if(parentList.equalsIgnoreCase("ul"))
          start(output,new Ul());
        }
      else if(lists.peek().equalsIgnoreCase("ul"))
        {
        if(output.charAt(output.length()-1)!='\n')
          output.append("\n");
        // Nested BulletSpans increases distance between bullet and text, so we must prevent it.
        int bulletMargin=indent;
        if(lists.size()>1)
          {
          bulletMargin=indent-bullet.getLeadingMargin(true);
          if(lists.size()>2)
            // This get's more complicated when we add a LeadingMarginSpan into the same line:
            // we have also counter it's effect to BulletSpan
            bulletMargin-=(lists.size()-2)*listItemIndent;
          }
        final BulletSpan newBullet=new BulletSpan(bulletMargin);
        end(output,Ul.class,new LeadingMarginSpan.Standard(listItemIndent*(lists.size()-1)),newBullet);
        }
      else if(lists.peek().equalsIgnoreCase("ol"))
        {
        if(output.charAt(output.length()-1)!='\n')
          output.append("\n");
        int numberMargin=listItemIndent*(lists.size()-1);
        if(lists.size()>2)
          // Same as in ordered lists: counter the effect of nested Spans
          numberMargin-=(lists.size()-2)*listItemIndent;
        end(output,Ol.class,new LeadingMarginSpan.Standard(numberMargin));
        }
      }
    else if(opening)
      Log.d("TagHandler","Found an unsupported tag "+tag);
    }

  private static void start(final Editable text,final Object mark)
    {
    final int len=text.length();
    text.setSpan(mark,len,len,Spanned.SPAN_MARK_MARK);
    }

  private static void end(final Editable text,final Class<?> kind,final Object... replaces)
    {
    final int len=text.length();
    final Object obj=getLast(text,kind);
    final int where=text.getSpanStart(obj);
    text.removeSpan(obj);
    if(where!=len)
      for(final Object replace : replaces)
        text.setSpan(replace,where,len,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    return;
    }

  private static Object getLast(final Spanned text,final Class<?> kind)
    {
    /*
     * This knows that the last returned object from getSpans()
     * will be the most recently added.
     */
    final Object[] objs=text.getSpans(0,text.length(),kind);
    if(objs.length==0)
      return null;
    return objs[objs.length-1];
    }

  private static class Ul
    {
    }

  private static class Ol
    {
    }
  }
Android-Entwickler
quelle
1
Diese Antwort hat nur eine geringfügig andere Formatierung als die ursprüngliche Quelle, die erstellt wurde, um eine andere Antwort auf dieselbe Frage zu unterstützen: stackoverflow.com/a/17365740/262462 :)
Kuitsi
wahr. habe das nicht bemerkt.
Android-Entwickler
2

Ich hatte das Problem, dass ich nach einer Liste mit @ Kuitsis-Lösung immer eine leere Zeile bekam. Ich habe ein paar Zeilen in handleTag () hinzugefügt und jetzt sind die leeren Zeilen weg:

@Override
public void handleTag(final boolean opening, final String tag, final Editable output, final XMLReader xmlReader) {
    if (UL_TAG.equalsIgnoreCase(tag)) {
        if (opening) {   // handle <ul>
            lists.push(new Ul());
        } else {   // handle </ul>
            lists.pop();
            if (output.length() > 0 && output.charAt(output.length() - 1) == '\n') {
                output.delete(output.length() - 1, output.length());
            }
        }
    } else if (OL_TAG.equalsIgnoreCase(tag)) {
        if (opening) {   // handle <ol>
            lists.push(new Ol()); // use default start index of 1
        } else {   // handle </ol>
            lists.pop();
            if (output.length() > 0 && output.charAt(output.length() - 1) == '\n') {
                output.delete(output.length() - 1, output.length());
            }
        }
    } else if (LI_TAG.equalsIgnoreCase(tag)) {
        if (opening) {   // handle <li>
            lists.peek().openItem(output);
        } else {   // handle </li>
            lists.peek().closeItem(output, lists.size());
        }
    } else {
        Log.d("TagHandler", "Found an unsupported tag " + tag);
    }
}
JensJensen
quelle
2

Sie können verwenden Html.TagHandler. Unten kann für Kotlin verwendet werden

    class UlTagHandler : Html.TagHandler {
    override fun handleTag(
        opening: Boolean, tag: String, output: Editable,
        xmlReader: XMLReader
    ) {
        if (tag == "ul" && !opening) output.append("\n")
        if (tag == "li" && opening) output.append("\n\t•")
    }
}

und

textView.setText(Html.fromHtml(myHtmlText, null, UlTagHandler()));
Shalu TD
quelle
0

Dies ist eine Bestätigung dessen, was Kasim gesagt hat. es gibt Fragmentierung. Ich fand, wie man das löst. Ich muss umbenennen <li>und ul zu einem benutzerdefinierten Tag. so:

myHTML.replaceAll("</ul>","</customTag>").replaceAll("<ul>","<customTag>");
//likewise for li

dann kann ich in meinem Handler nach diesem customTag suchen (der nichts tut) und ihn dazu bringen, etwas zu tun.

//now my handler can handle the customtags. it was ignoring them after nougat. 
 public class UlTagHandler implements Html.TagHandler {
        //for ul in nougat and up this tagHandler is completely ignored
        @Override
        public void handleTag(boolean opening, String tag, Editable output,
                              XMLReader xmlReader) {

            if (tag.equals("customtag2") && opening)
            output.append("\n\t\u25CF\t");
        if (tag.equals("customtag2") && !opening)
            output.append("\n");
        }
    }

Dies sollte es für alle Versionen von Android funktionieren.

j2emanue
quelle