使用HTML内容在TextView上进行额外填充

时间:2013-05-16 10:54:33

标签: android html textview

我有TextView

<TextView
    android:id="@+id/issue_journal_item_notes"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/issue_journal_item_details"
    android:layout_below="@+id/issue_journal_item_details"
    android:background="@drawable/journal_item_notes_background"
    android:padding="8dp"
    android:text="issue_journal_item_notes"
    android:textIsSelectable="true" />

我正在填写:

String html = "<p>Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)</p>";
theTextView.setText(Html.fromHtml(html));

这导致:

Resulting screenshot

“受让人......”是另一个TextView 我的TextView是具有灰色背景的那个。它的界限清晰可见,浅灰色。左侧的左侧较暗的灰色条是背景的一部分,因此它也是TextView

我们可以清楚地看到8dp方形填充。但是,底部的空白区域是什么?它是某种填充,但我没有在XML或代码中设置它!

如果有人问,我需要 HTML支持,因为与上面显示的屏幕截图不同,内容可能包含一些HTML内容(<pre><i>,{{ 1}}等。)

8 个答案:

答案 0 :(得分:54)

你看到的额外'填充'实际上只是一个换行符,然后是另一个换行符:

enter image description here

当您深入了解Html.fromHtml(...)实施时,您会遇到以下处理段落标记的方法:

private static void handleP(SpannableStringBuilder text) {
    int len = text.length();

    if (len >= 1 && text.charAt(len - 1) == '\n') {
        if (len >= 2 && text.charAt(len - 2) == '\n') {
            return;
        }

        text.append("\n");
        return;
    }

    if (len != 0) {
        text.append("\n\n");
    }
}

以上代码段取自Android 4.2.2 source。逻辑非常简单,并且基本上确保每个段落标记以\n\n结尾,以在两个元素块之间给出视觉差距。这意味着框架不会考虑整个Html文本是仅包含一个段落(您的情况),还是多个连续的paragaps - 总是在转换结束时是两个换行符段落。

话虽这么说,如果你知道你总是处理一个段落,最简单的解决方案是在将它包装到Html.fromHtml(...)之前删除它。这几乎是其他一个答案中提出的建议。

现在,既然你提到这不是一个真正的选择,那么另一种方法就是“修剪”Html.fromHtml(...)的结果,删除任何尾随的空格。 Android返回Spanned(通常这是一个SpannableStringBuilder对象),遗憾的是,它没有内置trim()方法。尽管如此,或者借用其中一种可用的实现方式并不是太棘手。

trim()方法的基本实现有点像这样:

public static CharSequence trim(CharSequence s, int start, int end) {
    while (start < end && Character.isWhitespace(s.charAt(start))) {
        start++;
    }

    while (end > start && Character.isWhitespace(s.charAt(end - 1))) {
        end--;
    }

    return s.subSequence(start, end);
}

要使用它,请将原始代码更改为:

String html = "<p>Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)</p>";
CharSequence trimmed = trim(Html.fromHtml(html));
theTextView.setText(trimmed);

瞧,前后:

enter image description here

答案 1 :(得分:14)

您也可以使用以下代码

 myTextView.setText(noTrailingwhiteLines(html));

private CharSequence noTrailingwhiteLines(CharSequence text) {

    while (text.charAt(text.length() - 1) == '\n') {
        text = text.subSequence(0, text.length() - 1);
    }
    return text;
}

答案 2 :(得分:4)

Html.fromHtml(html)返回Spannable,因此您可以通过调用toString()然后trim字符串将其转换为字符串,然后将其设置为textview

String html = "<p>Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)</p>";
theTextView.setText(Html.fromHtml(html).toString().trim());

答案 3 :(得分:0)

TextView周围的布局是什么?我记得的是,有些布局忽略了组件的高度偏好,只是让它适合。

答案 4 :(得分:0)

尝试删除<p>代码。

String html = "Hi,<br/>Do you think you could get a logcat during the crash? That seems really strange, especially the fact that it makes Android reboot.<br/>You can get the SDK here: http://developer.android.com/sdk/index.html<br/>(needed for logcat)";
theTextView.setText(Html.fromHtml(html));

希望它有效。

答案 5 :(得分:0)

处理HTML标记会导致添加换行符\n,有时还会出现多个\n。结果将是一个在文本之间具有多个换行符的字符串(特别是如果HTML字符串包含<br/>标记)。

以下方法删除由<br/> tag.引起的前导和尾随换行符

还要减少文本之间的多行新行(API> 24)。

/**
 *
 * @param htmlString
 * @return Spanned represents the html string removed leading and trailing newlines. Also, reduced newlines resulted from processing HTML tags (for API >24)
 */
public static Spanned processHtmlString(String htmlString){

    // remove leading <br/>
    while (htmlString.startsWith("<br/>")){

        htmlString = htmlString.replaceFirst("<br/>", "");
    }

    // remove trailing <br/>
    while (htmlString.endsWith("<br/>")){

        htmlString =  htmlString.replaceAll("<br/>$", "");
    }

    // reduce multiple \n in the processed HTML string 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

        return Html.fromHtml(htmlString,  FROM_HTML_MODE_COMPACT);
    }else{

        return Html.fromHtml(htmlString);
    }
}

答案 6 :(得分:0)

https://stackoverflow.com/a/16745540/2761728显示Android将在HTML标记的末尾添加额外的\n。答案显示了一种在内容结尾处修剪不需要的\n的方法,但不会为您在Android插入的每个标签之间删除\n

对于我来说,我有以下html内容:

<p>This is the first paragraph.</p><p>And this is second paragraph.</p>

Html.fromHtml之后,文本将变为

This is the first paragraph. 


And this is second paragraph. 


我尝试了一些方法,发现使用提供的标志\n可以避免Html。我将代码与trim结合在一起,并提出了以下解决方案:

trimLastBreak(HtmlCompat.fromHtml(htmlContent, FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH))

结果是完美的:

This is the first paragraph.
And this is second paragraph.

答案 7 :(得分:0)

根据Android文档,Html.fromHtml()使用FROM_HTML_MODE_LEGACY将HTML转换为文本。但是FROM_HTML_MODE_LEGACY在两者之间添加了两个换行符。

从Android N开始,有FROM_HTML_MODE_COMPACT,默认情况下仅使用一个换行符。

/**
     * Flags for {@link #fromHtml(String, int, ImageGetter, TagHandler)}: Separate block-level
     * elements with blank lines (two newline characters) in between. This is the legacy behavior
     * prior to N.
     */
    public static final int FROM_HTML_MODE_LEGACY = 0x00000000;

    /**
     * Flags for {@link #fromHtml(String, int, ImageGetter, TagHandler)}: Separate block-level
     * elements with line breaks (single newline character) in between. This inverts the
     * {@link Spanned} to HTML string conversion done with the option
     * {@link #TO_HTML_PARAGRAPH_LINES_INDIVIDUAL}.
     */
    public static final int FROM_HTML_MODE_COMPACT =
            FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH
            | FROM_HTML_SEPARATOR_LINE_BREAK_HEADING
            | FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM
            | FROM_HTML_SEPARATOR_LINE_BREAK_LIST
            | FROM_HTML_SEPARATOR_LINE_BREAK_DIV
            | FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE;

因此我们可以使用将HTML转换为纯文本

HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT);