HTML.fromHtml在文本末尾添加空格?

时间:2012-08-09 11:24:08

标签: java android

在我的应用程序中,我使用Html.fromHtml(string).toString方法删除在解析某些JSON时收到的一些<p>标记。

如果我保留<p>标签,则文本完全适合背景(背景是相对布局,高度和宽度都包含wrap_content。)但是,如果我使用fromHtml删除{{1}标签,suddenely在文本下面有一个巨大的空间,我相信最后是在fromHtml方法中添加空格?

有什么想法吗?

编辑:

以下是截图: http://imgur.com/a/zIZNo

具有<p>标签的标签显然是不使用HTML的标签! :)

编辑2:已找到解决方案,请参阅下面的答案。感谢Andro Selva帮我讲述了正在添加的隐藏<p>

5 个答案:

答案 0 :(得分:8)

找到了解决方案:

fromHtml返回Spanned类型。所以我分配了返回给变量的内容,将其转换为字符串,然后在其上使用.trim()方法。

它最后删除了所有空格。

答案 1 :(得分:5)

是的,你的想法是非常正确的。它为底部增加了空间。但在此之前,让我解释一下这是如何工作的。

你必须查看HTML类才能看到它是如何工作的。

简单来说,这就是它的工作原理:只要你的Html课程查看<p>标签,它的作用就是在末尾添加两个“\ n”字符。

在这种情况下,您在底部看到的空白空间实际上是因为两个\ n附加到paragaraph的末尾。

我已经添加了负责此操作的Html类的实际方法,

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

    }
}

如果要覆盖此操作,则必须覆盖Html类本身,这有点棘手,无法在此处完成。

修改

这是Html类的链接,

Html class

答案 2 :(得分:3)

如果您尝试在对象中使用它或尝试将其放在特定位置,请尝试使用<a>标记而不是<p><p>添加返回来自结束,a写无,但你必须记住自己用\n<b>,然后保持风格

答案 3 :(得分:0)

@Andro Selva的解释是正确的,没有太多可以做的。令人沮丧的是,API 24及其后的内容在调用中包含了标记

Spanned fromHtml (String source, 
                int flags, 
                Html.ImageGetter imageGetter, 
                Html.TagHandler tagHandler);

我怀疑 FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH 标志会减少双倍&#34; \ n \ n&#34;标准段落终止于单一&#34; \ n&#34;换行符

考虑到Android版本的历史,我无法专门为Android API 24+编写软件!所以...我找到了一个包含2个额外自定义标签的kludge解决方案。

1. <scale factor="x.xx">... </scale>
2. <default>... </default>

通过此方法

调用RelativeSizeSpan类
private void ProcessRelativeSizeTag(float scalefactor, boolean opening, Editable output) {
                int len = output.length();
                if (opening) {
                    System.out.println("scalefactor open: " + scalefactor);
                    output.setSpan(new RelativeSizeSpan(scalefactor), len, len,
                            Spannable.SPAN_MARK_MARK);
                } else {
                    Object obj = getLast(output, RelativeSizeSpan.class);
                    int where = output.getSpanStart(obj);
                    scalefactor = ((RelativeSizeSpan)obj).getSizeChange();
                    output.removeSpan(obj);
                    System.out.println("scalefactor close: " + scalefactor);
                    if (where != len) {
                        output.setSpan(new RelativeSizeSpan(scalefactor), where, len,
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                }
            }

从提供给Html.fromHtml方法的自定义TagHandler中调用,即:

private static class CustomTagHandler implements Html.TagHandler {

    private void ProcessRelativeSizeTag(float scalefactor, boolean opening, Editable output) {
            int len = output.length();
            if (opening) {
                //mSizeStack.push(scalefactor);
                System.out.println("scalefactor open: " + scalefactor);
                output.setSpan(new RelativeSizeSpan(scalefactor), len, len,
                        Spannable.SPAN_MARK_MARK);
            } else {
                Object obj = getLast(output, RelativeSizeSpan.class);
                int where = output.getSpanStart(obj);
                scalefactor = ((RelativeSizeSpan)obj).getSizeChange();

                output.removeSpan(obj);

                //scalefactor = (float)mSizeStack.pop();
                System.out.println("scalefactor close: " + scalefactor);
                if (where != len) {
                    output.setSpan(new RelativeSizeSpan(scalefactor), where, len,
                            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
            }
        }
...
        final HashMap<String, String> mAttributes = new HashMap<>();

        @Override
        public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
            String Attr;
            processAttributes(xmlReader);
            if ("default".equalsIgnoreCase(tag)) {
                ProcessRelativeSizeTag(mDefaultTextSize, opening, output);
                return;
            }

            if ("scale".equalsIgnoreCase(tag)) {
                Attr = mAttributes.get("factor");
                if (Attr != null && !Attr.isEmpty()) {
                    float factor = parseFloat(Attr);
                    if (factor > 0)
                        ProcessRelativeSizeTag(factor, opening, output);
                }
                return;
... 
            }

       }

要使用,我将Textview对象的文本大小设置为1.即1像素!然后,我在变量mDefaultTextSize中设置所需的真实文本大小。我在htmlTextView中包含了所有Html功能,它将TextView扩展为:

public class htmlTextView extends AppCompatTextView {
    static Typeface mLogo;
    static Typeface mGAMZ;
    static Typeface mBrush;
    static Typeface mStandard;
    int GS_PAINTFLAGS = FILTER_BITMAP_FLAG | ANTI_ALIAS_FLAG | SUBPIXEL_TEXT_FLAG | HINTING_ON;
    static float mDefaultTextSize;
    static Typeface mDefaultTypeface;
etc

}

包括公共方法

public void setDefaultTextMetrics(String face, float defaultTextSize) {
        mDefaultTypeface = mStandard;
        if (face != null) {
            if ("gamz".equalsIgnoreCase(face)) {
                mDefaultTypeface = mGAMZ;
            } else {
                if ("brush".equalsIgnoreCase(face)) {
                    mDefaultTypeface = mBrush;
                }
            }
        }
        setTypeface(mDefaultTypeface);
        setTextSize(1);
        mDefaultTextSize = defaultTextSize;
    }

一个简单的((htmlTextView)tv).setDefaultTextMetrics(null, 30);调用将我的htmlTextView设置为默认使用我的标准字体,文字大小为30.

然后,当我将此示例用于fromHtml:

<string name="htmlqwert">
<![CDATA[
        <p><default><scale factor="1.5"><box> qwertQWERT </box></scale></default></p>
        <p><default><scale factor="1.5"><box> qwertQWERT </box></scale></default></p>
        <p><default><scale factor="1.5"><box> qwertQWERT </box></scale></default></p>
        <p><default><scale factor="1.5"><box> qwertQWERT </box></scale></default></p>
]]>
</string>

我的自定义标记<box>只是让我突出显示文本的背景。请参阅附图,使用<default>标记显示一个结果,TextView文字大小设置为1,<default>标记调用RelevantSizeSpan的因子为30,一个用:

<string name="htmlqwert">
    <![CDATA[
            <p><scale factor="1.5"><box> qwertQWERT </box></scale></p>
            <p><scale factor="1.5"><box>qwertQWERT</box></scale></p>
            <p><scale factor="1.5"><box>qwertQWERT</box></scale></p>
            <p><scale factor="1.5"><box>qwertQWERT</box></scale></p>
    ]]>
    </string>

不使用<default>代码,而是将TextView文字大小设置为30。在第一种情况下,额外的新线仍然存在,但它只有1像素高!

注意<scale factor="1.5">...</scale>标签没有实际意义。他们只是遗留在其他测试的人工制品上。

结果:以下两个示例在段落之间都有2个换行符,但在左侧的一行中,其中一行只有1个像素高。我将把它留给读者来弄清楚如何将它减少到零,但不要使用0的文本大小

答案 4 :(得分:0)

这个解决方案对我有用 创建一个辅助方法来替换所有段落开始和结束标记并全部替换为空字符。

@Nullable
public static String removeParagraphTags(@Nullable String input) {
    if (input == null) {
        return null;
    }
    return input.replaceAll("<p>", "").replaceAll("</p>", "");
}

和用法

  String input = "<p>This is some text in a paragraph.</p>";
HtmlCompat.fromHtml(StringUtils.removeParagraphTags(input),HtmlCompat.FROM_HTML_MODE_COMPACT)