Html.fromHtml(String).toString(); gives css in starting String - android

protected String getEntryContent(String entryContent) {
Log.d(getClass().getName(), "getEntryContent()");
String mWebViewContent;
mWebView.loadDataWithBaseURL(baseUrl,
entryContent, mimeType,
encoding, null);
mWebViewContent =Html.fromHtml(entryContent).toString();
return mWebViewContent;
}
Output:
h2 {font-size:1.2em;font-weight:normal;} a {color:#6688cc;} ol {padding- left:1.5em;} blockquote {margin-left:0em;} .interProject, .noprint {display:none;} li, blockquote {margin-top:0.5em;margin-bottom:0.5em;}
quarterly (not comparable) Occurring once every quarter year (three months).
quarterly rent payments
This gives me starting line as a CSS.
How can i remove that?

You probably passed the inline CSS in your string. From the javadoc of HTML.fromHtml it nowhere states that it can handle inline css, therefore it propably handles it like normal text
Returns displayable styled text from the provided HTML string. Any tags in the HTML will use the specified ImageGetter to request a representation of the image (use null if you don't want this) and the specified TagHandler to handle unknown tags (specify null if you don't want this).
You have to remove the css manually yourself. See this answer on how to do that: Removing css information from HTML in java

You can use this:
CharSequence mSequence = Html.fromHtml("<b>Hello</b> Android");
textView.setText(mSequence);
You can also convert it into String as:
String mString = mSequence.toString();

Related

ANDROID--How to take one part of html tag with fromHtml?

I want to take one part of description from html tag. But I do not know how can I apply it?
Here is my Html tag:
İstanbul Çağlayan Adliyesi’nde teröristler tarafından silahla vurularak öldürülen savcı Mehmet Selim Kiraz’ın babası hastanede taziyeleri kabul ederken, yakınları da gözyaşı döktü. Savcı Kiraz’ın cenazesi Adli Tıp Kurumu morguna götürüldü.
I need to parse this part from description.
The following code give me all sentences in the description but I don't want some sentences which are in <a href=...></a> tags:
viewHolder.txtViewDescription.setText(Html.fromHtml(itemsData.get(position).getDescription()));
How can I apply it?
Thanks for help...
You can use this Regular expression to remove all anchor tags.
String your_string = "<a>your html content</a>useful text"
String exp = "<a href=.*</a>";
String result = your_string.replaceAll(exp, "");
If I understand you well, you are trying to get the whole text, but without this from tags, so you could use a regex like this
str = str.replaceAll("<a href=([^<]*)>([^<]*)</a>", "");
and remove all tags. Then you could use the line you wrote to extract the text
viewHolder.txtViewDescription.setText(Html.fromHtml(itemsData.get(position).getDescription()));
Hopefully this helps you
Try this regular expression for replacing all the hyperlink tags.
String regx = "<a [\\s]*href .*></a>";
String result = description.replaceAll(regx);

AutoLink link square brackets of URL in TextView

I have a url:
https://<site name>/pallavi/[Songs.PK]%2002%20.mp3
I have a text view, with property: android:autoLink="all"
If I simply set the text to the text view, my text view simply highlights the portion preceding the [. It looks something like this:
https://< site name >/pallavi/[Songs.PK]%2002%20.mp3
What i want is, the whole link should be highlighted like:
https://< site name >/pallavi/[Songs.PK]%2002%20.mp3
What I have tried till now:
Used the < pre > tag and Html.fromHtml, but it doesn't seem to work! (I don't even know if the < pre > is supported in android though.)
Used Jsoup.parser. But that too doesn't seem to work for me.
UPDATE
I have tried this answer too: https://stackoverflow.com/a/12376115/1320263
Please let me know if the issue is with android that the text view's linkAll property itself does not consider parenthesis as a valid character or not? If it is supported, how do i hyperlink that too?
Also NOTE:
The text(or link) I have written in the question is just a sample text. In reality, I am getting a block of text, from where it would be very difficult to identify where exactly the hyper link starts and where it ends. Also, the number of links present in the block would be un-known. Hence I cannot use the < a href = "" > thing...
If some one else happens to have the same issue, following is the solution which worked for me:
Pattern pattern = Pattern.compile("(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))");
SpannableString spannable = new SpannableString(html);
Matcher matcher = pattern.matcher(spannable);
// Create ActivitySpans for each match
while (matcher.find())
spannable.setSpan(new ActivitySpan(matcher.group()), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Create a new TextView with these spans and enable the clickable links
mTxtEventDescription.setText(spannable);
You can try this:
((TextView) findViewById(R.id.your_text_view)).setMovementMethod(LinkMovementMethod.getInstance());
((TextView) findViewById(R.id.your_text_view)).setText(Html.fromHtml(getResources().getString(R.string.string_with_links)));`

Extra padding on TextView with HTML contents

I have this 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" />
I'm filling this with:
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));
This results in:
"Assignee ..." is another TextView.
My TextView is the one with the grey background. Its bounds are clearly seen with the very light grey. The left darker gray bar to the left is part of the background, so it's also the TextView
We can clearly see the 8dp square padding. However, what's the empty space at the bottom? It's some kind of padding, but I havent set this in XML nor in code!
In case somebody asks, I need HTML support, because unlike in the screenshot shown above, the contents may have some HTML content (<pre>, <i>, <b>, etc).
The extra 'padding' you're seeing, is in fact just a line break followed by another line break:
When you dive into the Html.fromHtml(...) implementation, you'll come across the following method that handles paragraph tags:
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");
}
}
Above snippet was takes from the Android 4.2.2 source. The logic is quite straightforward and basically ensures that every paragraph tag ends with \n\n, to give a visual gap between two element blocks. It means the framework will not into account whether the whole Html text consists of only a single paragraph (your case), or multiple, successive paragaps - there will always be two line breaks at the end of a transformed paragraph.
That being said, if you know you're always dealing with a single paragraph, the easiest solution is to remove that wrapping paragraph before feeding it to Html.fromHtml(...). This is pretty much what was proposed in one of the other answers.
Now, since you mentioned this isn't really an option, the alternative would be to 'trim' the result of Html.fromHtml(...), removing any trailing white spaces. Android returns a Spanned (usually this is a SpannableStringBuilder object), which, unfortunately, doesn't come with a built-in trim() method. It's not too tricky to come up with your own though, or borrow one of several implementations available out there.
A basic implementation for a trim() method would like somewhat like this:
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);
}
To use it, change your original code to:
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);
And voilà, before and after:
You can also use below code
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;
}
Html.fromHtml(html) returns Spannable so you can convert this to string by calling toString() then trim the string then set it to 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());
As per Android documentation the Html.fromHtml() uses FROM_HTML_MODE_LEGACY for converting HTML to text. But FROM_HTML_MODE_LEGACY adds two newline characters in between.
From Android N onwards there is FROM_HTML_MODE_COMPACT which by default uses only one newline character.
/**
* 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;
So for converting HTML to plaintext we can use,
HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT);
Try this, by removing the <p> tag.
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));
Hope it works.
Processing HTML tags lead to newlines \n being added and sometimes multiple \n following each other. The result will be a string with multiple newlines between the text (specially if the HTML string contains <br/> tag).
The following method removes leading and trailing newlines that are resulted from <br/> tag.
Also, reduces multiple new lines between text (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);
}
}
What is the layout around your TextView? What I remember is that some layouts ignore the height preference of your component and simply make it fit.
https://stackoverflow.com/a/16745540/2761728 shows that Android will add extra \n at the end of your html tag. The answer shows a way to trim the unwanted \n at the end of your content, but it won't remove the \n between each tag Android insert for you.
For my case I have this html content:
<p>This is the first paragraph.</p><p>And this is second paragraph.</p>
After Html.fromHtml , the text will become
This is the first paragraph.
And this is second paragraph.
I tried some method and find that the \n can be avoid with the flag Html provided. I combine the code with trim and come out with this solution:
trimLastBreak(HtmlCompat.fromHtml(htmlContent, FROM_HTML_SEPARATOR_LINE_BREAK_PARAGRAPH))
And the result is perfect:
This is the first paragraph.
And this is second paragraph.
Kotlin code
fun trimTrailingWhitespace(source: CharSequence?): CharSequence? {
if (source == null) return ""
var i = source.length
// loop back to the first non-whitespace character
while (--i >= 0 && Character.isWhitespace(source[i])) {
}
return source.subSequence(0, i + 1)
}
Usage
val trimmedMsg = trimTrailingWhitespace(
Html.fromHtml(
message,
Html.FROM_HTML_MODE_LEGACY
)
)
binding.tvBotText.text = trimmedMsg

Android handle HTML links and typed links in a TextView

I am trying to handle both HTML and typed links in TextViews and I am unable to find a combination of the built in tools to do this. I can make one or the other work but not both.
Given the following formats
http://google.com
Google!
Using .setMovementMethod(LinkMovementMethod.getInstance()) I can make the anchor tag turn into a link and open a webpage on click. Using .setAutoLinkMask(Linkify.ALL) I can make the typed link work as expected. The problem is setAutoLinkMask disables the setMovementMethod functionality and removes the highlighting it creates on the html link as well as its clicking functionality.
I tried searching for others with this issue and I believe I am being blocked by a lack of proper terms for this situation. Has anyone else come across a solution to handle both cases seamlessly?
This is what I have currently, only the typed link is linked in the TextView, the anchor just displays the text it wraps.
mTextViewBio.setText(Html.fromHtml(htmlstring));
mTextViewBio.setAutoLinkMask(Linkify.ALL);
mTextViewBio.setMovementMethod(LinkMovementMethod.getInstance());
mTextViewBio.setLinksClickable(true);
TextView output:
http://google.com
Google!
Problem is that when Linify.addLinks() is called first thing what this method does is removing all spans. When you use Html.fromHtml() Spanned is return, so when Linkify parse text again firstly remove "html links". I wrote a simply class LinkifyExtra. It has one extra method
public class LinkifyExtra extends Linkify {
public static Spanned addLinksHtmlAware(String htmlString) {
// gather links from html
Spanned spann = Html.fromHtml(htmlString);
URLSpan[] old = spann.getSpans(0, spann.length(), URLSpan.class);
List<Pair<Integer, Integer>> htmlLinks = new ArrayList<Pair<Integer, Integer>>();
for (URLSpan span : old) {
htmlLinks.add(new Pair<Integer, Integer>(spann.getSpanStart(span),
spann.getSpanEnd(span)));
}
// linkify spanned, html link will be lost
Linkify.addLinks((Spannable) spann, Linkify.ALL);
// add html links back
for (int i = 0; i < old.length; i++) {
((Spannable) spann).setSpan(old[i], htmlLinks.get(i).first,
htmlLinks.get(i).second, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spann;
}
}
and use it like that
String htmlstring = "http://google.com Google!";
textView = (TextView)findViewById(R.id.textView1);
textView.setText(LinkifyExtra.addLinksHtmlAware(htmlstring));
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setLinksClickable(true);
And it works. But you can't use mTextViewBio.setAutoLinkMask(Linkify.ALL);because it triggers addLinks() and remove "html links". Depends of what you want to do in bigger picture, this method may need some changes. I skip checking if spans are overlapping because I suppose it can't happen but if I am wrong you can simply copy this method.

Android - Class Html - fromHtml - How does it work?

I'm using Html.fromHtml to get the contents of a description tag (in a feed XML) and it works fine
Description tag:
<description><![CDATA[<div class="K2FeedIntroText"><p><img style="margin: 10px; float: left;" alt="block curta" src="http://loc.grupolusofona.pt/images/stories/destaques/block%20curta.jpg" height="110" width="120" />Quatro Horas Descalço é o nome da curta-metragem, realizada por Ico Costa, que se estreia mundialmente no 7.º Festival Internacional de Cinema de Roma, nos dias 12 e 13 de novembro, em competição no Cinema XXI.</p>
]]>
But as I go look into the documentation it says:
Returns displayable styled text from the provided HTML string. Any <img> tags in the HTML will display as a generic replacement image which your program can then go through and replace with real images.
So my question is: how can i do what it says there "which your program can then go through and replace with the real image" ?
I know how to get the img url via RegEx using a Pattern, i just wanted to know how can i use the class to "go through and replace it with the image"
Please say something if i was unclear and ill try to explain it better.
EDIT:
Well, i'm trying to implement this in a simple rss reader (and trying to keep it as simple as possible code-wise)
I'm using a DOM Parser and i'm using a map = HashMap<String, Spanned> to store the values of each child node, along with a KEY:
map.put(KEY_DESC, Html.fromHtml(parser.getValue(e, KEY_DESC)));
In the comments of the answer i found a useful link from which i created a new Class (URLImageParser) and tried to use it like so:
map.put(KEY_DESC, htmlSpan);
Where htmlSpan would be the result of:
this.textView = (TextView)this.findViewById(R.id.textview);
URLImageParser p = new URLImageParser(textView, this);
Spanned htmlSpan = Html.fromHtml(html, p, null);
textView.setText(htmlSpan);
I also created a android:visibility="gone" TextView just in case it needed to store the values in a TextView (maybe i interpreted it wrong)
My original thought was that htmlSpan was of the type Spanned so it would fit in my HashMap just fine.
For uploading to ListView i'm using a SimpleAdapter like so:
ListAdapter adapter = new SimpleAdapter(this, menuItems, R.layout.linhafeed,
new String[] { KEY_TITLE, KEY_DESC, KEY_PUBDATE, KEY_LINK },
new int[] { R.id.title, R.id.desc, R.id.pub, R.id.link });
Where menuItems is ArrayList<HashMap<String,Spanned>>
Something i got wrong here ?
Html.fromHtml(...) will replace any <img ... /> tag with an ImageSpan and a special 'object replacement character' (\uFFFC).
To get the actual image to show up, it looks like there are two options:
implement an ImageGetter that returns the image to display as a Drawable. If I recall correctly, this won't allow you to offload the image loading to a different thread, because it expects the result to be returned right away. Hence, this should suffice for local resources (and probably also any assets in a device's local storage, provided there are no potentially long-running operations required; i.e. scaling, cropping, applying effects etc).
do a second pass over the Spanned result and replace any \uFFFC occurrences. You should be able to get the source (url) of the image from every ImageSpan using the getSource() method. Unfortunately, it doesn't look there are any setters to update the Drawable once loaded, so I'm guessing you may need to replace the ImageSpan with a new one, passing in the loaded image in the constructor.
A third alternative, which may be a bit more heavy-weight than above, is to use a WebView rather than a TextView. That way you don't have to deal with any of the image loading yourself, as it's built into the widget.

Categories

Resources