Handling HTML content on a TextView is simple as far as the HTML coming in contains a few tags that are by default supported by Android. Simple formatting like bold, italics, font sizes can be handled without even coding a single extra line.
Say, if you have a TextView tv, and there's some HTML string with bold and italicized text, bringing it up on the TextView is pretty simple.
One line code for that:
tv.setText(Html.fromHtml(source));
where the source is actually your HTML string. This works perfectly. But how do we show images if there are any. Well, it's a bit tricky. You have to use the other method that takes in an ImageGetter and a TagHandler.
fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler)
The tagHandler is for situations where you wish to handle specific tags differently. I didn't wish to do that, so I just passed null there.
Now comes the main task. How do you get the image on to the TextView!!!!
Implement the Html.ImageGetter's getDrawable method which handles downloading the image, or accessing it from the net, and then create a drawable and return that object.
static ImageGetter imgGetter = new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
Drawable drawable = null;
drawable = Drawable.createFromPath(source); // Or fetch it from the URL
// Important
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable
.getIntrinsicHeight());
return drawable;
}
};
and use the method on the TextView like this.
tv.setText(Html.fromHtml(source, imgGetter, null);
This will load the TextView with the image. But this call to the getDrawable method is not asynchronous. So, until and unless that method returns, you UI will be blocked. In my case, I am creating the drawable from a local image, so, it didn't take much time. But, if you want to fetch an image from the web, you have to make this call in a separate thread, so that the UI is not blocked.
So, check your HTML string if they contain any images that have to be downloaded. If you find any, create a thread that download that image, saves it somewhere and returns you the location of that file. Now, change the src tags to point to the local images, and call setText method on the TextView.
And that should do it. The important thing to remember is, you have to change the HTML to point it to the file that you have downloaded.
Sample Source code : http://code.google.com/p/myandroidwidgets/source/browse/#svn/trunk/TextViewHTML
This sample doesn't use threads. So, your UI will be blocked unitl the image here is downloaded. So, keep waiting. :)
Hi kumar,
ReplyDeletedrawable = Drawable.createFromPath(source);
This lines return null..
wat's the problem with this ?..
What is your source?
ReplyDeleteKumar,
ReplyDeleteSome Text in my Paragraph Tag
< src="http://google.com/media/sample123.jpg" alt="" />
When i try to post the comment. Its not accepting paragraph & image tag. So i removed those tags.
Here
This is my source. When i try to get my source today morning its works fine. But yesterday it showed a null pointer exception in setBounds line.
What's the problem ?..
Kumar,
ReplyDeleteIn my last comment i mentioned its working fine. After i posted comment & i tried to execute one more time, it showed same error Null Pointer Exception in setBound Line...
Actually the drawable returns as null, so we can't able to set Bounds for that image.
What's wrong with my code ?...
The source should be a local file. Else, you have to in this method, download that file from the net, save it locally, and return the drawable of that file.
ReplyDeleteThanks for your reply Kumar.
ReplyDeleteI'm fetching from server (using JSON ) and then storing it to DB.
From DB only i'm setting it to textview.
we should not use source from DB too ?..
I haven't checked if it works that way, but with the file stuff, it works. If you an give some code, then I can check it and let you know.
ReplyDeleteMail it to me...
Once again thanks for your reply.
ReplyDeleteI will send the file in couple of hours to your mail id. Sorry to take couple of hours
By, code, I meant, Java code :)
ReplyDeleteWhat I can guess, would be your problem, is the formatting. Re-creating an image from a byte stream is difficult. So, I would suggest that you create files and use those files to create drawables.
Updated with Sample Code.
ReplyDeleteThanks Kumar,
ReplyDeleteLet me check it & then you know..
Hi Kumar,
ReplyDeleteWhen i try to use the code. I got the exception.
Exception = java.io.FileNotFoundException: /sdcard/test.jpg
When i created Emulator i didn't mentioned any size of SD Card. In my android Phone also i'm not having SD Card.
This problem is due to SD Card ? , If so please give another idea without SD Card to load image in textview..
Use the data directory.
ReplyDeleteEnvironment.getExternalStorageDirectory(). Instead of this, use Environment.getDataDirectory()
When i try to use getDataDirectory() it throws Excpetion.
ReplyDeleteException = java.io.FileNotFoundException: /data/test.jpg
I changed getDataDirectory() in both places.
FileOutputStream fileout = new FileOutputStream(new File(Environment.getDataDirectory().getAbsolutePath()+ "/test.jpg"));
drawable = Drawable.createFromPath(Environment .getDataDirectory().getAbsolutePath() + "/test.jpg");
Well, I guess, you can easily check and rectify this error. Else, please setup an SD-card. I am sure you can get around this problem
ReplyDeleteFor past 2 days i tried to find that solution. But i can't .. Can you please help over from this ?..
ReplyDeletePlease post some code where you have a problem.
ReplyDeleteProblem arise at the line
ReplyDeletedrawable = Drawable.createFromPath(Environment .getDataDirectory().getAbsolutePath() + "/test.jpg");
Before this line... I set
FileOutputStream fileout = new FileOutputStream(new File(Environment.getDataDirectory().getAbsolutePath()+ "/test.jpg"));
Environment.getDataDirectory().getAbsolutePath()+"/data/your package"+"/test.jpg"
ReplyDeleteYou have to save the file inside /data/your package/file name
Kumar... Thanks for your reply...
ReplyDeleteI replaced my code with your code.
Previously it thrown File not found exception... Now its throwing Unknown host exception.. I think its due to net problem ( Net speed is very low here). Tomorrow i will check it one more time & then i will reply to you about this..
Once again thanks for your reply & answer.. :)
Thanks Kumar :)
ReplyDeleteIts working fine.
Hi Kumar,
ReplyDeleteYour code works fine. But when tried running it in thread it throws this exception
"Exception=android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
Kindly give some hint what causing it.
Well, you cannot access UI from a different thread. Try using the handler.
ReplyDeleteI can not use color for my text when I am using Html.fromHtml(source)
ReplyDeletecan you help me, please?
thanks for your post.I'm trying to use Html.fromHtml, but I can not apply color for my text in textView, and I dont know how to insert image from local like you've said. Could you give me an example to solve two problems here, please?
ReplyDeleteHello Kumar,
ReplyDeleteI was just wondering if you have any idea about my problem. When I use getExternalStorageDirectory() it is able to create a temporary file but if I replaced it with getDataDirectory() I am able to retrieve the path but an error occurs when I create the
temporary file. Can you help me with this? Thank you so much..
File sampleDir = Environment.getExternalStorageDirectory();
try {
audiofile = File.createTempFile("test", ".3gp", sampleDir);
}
public static File getDataDirectory ()
ReplyDeleteSince: API Level 1
Gets the Android data directory.
For access to your package's data directory, you have to append "/data/" to this path.
Hello long,
ReplyDeleteHere is a solution to set color for a text in Html.fromHtml()
http://www.androidpeople.com/android-html-view/
Hello Kumar,
ReplyDeleteThanks for your quick reply..
> For access to your package's data directory,
> you have to append "/data/" to this path.
File sampleDir = Environment.getDataDirectory();
try {
audiofile = File.createTempFile("test", ".3gp", sampleDir);
}
upon checking sampleDir is already equal to "/data" , do I still need to append "/data/" when calling createTempFile?
If yes, I tried passing the following arguments instead
File.createTempFile("/data/test", ".3gp", sampleDir)
and it still didn't work..
upon checking both values of AudioFile is null..
Sorry, but I'm still new to Android programming..
Thanks again.. Hope you can help me on this one.
You data directory would be /data/data/. This is the complete path to your packages data directory. So, yes, you will have to not only append /data, but also your package name. For example, if your package name is com.sample, then your code should be like this.
ReplyDeleteFile file = new File(Environment.getDataDirectory().getAbsolutePath()+"/data/com.sample/test.jpg");
Try this, this should work.
Thanks so much, now I'm using webview to show picture and rich text data. But it turns out to be very slow whenever I append text, and reload all the html content. I still want to use textView with image, for example chat with emoticon, hix, how to do that?
ReplyDeleteHope you can help me.
Well, emoticons are different. Except those, you can show any HTML content on a TextView, of course, except videos. I have not done a performance comparison between the two, so I can't really comment if you are better off using TextView instead of WebView. You can ask your question on google groups, and someone will answer for sure.
ReplyDeleteOk, thanks, using webview is the worst method I use to display image and text in a view, because I must reload all the data whenever I add new content. So that, thanks, I'm still finding out a way to display text and image. Thanks so much:D
ReplyDeleteHello Kumar,
ReplyDeleteThank you very much!!
Now I understand how it works. And also the code worked..
>File file = new >File(Environment.getDataDirectory().getAbsolutePath()+"/data/com.sample/test.jpg");
Thank you again..
Hi Kumar,
ReplyDeleteI want to get path of a file "accounts.db" which exists at path "/data/system/accounts.db".
can you please suggest how should i use getDataDirecoty() in this case.
i can hardcode till "/data" after that i want any function wich would search this file.
any help wud be appreciable.
You cannot access system files like this. Your apps will not have access to these folders (system). Sorry.
ReplyDeleteHello, I tried with your code but it displayed only source in the text view! No image is displayed. why it is happened?
ReplyDeleteThanks.
Did you try running the example? If the example works, then probably you are doing something wrong. Do let me know the errors from the Logcat.
ReplyDeleteNow Only a blue icon image is coming. Not the real image.
ReplyDeleteCheck the logcat for errors.
ReplyDeletejava.io.FileNOTFountException: /mnt/sdcard/test.jif (Permission denied)
ReplyDeleteyeh .. it is working..
ReplyDeleteI have used
"Environment.getDataDirectory().getAbsolutePath()+"/data/com.mypackage/test.jpg"
Thanks a lot....
Hi Kumar,
ReplyDeleteIt's working fine with TextView - but i would like to populate image in email body - any pointer on this would be greatly appriciated.
Thanks
Ankit Shah
you don't have to save the image locally first, you can use Drawable.createFromStream(inputStream, source) method, i have tried it, it works ! :D :D :D
ReplyDelete@m Aji: Thanks. That's already mentioned though in the post. For the example, I chose to download and save it before using it. :)
ReplyDeletehow can i send image in email body in android
ReplyDeleteI don't think that's possible.
ReplyDeleteHi Bibek
ReplyDeleteI need to insert and image in textview and I need to access the image locally from res/raw directory. Can you explain?
Your getDrawable method should return the required drawable. So, it doesn't really depend on how you create it, it can be from your resources as well.
ReplyDeleteHi.I tried using this in an edit text but encountered the following problems
ReplyDelete1)When i try to enter a second image the first disappears.
2)The focus returns to the start of the edit text after inserting the image
How to create contact group and set ringtone for it in android. Help me
ReplyDeleteWhat if i want to load multiple images and format them alternating with text for example
ReplyDeletethis is image 1:
this is image 2:
thanks