Android TextView and Image loading from URL — Part 2

If you’ve ended up in a situation where you need to give super powers to your humble TextView and this super power includes :

  1. Displaying HTML content which includes <img> tag.
  2. Click actions on the displayed image.
  3. Center aligning the loaded image with the adjacent text.

Search no more, this article is for you.

Super Power 2: Click listener on the loaded image.

To be exact, the requirement was, have a click listener on the loaded image and when user clicks on it, show a pop up (or alert dialog in Android terminology) with image in original size.

This requires two things :

a) Setting a click listener on the image

b) Getting the original source URL so that the selected image can be displayed in an alert dialog.

Searching for solutions for problem a) and b) lead me to an incredible tool / helper which always existed and I never realized — Spans. Specifically :

  1. ImageSpan : Son of DynamicDrawableSpan, Son of ReplacementSpan, Son of MetricAffectingSpan, daughter of Great Queen CharacterStyle created by God Object.
  2. UrlSpan : Son of ClickableSpan, daughter of Great Queen CharacterStyle created by God Object.

A combination of these two solved my problem and you can use it as following :

public interface Callback {
void onImageClick(String imageUrl);
public static void setClickListenerOnHtmlImageGetter(Spannable html, final Callback callback) {
for (final ImageSpan span : html.getSpans(0, html.length(), ImageSpan.class)) {
int flags = html.getSpanFlags(span);
int start = html.getSpanStart(span);
int end = html.getSpanEnd(span);

html.setSpan(new URLSpan(span.getSource()) {
public void onClick(View v) {
}, start, end, flags);

Here Spannable html is the html we generated in Part 1 after adding the ImageGetter, Callback callback is simply an interface which gives a call back once the listener is invoked.

What the code does is, it iterates through the given Spannable and checks if there is any <img> tag in it and once it finds one, gives info about its start offset, end offset and any flags attached to it.

Once we have this info, we now set a URLSpan on this particular span by getting the url attached with <img> tag, calling span.getSource.

Thankfully, URLSpan has an OnClick method inside the class which we can invoke and pass the url back with our callback interface.

I’ve packaged both the ImageGetter handling (from Part 1) as well as click handling into a utility class ImageUtils as follows :

And finally, I use them with my textview like this :

Spannable html = ImageUtils.getSpannableHtmlWithImageGetter(questionTextView, content);
ImageUtils.setClickListenerOnHtmlImageGetter(html, new ImageUtils.Callback() {
public void onImageClick(String imageUrl) {
}, true);

The last piece to the solution is this :


According to documentation, what this does is “A movement method that traverses links in the text buffer”.

Guess who does it help ? Yes. Son of Clickable Span !

Part 3: Android TextView and Image loading from URL