Html List标签在android textview中不起作用.我能做什么?

Pra*_*een 95 android

Html List标签在android TextView中不起作用.这是我的字符串内容:

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>";
Run Code Online (Sandbox Code Playgroud)

我在这样的文本视图中加载它:

textview.setText(Html.fromHtml(str));
Run Code Online (Sandbox Code Playgroud)

输出看起来像一个段落.我能做什么?它有什么解决方案吗?

编辑:

webview.loadData(str,"text/html","utf-8");
Run Code Online (Sandbox Code Playgroud)

Cri*_*ian 149

正如您在Html类源代码中看到的那样,Html.fromHtml(String)不支持所有HTML标记.在这种情况下,<ul><li>不受支持.

从源代码我构建了一个允许的HTML标记列表:

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

所以你最好使用WebView它的loadDataWithBaseURL方法.尝试这样的事情:

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);
Run Code Online (Sandbox Code Playgroud)

  • 这是一个解决方案?你不能只使用WebView,与TextView相比,它是一个非常昂贵的小部件.您不能只为每个格式化的文本使用WebView. (10认同)
  • 你实际上不能以同样的方式使用WebView,所以这实际上并不是解决问题的方法. (6认同)
  • 然后使用WebView? (2认同)
  • 非常重要的是要注意这个"允许"标签的某些属性也不受支持.:=( (2认同)
  • 冷静......我编辑了我的答案,请让我知道它是否有效. (2认同)

Ama*_*tam 134

看起来像一个老问题,我遇到了同样的问题,我所做的是覆盖默认的TagHandler,我是StackOverflow和Android的新手,并且感谢任何更正或更好的方法:)这个对我有用.

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;
                }
            }   
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并用于显示文字......

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

[编辑]

Kuitsi还发布了一个非常好的库,它也是如此:

这个SO链接得到它.

  • @Aman Gautam非常棒,谢谢!你有任何想法如何在包装超过1行时标记文本吗?使用此代码在第二行之后,文本与数字对齐而不是标签,以保持数字分开.我尝试了一些事情,但我无法理解 (6认同)
  • 不工作24.永远不会检测到ul标签. (3认同)

Kui*_*tsi 65

完整的示例项目位于https://bitbucket.org/Kuitsi/android-textview-html-list.
示例图片位于https://kuitsi.bitbucket.io/stackoverflow3150400_screen.png

这个解决方案最接近masha的答案.有些代码也来自内部类android.text.Html.HtmlToSpannedConverter.它支持嵌套的有序和无序列表,但有序列表中的太长文本仍与项目编号而不是文本对齐.混合列表(ol和ul)也需要一些工作.示例项目包含Html.TagHandler的实现,它传递给Html.fromHtml(String,ImageGetter,TagHandler).

编辑:对于更广泛的HTML标记支持,https://github.com/NightWhistler/HtmlSpanner也可能值得尝试.

  • 为了避免其他人浪费2个小时,NightWhistler HtmlSpanner删除所有重音字符,无论出于何种未知原因. (2认同)

Tru*_*yen 24

Aman Guatam代码的一个小修复.上述函数存在呈现换行符的问题.例如:如果在<li>标记之前是<p>标记,则会呈现2个换行符.这是升级代码:

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


kas*_*sim 12

警告

截至2016年2月10日android.text.Html实际上支持liul标记并使用基本new BulletSpan(),这意味着在最新版本的Android中,Html.TagHandler此处发布的解决方案将被忽略

确保您的代码处理此更改,以防您期望BulletSpan的间隙大于默认值,您必须使用某种解决方案来查找/替换跨度

  • But that new Html class is only available in Android `N` and above. (4认同)

mas*_*sha 9

使用LeadingMarginSpan的不同解决方案.处理有序和无序列表以及嵌套.

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 );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢使用Spans的想法,但我无法使用此代码获得嵌套列表.两行`output.setSpan(...)`与`java.lang.RuntimeException崩溃:PARAGRAPH span必须从段落边界开始 (5认同)
  • 为什么使用Vector而不是简单的ArrayList?Vector适用于多线程... (2认同)

小智 8

如果您只需要格式化列表,请保持简单并在TextView中复制/粘贴unicode字符以获得相同的结果.

•Unicode字符'BULLET'(U + 2022)


Cha*_*ake 5

我来这里寻找TagHandler实现.Truong Nguyen和Aman Guatam的答案都非常好,但我需要两者的混合版本:我需要我的解决方案,不要重新格式化它,并能够重新解析<ol>标签,因为我正在解析类似的东西<h3>title</h3><ol><li>item</li><li>item</li><li>item</li></ol>.

这是我的解决方案.

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;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,由于我们在新列表开始时重置索引值,因此如果您嵌入像中的列表,它将无法工作 <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

使用该代码,您将得到1, 1, 2, 3而不是1, 1, 2, 2.