Skip to content

Instantly share code, notes, and snippets.

Created September 3, 2011 01:57
Show Gist options
  • Save anonymous/1190397 to your computer and use it in GitHub Desktop.
Save anonymous/1190397 to your computer and use it in GitHub Desktop.
private TextView htmlTextView;
private SpannableStringBuilder htmlSpannable;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
// first parse the html
// replace getHtmlCode() with whatever generates/fetches your html
Spanned spanned = Html.fromHtml(getHtmlCode());
// we need a SpannableStringBuilder for later use
if (spanned instanceof SpannableStringBuilder) {
// for now Html.fromHtml() returns a SpannableStringBuiler
// so we can just cast it
htmlSpannable = (SpannableStringBuilder) spanned;
} else {
// but we have a fallback just in case this will change later
// or a custom subclass of Html is used
new SpannableStringBuilder(spanned);
}
// now we can call setText() on the next view.
// this won't show any images yet
htmlTextView.setText(htmlSpannable);
// next we start a AsyncTask that loads the images
new ImageLoadTask().execute();
// ...
}
private class ImageLoadTask extends AsyncTask {
DisplayMetrics metrics = new DisplayMetrics();
@Override
protected void onPreExecute() {
// we need this to properly scale the images later
getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
@Override
protected Void doInBackground(Void... params) {
// iterate over all images found in the html
for (ImageSpan img : htmlSpannable.getSpans(0,
htmlSpannable.length(), ImageSpan.class)) {
if (!getImageFile(img).isFile()) {
// here you have to download the file
}
// we use publishProgress to run some code on the
// UI thread to actually show the image
// -> onProgressUpdate()
publishProgress(img);
}
return null;
}
@Override
protected void onProgressUpdate(ImageSpan... values) {
// save ImageSpan to a local variable just for convenience
ImageSpan img = values[0];
// now we get the File object again. so remeber to always return
// the same file for the same ImageSpan object
File cache = getImageFile(img);
// if the file exists, show it
if (cache.isFile()) {
// first we need to get a Drawable object
Drawable d = new BitmapDrawable(getResources(),
cache.getAbsolutePath());
// next we do some scaling
int width, height;
int originalWidthScaled = (int) (d.getIntrinsicWidth() * metrics.density);
int originalHeightScaled = (int) (d.getIntrinsicHeight() * metrics.density);
if (originalWidthScaled > metrics.widthPixels) {
height = d.getIntrinsicHeight() * metrics.widthPixels
/ d.getIntrinsicWidth();
width = metrics.widthPixels;
} else {
height = originalHeightScaled;
width = originalWidthScaled;
}
// it's important to call setBounds otherwise the image will
// have a size of 0px * 0px and won't show at all
d.setBounds(0, 0, width, height);
// now we create a new ImageSpan
ImageSpan newImg = new ImageSpan(d, img.getSource());
// find the position of the old ImageSpan
int start = htmlSpannable.getSpanStart(img);
int end = htmlSpannable.getSpanEnd(img);
// remove the old ImageSpan
htmlSpannable.removeSpan(img);
// add the new ImageSpan
htmlSpannable.setSpan(newImg, start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// finally we have to update the TextView with our
// updates Spannable to display the image
htmlTextView.setText(htmlSpannable);
}
}
private File getImageFile(ImageSpan img) {
// you need to implement this method yourself.
// it must return a unique File object (or something
// different if you also change the rest of the code)
// for every image tag. use img.getSource() to get
// the src="" attribute. you might want to use some
// hash of the url as file name
}
}
@vbeniwal
Copy link

thank you for this

@shuaixieca
Copy link

Hi, can you tell me why I got nullPointerException when it runs htmlTextView.setText(htmlSpannable);? The htmlSpannable is not null.

@goutamtweakpixel
Copy link

This is working like a charm. Thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment