How To Implement Html.fromhtml With Imagegetter In Android

gadget-accessories

You have an Android App that just fetched HTML content from the web to be displayed on a TextView. The first thing we do is to use Html.fromHtml() method; however, you soon realize that this method replaces all images with generic placeholders (besides not supporting all HTML tags). The good news is that this method does support ways of handling images (and other tags but this tutorial is just for images).
Implementing a ImageGetter is straight and simple; you pass an ImageGetter object to be use to fetch the images that later will be use to fill the placeholders. In order to fetch the images the ImageGetter object must implement the getDrawable method. The getDrawable method must return the Drawable object that will fill the placeholder; but, if null is returned the generic image placeholder will be used instead (see implementation below).

String s = Html.fromHtml(htmlContent, new ImageGetter() {
@Override
public Drawable getDrawable(String source)
{
return null;
}
}
,null);

Implementing a ImageGetter is straight and simple; you pass an ImageGetter object to be use to fetch the images. The way you fetch the images will vary depending on your application needs; so for this example I will fetch the images directly to an InputStream object (sometimes the best way could be saving them to a folder in the SD card).

Fetch Method

public InputStream imageFetch(String source)throws MalformedURLException,IOException {
URL url = new URL(source);
Object o = url.getContent();
InputStream content = (InputStream)o;
// add delay here (see comment at the end)
return content;
}

Fully Implemented Method

String s = Html.fromHtml(htmlContent, new ImageGetter() {
@Override
public Drawable getDrawable(String source) {
Drawable d = null;
try {
InputStream src = imageFetch(source);
d = Drawable.createFromStream(src, “src”);
if(d != null){
d.setBounds(0,0,(d.getIntrinsicWidth(),
d.getIntrinsicHeight());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return d;
}
},null);
TextView t = (TextView)findViewById(R.id.textOutput);
t.setText(s);

One thing to consider is big images may need more time to download so depending on the connection you app may not be able to load all images. Some people work around this by saving the images on the SD card; however, I have gotten around this issue by running this method asynchronously while putting a slight delay on the imageFetch function (right before returning the content).