Images
WARNING
This is documentation for legacy versions. For the most current version click here.
Starting with 3.0.0 Markwon comes with ImagesPlugin
which supports http(s), file and data schemes and default media
decoder (for simple images, no SVG or GIF which
are defined in standalone modules).
ImagesPlugin
ImagePlugin takes care of obtaining image resource, decoding it and displaying it in a TextView.
WARNING
Although core artifact contains ImagesPlugin one must
still explicitly register the ImagesPlugin on resulting Markwon
instance.
final Markwon markwon = Markwon.builder(context)
.usePlugin(ImagesPlugin.create())
There are 2 factory methods to obtain ImagesPlugin:
ImagesPlugin#create(Context)ImagesPlugin#createWithAssets(Context)
The first one #create(Context) configures:
FileSchemeHandlerthat allows obtaining images fromfile://urisDataUriSchemeHandlerthat allows inlining images withdata:scheme (data:image/svg+xml;base64,MTIz)NetworkSchemeHandlerthat allows obtaining images fromhttp://andhttps://uris (internally it usesHttpURLConnection)ImageMediaDecoderwhich tries to decode all encountered images as regular ones (png, jpg, etc)
The second one #createWithAssets(Context) does the same but also adds support
for images that reside in assets folder of your application and
referenced by file:///android_asset/{path} uri.
ImagesPlugin also prepares a TextView to display images. Due to asynchronous
nature of image loading, there must be a way to invalidate resulting Spanned
content after an image is loaded.
WARNING
Images come with few limitations. For of all, they work with a TextView only.
This is due to the fact that there is no way to invalidate a Spanned content
by itself (without context in which it is displayed). So, if Markwon is used,
for example, to display a Toast with an image:
final Spanned spanned = markwon.toMarkdown("Hello ");
Toast.makeText(context, spanned, Toast.LENGTH_LONG).show();
Image probably won't be displayed. As a workaround for Toast a custom View
can be used:
final Spanned spanned = markwon.toMarkdown("Hello ");
final View view = createToastView();
final TextView textView = view.findViewById(R.id.text_view);
markwon.setParsedMarkdown(textView, spanned);
final Toast toast = new Toast(context);
toast.setView(view);
// other Toast configurations
toast.show();
SchemeHandler
To add support for different schemes (or customize provided) a SchemeHandler must be used.
final Markwon markwon = Markwon.builder(context)
.usePlugin(ImagesPlugin.create(context))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
// example only, Markwon doesn't come with a ftp scheme handler
builder.addSchemeHandler("ftp", new FtpSchemeHandler());
}
})
.build();
It's a class to convert an URI into an InputStream:
public abstract class SchemeHandler {
@Nullable
public abstract ImageItem handle(@NonNull String raw, @NonNull Uri uri);
}
ImageItem is a holder class for resulting InputStream and (optional)
content type:
public class ImageItem {
private final String contentType;
private final InputStream inputStream;
/* rest omitted */
}
Based on contentType returned a corresponding MediaDecoder will be matched.
If no MediaDecoder can handle given contentType then a default media decoder will
be used.
MediaDecoder
By default core artifact comes with default image decoder only. It's called
ImageMediaDecoder and it can decode all the formats that BitmapFactory#decodeStream(InputStream)
can.
final Markwon markwon = Markwon.builder(this)
.usePlugin(ImagesPlugin.create(this))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
builder.addMediaDecoder("text/plain", new TextPlainMediaDecoder());
}
})
.build();
MediaDecoder is a class to turn InputStream into a Drawable:
public abstract class MediaDecoder {
@Nullable
public abstract Drawable decode(@NonNull InputStream inputStream);
}
TIP
If you are using html you do not have to additionally setup
images displayed via <img> tag, as HtmlPlugin automatically uses configured
image loader. But images referenced in HTML come with additional support for
sizes, which is not supported natively by markdown, allowing absolute or relative sizes:
<img src="./assets/my-image" width="100%">
Placeholder drawable 3.0.0
It's possible to provide a custom placeholder for an image (whilst it's loading).
final Markwon markwon = Markwon.builder(context)
.usePlugin(ImagesPlugin.create(context))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
builder.placeholderDrawableProvider(new AsyncDrawableLoader.DrawableProvider() {
@Override
public Drawable provide() {
// your custom placeholder drawable
return new PlaceholderDrawable();
}
});
}
});
Error drawable 3.0.0
To fallback in case of error whilst loading an image, an error drawable can be used:
final Markwon markwon = Markwon.builder(context)
.usePlugin(ImagesPlugin.create(context))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
builder.errorDrawableProvider(new AsyncDrawableLoader.DrawableProvider() {
@Override
public Drawable provide() {
// your custom error drawable
return new MyErrorDrawable();
}
});
}
});
WARNING
Before 3.0.0 AsyncDrawableLoader accepted a simple Drawable as error drawable
argument. Starting 3.0.0 it accepts a DrawableProvider instead.