Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Html List tag no funciona en android textview. ¿que puedo hacer?

Html List tag no funciona en Android TextView. Éste es mi contenido de la secuencia:

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 USA of 100% imported cotton.</li></ul>"; 

Lo cargué en una vista de texto como esta:

  • IInAppBillingService.aidl no puede generar archivos Java en Android Studio
  • Desactivación de la función de extracción de cromo de Android para actualizar
  • SYSTEM_UI_FLAG_LOW_PROFILE no funciona en HTC One M8
  • Cómo convertir una aplicación de swing java para trabajar en android
  • ¿Cómo hacer efecto de resplandor alrededor de un mapa de bits?
  • Android: ¿ver bases de datos SQLite en el dispositivo?
  •  textview.setText(Html.fromHtml(str)); 

    La salida se ve como un párrafo. ¿Que puedo hacer? ¿Hay alguna solución para ello?

    Editar:

     webview.loadData(str,"text/html","utf-8"); 

  • Tiempo de inactividad de la aplicación
  • Cómo detener un proceso de System.Diagnostics.Process y obtener las estadísticas al final
  • Definiendo textColor en TextView en el archivo de diseño principal de layout / main.xml que no hace referencia al archivo colors.xml. (Quiere un #RRGGBB en lugar de @ color / text_color)
  • Android: cómo crear Switch caso de esto?
  • ¿Mostrar la vista por encima de la barra de estado?
  • ¡R.java se ha modificado manualmente! Revertir a la versión generada
  • 13 Solutions collect form web for “Html List tag no funciona en android textview. ¿que puedo hacer?”

    Como se puede ver en el código fuente de la clase Html , Html.fromHtml(String) no admite todas las etiquetas HTML. En este caso, <ul> y <li> no son compatibles.

    Desde el código fuente he construido una lista de etiquetas HTML permitidas:

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

    Así que es mejor utilizar WebView y su método loadDataWithBaseURL . Intente algo como esto:

     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 USA of 100% imported cotton.</li></ul></body></html>"; webView.loadDataWithBaseURL(null, str, "text/html", "utf-8", null); 

    Parece una vieja pregunta, estoy teniendo el mismo problema, lo que hice es sobreponer el TagHandler predeterminado, soy nuevo en StackOverflow y Android, y apreciar cualquier corrección o un mejor método 🙂 Este trabajó para mí.

     package com.tumblr.amangautam.cars; import org.xml.sax.XMLReader; import android.app.Activity; import android.os.Bundle; import android.text.Editable; import android.text.Html; import android.text.Html.TagHandler; import android.util.Log; 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; } } } } } 

    Y para mostrar el texto …

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

    [Editar]

    Kuitsi también ha publicado una muy buena biblioteca que hace lo mismo:

    Lo tengo desde este enlace SO .

    El proyecto de muestra completo se encuentra en https://bitbucket.org/Kuitsi/android-textview-html-list .
    El cuadro de muestra está disponible en https://kuitsi.bitbucket.io/stackoverflow3150400_screen.png

    Esta solución está más cerca de la respuesta de masha . Algún código también se toma de la clase interna android.text.Html.HtmlToSpannedConverter . Es compatible con listas ordenadas y desordenadas anidadas, pero los textos demasiado largos en listas ordenadas todavía están alineados con el número de elemento en lugar de texto. Las listas mixtas (ol y ul) también necesitan un poco de trabajo. Proyecto de ejemplo contiene la implementación de Html.TagHandler que se pasa a Html.fromHtml (String, ImageGetter, TagHandler) .

    Editar: Para mayor compatibilidad de etiquetas HTML, https://github.com/NightWhistler/HtmlSpanner también podría valer la pena intentarlo.

    Una pequeña corrección para el código Aman Guatam. La función anterior tiene problema de representación de carácter de nueva línea. Por ejemplo: si antes de la etiqueta <li> es una etiqueta <p> , se renderizan 2 caracteres de nueva línea. Aquí se actualiza el código:

     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; } } } } 

    Diferente solución usando LeadingMarginSpan. Maneja las listas ordenadas y no ordenadas, así como anidar.

     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 ); } } } 

    Si sólo necesita formatear una lista, manténgala simple y copie / pegue un carácter unicode en su TextView para obtener el mismo resultado.

    • Unicode Carácter 'BULLET' (U + 2022)

    Vine aquí buscando implementaciones de TagHandler. Las respuestas de Truong Nguyen y Aman Guatam son muy agradables, pero necesitaba una versión mixta de ambas: necesitaba mi solución para no sobreformatarla y poder devolver etiquetas <ol> , ya que estoy analizando algo como <h3>title</h3><ol><li>item</li><li>item</li><li>item</li></ol> .

    Aquí está mi solución.

     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; } } } } } 

    Tenga en cuenta que, dado que estamos restableciendo el valor del índice cada vez que se inicia una nueva lista, NO funcionará si anidamos listas como en <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

    Con ese código, obtendrías 1, 1, 2, 3 lugar de 1, 1, 2, 2 .

    ADVERTENCIA

    A partir del 10 de febrero de 2016 android.text.Html realmente apoya las etiquetas li y ul y utiliza un new BulletSpan() básico, lo que significa que en las últimas versiones de Android las soluciones Html.TagHandler publicadas aquí serán ignoradas

    Asegúrese de que su código se encarga de este cambio en caso de que usted está esperando un BulletSpan con una brecha más grande que el predeterminado, tendrá que tener algún tipo de solución que hace un encontrar / reemplazar de los vanos

    Claro, hay una manera de mostrar balas en Android TextView. Puede reemplazar las etiquetas <li> por &#149; (Que es el código HTML de la viñeta).

    Si desea probar otros iconos de la lista, use el preferido de la tabla es este enlace;

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

    ¿Qué tal el siguiente código (basado en este enlace ):

     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 { } } 

    Usted puede simplemente reemplazar el "li" con unicodes

      @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"); } } } 

    La respuesta de Lord Voldermort es un buen punto de partida. Sin embargo yo requería la etiqueta del ol para exhibir la lista ordenada 1. 2. 3. .... vez de balas. Además, las etiquetas anidadas necesitan un manejo especial para funcionar correctamente.

    En mi código, he mantenido la pila (parentList) para mantener un registro de las etiquetas ul y ol abiertas y cerradas y también para conocer la etiqueta abierta actual. Además, un levelWiseCounter se utiliza para mantener diferentes cuentas en caso de etiquetas anidadas.

     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 } } 

    Tuve el problema, que siempre tenía una línea vacía después de una lista con la solución @Kuitsis. He añadido unas pocas líneas en handleTag () y ahora las líneas vacías se han ido:

     @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); } } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.