【问题标题】:HTML.fromHtml adds space at end of text?HTML.fromHtml 在文本末尾添加空格?
【发布时间】:2012-08-06 14:44:15
【问题描述】:

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

如果我保留<p> 标签,文本完全适合背景(背景是一个相对布局,在高度和宽度上都有 wrap_content。)但是,如果我使用 fromHtml 删除<p> 标签,突然文字下方有一个很大的空格,我相信是fromHtml方法最后加了空格?

有什么想法吗?

编辑:

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

带有<p>标签的那个是不使用fromHtml的,很明显! :)

编辑 2:已找到解决方案,请参阅下面的答案。感谢 Andro Selva 帮助我告诉我正在添加的隐藏 /n!

【问题讨论】:

  • 我猜任何与差异相关的屏幕截图都会有所帮助

标签: java android


【解决方案1】:

找到解决办法:

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

它删除了最后的所有空白。

【讨论】:

  • 这消除了额外的填充,但它也删除了跨度中可能存在的各种格式(例如粗体、斜体..)。那么,为什么还要打扰 html?
  • @Jakob String.Trim() 仅删除给定变量开头和结尾的空格。它不应该删除任何其他内容。
  • @CameronW。是的,它可以删除空格,但它不是空格(它是 html 换行符),除非您按照您的建议将其转换为字符串,这将删除格式(例如 toString())
  • 请参阅 stackoverflow.com/a/9974562/22904 以获得一个很好的答案,它可以在不删除任何格式的情况下修剪文本。
  • 无意义的解决方案。如果丢失了所有格式,将 Spanned 转换为 String 的目的是什么?
【解决方案2】:

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

您必须查看 HTML 类以了解它是如何工作的。

简单来说,它是这样工作的:每当您的Html 类查看<p> 标记时,它所做的只是在末尾附加两个“\n”字符。

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

我已经添加了负责此操作的 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

【讨论】:

  • 感谢您让我知道正在添加的 /n。但是我找到了自己的解决方案,将在下面写下答案。
【解决方案3】:

如果您尝试在对象中使用它或尝试将其放置在特定位置,请尝试使用<a> 标签而不是<p>,<p> 在末尾添加回车符,a 写无,但是你必须记得用<b>自己写\n,这样你就可以保持风格

【讨论】:

    【解决方案4】:

    @Andro Selva 的解释是正确的,没有什么可做的。令人沮丧的是,API 24 及更高版本在调用中包含标志后会变得更好

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

    我怀疑 FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH 标志会将标准段落终止的双“\n\n”减少到换行符的单个“\n”

    考虑到 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>
    

    我的自定义标签&lt;box&gt; 只是让我突出显示文本的背景。见附图,显示了一个使用&lt;default&gt;标签的结果,其中TextView文本大小设置为1,&lt;default&gt;标签调用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>
    

    不使用 &lt;default&gt; 标记,而是将 TextView 文本大小设置为 30。在第一种情况下,额外的新行仍然存在,但它只有 1 个像素高!

    注意&lt;scale factor="1.5"&gt;...&lt;/scale&gt; 标签并没有真正的意义。它们只是其他测试留下的人工制品。

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

    【讨论】:

      【解决方案5】:

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

      @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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-16
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        相关资源
        最近更新 更多