Using TextViews as simple HTML containers that display decorated text together with images is quite popular these days as an alternative to heavy-weight WebView. To properly display images in a TextView, one needs an implementation of Html.ImageGetter. While there is an example Glide app with such implementation, it's aimed at Glide 3, and I think such GlideImageGetter deserves being included in the lib (it's small and useful).
Here's my implementation for Glide 4.8 loosely based on others that work with other image libraries. Could be buggy, but may serve as a good starting point:
```package com.example.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Html;
import android.widget.TextView;
import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
public class GlideImageGetter implements Html.ImageGetter {
private Context context;
private TextView textView;
GlideImageGetter(Context context, TextView target) {
this.context = context;
textView = target;
}
@Override
public Drawable getDrawable(String url) {
BitmapDrawablePlaceholder drawable = new BitmapDrawablePlaceholder();
GlideApp.with(context)
.asBitmap()
.load(url)
.into(drawable);
return drawable;
}
private class BitmapDrawablePlaceholder extends BitmapDrawable implements Target<Bitmap> {
protected Drawable drawable;
BitmapDrawablePlaceholder() {
super(context.getResources(), Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888));
}
@Override
public void draw(final Canvas canvas) {
if (drawable != null) {
drawable.draw(canvas);
}
}
private void setDrawable(Drawable drawable) {
this.drawable = drawable;
int drawableWidth = drawable.getIntrinsicWidth();
int drawableHeight = drawable.getIntrinsicHeight();
int maxWidth = textView.getMeasuredWidth();
if (drawableWidth > maxWidth) {
int calculatedHeight = maxWidth * drawableHeight / drawableWidth;
drawable.setBounds(0, 0, maxWidth, calculatedHeight);
setBounds(0, 0, maxWidth, calculatedHeight);
} else {
drawable.setBounds(0, 0, drawableWidth, drawableHeight);
setBounds(0, 0, drawableWidth, drawableHeight);
}
textView.setText(textView.getText());
}
@Override
public void onLoadStarted(@Nullable Drawable placeholderDrawable) {
if(placeholderDrawable != null) {
setDrawable(placeholderDrawable);
}
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
if (errorDrawable != null) {
setDrawable(errorDrawable);
}
}
@Override
public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition<? super Bitmap> transition) {
setDrawable(new BitmapDrawable(context.getResources(), bitmap));
}
@Override
public void onLoadCleared(@Nullable Drawable placeholderDrawable) {
if(placeholderDrawable != null) {
setDrawable(placeholderDrawable);
}
}
@Override
public void getSize(@NonNull SizeReadyCallback cb) {
textView.post(() -> cb.onSizeReady(textView.getWidth(), textView.getHeight()));
}
@Override
public void removeCallback(@NonNull SizeReadyCallback cb) {}
@Override
public void setRequest(@Nullable Request request) {}
@Nullable
@Override
public Request getRequest() {
return null;
}
@Override
public void onStart() {}
@Override
public void onStop() {}
@Override
public void onDestroy() {}
}
}
This issue has been automatically marked as stale because it has not had activity in the last seven days. It will be closed if no further activity occurs within the next seven days. Thank you for your contributions.
Using
TextViews as simple HTML containers that display decorated text together with images is quite popular these days as an alternative to heavy-weightWebView. To properly display images in aTextView, one needs an implementation ofHtml.ImageGetter. While there is an example Glide app with such implementation, it's aimed at Glide 3, and I think suchGlideImageGetterdeserves being included in the lib (it's small and useful).Here's my implementation for Glide 4.8 loosely based on others that work with other image libraries. Could be buggy, but may serve as a good starting point:
import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.Html; import android.widget.TextView; import com.bumptech.glide.request.Request; import com.bumptech.glide.request.target.SizeReadyCallback; import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.transition.Transition; public class GlideImageGetter implements Html.ImageGetter { private Context context; private TextView textView; GlideImageGetter(Context context, TextView target) { this.context = context; textView = target; } @Override public Drawable getDrawable(String url) { BitmapDrawablePlaceholder drawable = new BitmapDrawablePlaceholder(); GlideApp.with(context) .asBitmap() .load(url) .into(drawable); return drawable; } private class BitmapDrawablePlaceholder extends BitmapDrawable implements Target<Bitmap> { protected Drawable drawable; BitmapDrawablePlaceholder() { super(context.getResources(), Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)); } @Override public void draw(final Canvas canvas) { if (drawable != null) { drawable.draw(canvas); } } private void setDrawable(Drawable drawable) { this.drawable = drawable; int drawableWidth = drawable.getIntrinsicWidth(); int drawableHeight = drawable.getIntrinsicHeight(); int maxWidth = textView.getMeasuredWidth(); if (drawableWidth > maxWidth) { int calculatedHeight = maxWidth * drawableHeight / drawableWidth; drawable.setBounds(0, 0, maxWidth, calculatedHeight); setBounds(0, 0, maxWidth, calculatedHeight); } else { drawable.setBounds(0, 0, drawableWidth, drawableHeight); setBounds(0, 0, drawableWidth, drawableHeight); } textView.setText(textView.getText()); } @Override public void onLoadStarted(@Nullable Drawable placeholderDrawable) { if(placeholderDrawable != null) { setDrawable(placeholderDrawable); } } @Override public void onLoadFailed(@Nullable Drawable errorDrawable) { if (errorDrawable != null) { setDrawable(errorDrawable); } } @Override public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition<? super Bitmap> transition) { setDrawable(new BitmapDrawable(context.getResources(), bitmap)); } @Override public void onLoadCleared(@Nullable Drawable placeholderDrawable) { if(placeholderDrawable != null) { setDrawable(placeholderDrawable); } } @Override public void getSize(@NonNull SizeReadyCallback cb) { textView.post(() -> cb.onSizeReady(textView.getWidth(), textView.getHeight())); } @Override public void removeCallback(@NonNull SizeReadyCallback cb) {} @Override public void setRequest(@Nullable Request request) {} @Nullable @Override public Request getRequest() { return null; } @Override public void onStart() {} @Override public void onStop() {} @Override public void onDestroy() {} } }
There will be a memory issue if you do it this way tho :/
Any updates on this? @AzimLord Can you elaborate on why this would be a memory issue? There does not appear to be a solid implementation I've found for Html.ImageGetter.
I have created a gist based on @ddekanski code with some changes and improvements:
https://gist.github.com/yrajabi/5776f4ade5695009f87ce7fcbc08078f
The above gist is tested with Glide 4.9 and 4.11 successfully.
First Thanks to @yrajabi
I have modified his code in Kotlin, here is my version: https://gist.github.com/iamriajul/e0026c1c8e1783e6ffa2da511d1d4f37
This might help others.
Thanks...
Most helpful comment
First Thanks to @yrajabi
I have modified his code in Kotlin, here is my version: https://gist.github.com/iamriajul/e0026c1c8e1783e6ffa2da511d1d4f37
This might help others.
Thanks...