如何在TextView中显示HTML?


756

我有简单的HTML

<h2>Title</h2><br>
<p>description here</p>

我想在中显示HTML样式的文本TextView。这个怎么做?


7
您要显示标签还是忽略标签?
DerMike 2010年


1
如果您正在寻找不推荐使用的解决方案,就在这里stackoverflow.com/questions/37904739/…–
crgarridos

Answers:


1350

您需要使用Html.fromHtml()XML字符串中的HTML。仅在布局XML中引用带有HTML的字符串将不起作用。

这是您应该做的:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>", Html.FROM_HTML_MODE_COMPACT));
} else { 
    textView.setText(Html.fromHtml("<h2>Title</h2><br><p>Description here</p>"));
}

7
h2根据定义,它周围会留有很多余地。并且p还有一些余量。如果您不希望出现这种差距,则可以考虑使用其他html元素。
David Hedlund 2010年

10
Kostadin,您可以将标签放入XML中,只需将它们包装在CDATA括号中即可。
杰拉德(Gerard)

3
对于那些希望与ol / ul / li标签一起使用的人,请查看以下解决方案:stackoverflow.com/a/3150456/1369016
Tiago

13
那应该是android.text.Html.fromHtml。我知道大多数IDE都会为您修复它,但是出于可读性考虑,最好知道程序包名称。
马丁

14
@Martin我不是说可读性而是说详尽性。直接在此类代码中使用的IMO完全限定名称比短名称可读性差。但是,我同意以下事实,即这样的答案应该提供软件包(附带说明),这是链接的要点;)
Joffrey 2014年

76

的setText(Html.fromHtml(bodyData))弃用 API 24后,现在你必须这样做:

 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
      tvDocument.setText(Html.fromHtml(bodyData,Html.FROM_HTML_MODE_LEGACY));
 } else {
      tvDocument.setText(Html.fromHtml(bodyData));
 }

4
为什么在API 24+中使用FROM_HTML_MODE_LEGACY?
galcyurio

64

看看这个:https : //stackoverflow.com/a/8558249/450148

太好了!!

<resource>
    <string name="your_string">This is an <u>underline</u> text demo for TextView.</string>
</resources>

它仅适用于少量标签。


12
此方法是否支持任何标签列表?
mente 2014年

23
@mente根据源代码:<a>,<b>,<big>,<blockquote>,<br>,<cite>,<dfn> <div align =“ ...”>,<em>,<字体大小=“ ...” color =“ ...” face =“ ...”> <h1-6>,<i>,<img src =“ ...”>,<p>,<small > <strike>,<strong>,<sub>,<sup>,<tt>,<u>(来源:dzone.com/snippets/how-display-html-android
JerabekJakub,2014年

@JerabekJakub,但要小心,如果要处理img,则必须实现Html.ImageGetter。
MiguelHincapieC

@ 0mahc0当实现img时可以设置大小吗?
2016年

1
@Joh是可能的。在实现.ImageGetter时,有一种称为getDrawable(String source)的方法。如果您需要更多帮助,提出问题并标记我,我给您举个例子;)
MiguelHincapieC 2016年

41

如果您希望能够通过xml对其进行配置而无需在Java代码中进行任何修改,那么您可能会发现此想法很有帮助。只需从构造函数调用init并将文本设置为html

public class HTMLTextView extends TextView {
    ... constructors calling init...
    private void init(){
       setText(Html.fromHtml(getText().toString()));
    }    
}

xml:

<com.package.HTMLTextView
android:text="@string/about_item_1"/>

1
什么是 '...'。请澄清
GilbertS

25

如果您试图显示来自字符串资源ID的HTML,则格式可能不会显示在屏幕上。如果发生这种情况,请尝试使用CDATA标记代替:

strings.xml:
<string name="sample_string"><![CDATA[<h2>Title</h2><br><p>Description here</p>]]></string>

...

