我有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));
这导致:
“受让人......”是另一个TextView
我的TextView
是具有灰色背景的那个。它的界限清晰可见,浅灰色。左侧的左侧较暗的灰色条是背景的一部分,因此它也是TextView
我们可以清楚地看到8dp方形填充。但是,底部的空白区域是什么?它是某种填充,但我没有在XML或代码中设置它!
如果有人问,我需要 HTML支持,因为与上面显示的屏幕截图不同,内容可能包含一些HTML内容(<pre>
,<i>
,{{ 1}}等。)
答案 0 :(得分:54)
你看到的额外'填充'实际上只是一个换行符,然后是另一个换行符:
当您深入了解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);
瞧,前后:
答案 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);