HTML.fromHtml adds space at the end of text?

In my application, I use the Html.fromHtml (string) .toString method to remove the <p> tags that are received when parsing some JSON.

If I leave the <p> tags, the text fits the background perfectly (the background is a relative layout with wrap_content both in height and in width). However, if I use fromHtml to remove <p> tags, suddenly there is a huge space under the text, which I believe is the fromHtml method adding to space at the end?

Any ideas?

EDIT:

Here are the screenshots: http://imgur.com/a/zIZNo

One that has <p> tags, one that doesn't use fromHtml, obviously! :)

EDIT 2: Solution found, see my answer below. Thanks to Andro Selva for helping me by telling me about the hidden /n that was being added!

+6
source share
5 answers

found solution:

fromHtml returns the type Spanned. So I assigned what was returned to the variable, converted it to a string, and then used the .trim () method.

He removed all the spaces at the end.

+8
source

Yes, what you were thinking is really correct. This adds space to the base. But first, let me explain how this works.

You should look at the HTML class to see how it works.

To be simple, here's how it works: whenever your Html class looks at the <p> tag, what it does is simply add the two ends "\ n" to the end.

In this case, the empty space that you see below is actually due to the fact that two \ n are added to the end of the paragraph.

And I added the actual method of the Html class that is responsible for this action,

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

If you want to override this action, you need to override the Html class itself, which is a bit more complicated and cannot be completed here.

EDIT

here is the link to the html class,

HTML class

+5
source

If you are trying to use it in an object or trying to install it in a specific place, try using the <a> tag instead of <p> , <p> adds return wagons at the end, and writes nothing, but you must remember to write \n yourself with using <b> and you keep the style

+3
source

@Andro Selva's explanation is correct, and little can be done about it. Disappointing, everything is getting better for API 24 and later with flags included in the call

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

and I suspect that the FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH flag will reduce the double "\ n \ n" of the standard terminal paragraph to a single "\ n" line break

Given the history of Android versions, I cannot afford to write software for the Android API 24+ exclusively! So ... I found a kludge solution with 2 additional custom tags included.

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

both calls to the RelativeSizeSpan class using this method

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

which is called from a custom TagHandler passed to the Html.fromHtml method, namely:

 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; ... } } 

To use, I set the text size of the Textview object to 1. That is, 1 pixel! Then I set the required true text size required for the mDefaultTextSize variable. I have all the Html functions inside an htmlTextView that extends Textview as:

 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 

}

which includes a public method

 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; } 

A simple call ((htmlTextView)tv).setDefaultTextMetrics(null, 30); sets my htmlTextView to use my standard default font with a text size of 30.

Then, when I give it this example for use in 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> 

my custom <box> just allows me to highlight the background of the text. See the Attached Image showing one result with the <default> with the Textview text size set to 1 and the <default> tag calling a RelevantSizeSpan 30 times, and one with:

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

using the <default> , but instead the Textview text Textview is 30. In the first case, an additional new line still exists, but it is only 1 pixel!

NB There is no real point for the <scale factor="1.5">...</scale> tags. They just left artifacts from other tests.

Results: Both examples below have two new lines between paragraphs, but in one of them one of these lines has only 1 pixel. I will leave it to the reader to figure out how to reduce it to zero, but not use text size 0

0
source

Processing HTML tags leads to the addition of new lines \n , and sometimes several \n following each other. The result will be a line with several newlines between the text (especially if the HTML line contains
tag).

The following method removes the start and end characters of a newline that are the result of a <br/> tag. In addition, several newlines between the text are shortened (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 proccessed HTML string if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return Html.fromHtml(htmlString, FROM_HTML_MODE_COMPACT); }else{ return Html.fromHtml(htmlString); } } 
0
source

Source: https://habr.com/ru/post/922462/


All Articles