MainActivity.java:
text.setText(Html.fromHtml(getString(R.string.sample_string));

有关更多详细信息,请参见此帖子


谢谢,该做的我-使用API 23.
的xman

24

下面的代码对我来说是最好的结果。

TextView myTextview = (TextView) findViewById(R.id.my_text_view);
htmltext = <your html (markup) character>;
Spanned sp = Html.fromHtml(htmltext);
myTextview.setText(sp);

13
String value = "<html> <a href=\"http://example.com/\">example.com</a> </html>";
    SiteLink= (TextView) findViewById(R.id.textViewSite);
    SiteLink.setText(Html.fromHtml(value));
    SiteLink.setMovementMethod(LinkMovementMethod.getInstance());

您如何更改锚的颜色?
EdmundYeung99年

android:textColorLink =“ color”
Pedro

这会将整个textview着色为红色,但是如果我只想要锚标签,则需要用<font>标签包裹<a>标签,并在其中添加颜色
EdmundYeung99,2014年

11

如果您只想显示一些html文本,而实际上并不需要a TextView,请WebView使用a 并按如下所示使用它:

String htmlText = ...;
webview.loadData(htmlText , "text/html; charset=UTF-8", null);

这也不限制您使用几个html标记。


2
尽管这是解决TextView支持的一组受限html标记的非常有用的方法,但它的缺点是,它与不能很好地配合使用layout_height="wrap_content"。您将必须设置一个明确的高度或match_parent。
Ridcully

3
webview非常慢
Jackky777 '17

11

在string.xml文件中的字符串中使用CData部分以将html内容实际显示到TextView的最佳方法是,以下代码片段将带给您一个不错的主意。

//in string.xml file
<string name="welcome_text"><![CDATA[<b>Welcome,</b> to the forthetyroprogrammers blog Logged in as:]]> %1$s.</string>

//and in Java code
String welcomStr=String.format(getString(R.string.welcome_text),username);
tvWelcomeUser.setText(Html.fromHtml(welcomStr));

即使在使用String.format方法格式化文本之后,字符串文本中的CData部分仍可保持html标记数据的完整性。因此,Html.fromHtml(str)可以正常工作,并且您会在“欢迎”消息中看到粗体文本。

输出:

欢迎来到您最喜欢的音乐应用商店。登录为:用户名


谢谢,这对我来说做到了-使用
API23。– XMAN

谢谢,您保存了我的一天:)仅需少量补充:我们需要将此检查添加到上述代码中:if(Build.VERSION.SDK_INT> = Build.VERSION_CODES.N){//用于24个api和更多textView.setText( Html.fromHtml(welcomStr,Html.FROM_HTML_OPTION_USE_CSS_COLORS)); } else {//或用于较旧的api textView.setText(Html.fromHtml(welcomStr)); }。API> = 24的第二个参数标志的值可以根据要求为任意值。
AndroidGuy


6

我也想建议以下项目:https : //github.com/NightWhistler/HtmlSpanner

用法与默认的android转换器几乎相同:

(new HtmlSpanner()).fromHtml()

在我已经开始通过自己的html到spannable转换器的实现开始后找到了它,因为标准Html.fromHtml在渲染控制方面没有提供足够的灵活性,甚至无法使用ttf的自定义字体


我收到以下错误消息:错误:(80,13)无法解决:com.osbcp.cssparser:cssparser:1.5我该如何解决?
Araju

6

我知道这个问题很旧。其他答案在这里建议Html.fromHtml()方法。我建议您HtmlCompat.fromHtml()androidx.core.text.HtmlCompat包中使用。因为这是Html该类的向后兼容版本。

样例代码:

import androidx.core.text.HtmlCompat;
import android.text.Spanned;
import android.widget.TextView;

String htmlString = "<h1>Hello World!</h1>";

Spanned spanned = HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT);

TextView tvOutput = (TextView) findViewById(R.id.text_view_id);

tvOutput.setText(spanned);

通过这种方式,您可以避免检查Android API版本,并且易于使用(单行解决方案)。


那和旧的methot有什么不同?HTML模式的目的是什么?
user1209216

1
正在寻找这样的东西。谢谢:)
Subhrajyoti Sen

5

使用简单Html.fromHtml("html string")。这将起作用。如果字符串具有类似的标记,<h1>则将出现空格。但是我们不能消除这些空间。如果仍然要删除空格,则可以删除字符串中的标记,然后将字符串传递给method Html.fromHtml("html string");。同样,通常这些字符串来自server(dynamic),但不是经常,如果将字符串原样传递给方法要比尝试从字符串中删除标记要好。



4

制作一个像下面这样的全局方法:

public static Spanned stripHtml(String html) {
            if (!TextUtils.isEmpty(html)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    return Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT);
                } else {
                    return Html.fromHtml(html);
                }
            }
            return null;
        }

您也可以在“活动/片段”中使用它,例如:

text_view.setText(stripHtml(htmlText));

3

我已经使用Web视图实现了这一点。就我而言,我必须从URL加载图像以及文本视图中的文本,这对我有用。

WebView myWebView =new WebView(_context);
        String html = childText;
        String mime = "text/html";
        String encoding = "utf-8";
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.loadDataWithBaseURL(null, html, mime, encoding, null);

为了正确显示UTF-8,您需要将MIME类型设置为“ text / html; charset = UTF-8”。
shawkinaw '16

3

它已经通过各种答案建议使用的HTML框架类的建议在这里,但不幸的是这个类在不同的Android版本和各种未解决的bug不同的行为,如表现在问题2146371477823512875953

因此,您可能希望使用兼容性库在Android版本之间标准化和向后移植Html类,其中包括元素和样式的更多回调:

Github项目HtmlCompat

虽然它类似于框架的Html类,但需要进行一些签名更改才能允许更多回调。这是GitHub页面上的示例:

Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0);
// You may want to provide an ImageGetter, TagHandler and SpanCallback:
//Spanned fromHtml = HtmlCompat.fromHtml(context, source, 0,
//        imageGetter, tagHandler, spanCallback);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(fromHtml);

@MartijnPieters先前关闭的答案是该问题的答案的重复,与框架方法的弃用有关。我已经扩展了使用兼容性库的更好方法的原因。我认为将两个问题都标记为彼此重复是不合理的,因为它们明显不同。
Paul Lammertsma '17

2

每当您编写自定义文本视图时,基本的HTML设置文本功能都将从某些设备中消失。

因此,我们需要按照以下其他步骤进行操作:

public class CustomTextView extends TextView {

    public CustomTextView(..) {
        // other instructions
        setText(Html.fromHtml(getText().toString()));
    }
}

1
public class HtmlTextView extends AppCompatTextView {

public HtmlTextView(Context context) {
    super(context);
    init();
}

private void init(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        setText(Html.fromHtml(getText().toString(), Html.FROM_HTML_MODE_COMPACT));
    } else {
        setText(Html.fromHtml(getText().toString()));
    }
 }
}

以上答案的更新


1

使用以下代码获取解决方案:

textView.setText(fromHtml("<Your Html Text>"))

效用法

public static Spanned fromHtml(String text)
{
    Spanned result;
    if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        result = Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY);
    } else {
        result = Html.fromHtml(text);
    }
    return result;
}

1

创建科特林扩展转换HTML字符串 -

fun String?.toHtml(): Spanned? {
    if (this.isNullOrEmpty()) return null
    return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_COMPACT)
}

0

我可以建议一个有点怪异但仍然很聪明的解决方案!我从这篇文章中得到了这个想法,并将其改编为Android。基本上,您使用,WebView然后将要显示和编辑的HTML插入可编辑的div标签中。这样,当用户点击WebView键盘时,将出现并允许编辑。他们只需要添加一些JavaScript即可取回编辑后的HTML,瞧!

这是代码:

public class HtmlTextEditor extends WebView {

    class JsObject {
        // This field always keeps the latest edited text
        public String text;
        @JavascriptInterface
        public void textDidChange(String newText) {
            text = newText.replace("\n", "");
        }
    }

    private JsObject mJsObject;

    public HtmlTextEditor(Context context, AttributeSet attrs) {
        super(context, attrs);

        getSettings().setJavaScriptEnabled(true);
        mJsObject = new JsObject();
        addJavascriptInterface(mJsObject, "injectedObject");
        setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                loadUrl(
                        "javascript:(function() { " +
                            "    var editor = document.getElementById(\"editor\");" +
                            "    editor.addEventListener(\"input\", function() {" +
                            "        injectedObject.textDidChange(editor.innerHTML);" +
                            "    }, false)" +
                            "})()");
            }
        });
    }

    public void setText(String text) {
        if (text == null) { text = ""; }

        String editableHtmlTemplate = "<!DOCTYPE html>" + "<html>" + "<head>" + "<meta name=\"viewport\" content=\"initial-scale=1.0\" />" + "</head>" + "<body>" + "<div id=\"editor\" contenteditable=\"true\">___REPLACE___</div>" + "</body>" + "</html>";
        String editableHtml = editableHtmlTemplate.replace("___REPLACE___", text);
        loadData(editableHtml, "text/html; charset=utf-8", "UTF-8");
        // Init the text field in case it's read without editing the text before
        mJsObject.text = text;
    }

    public String getText() {
        return mJsObject.text;
    }
}

在这里是作为一个要点的组件。

注意:我不需要原始解决方案中的高度更改回调,因此此处未提供,但是您可以根据需要轻松添加它。


0

如果androidx.在项目中使用*类,则应使用HtmlCompat.fromHtml(text, flag)。该方法的来源是:

@NonNull public static Spanned fromHtml(@NonNull String source, @FromHtmlFlags int flags) { if (Build.VERSION.SDK_INT >= 24) { return Html.fromHtml(source, flags); } //noinspection deprecation return Html.fromHtml(source); }

它比Html.fromHtml更好,因为代码更少,只有一行,并且是推荐的使用方式。


0

您可以像这样使用简单的Kotlin扩展功能:

fun TextView.setHtmlText(source: String) {
    this.text = HtmlCompat.fromHtml(source, HtmlCompat.FROM_HTML_MODE_LEGACY)
}

和用法:

textViewMessage.setHtmlText("Message: <b>Hello World</b>")

0

只需使用:

String variable="StackOverflow";
textView.setText(Html.fromHtml("<b>Hello : </b>"+ variable));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.