diff --git a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawable.java b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawable.java index 9d38b915..696f6529 100644 --- a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawable.java +++ b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawable.java @@ -39,6 +39,26 @@ public class AsyncDrawable extends Drawable { this.loader = loader; this.imageSizeResolver = imageSizeResolver; this.imageSize = imageSize; + + final Drawable placeholder = loader.placeholder(); + if (placeholder != null) { + + // process placeholder bounds + final Rect bounds = placeholder.getBounds(); + if (bounds.isEmpty()) { + // set intrinsic bounds + final Rect rect = new Rect( + 0, + 0, + placeholder.getIntrinsicWidth(), + placeholder.getIntrinsicHeight()); + placeholder.setBounds(rect); + setBounds(rect); + } + + // apply placeholder immediately if we have one + setResult(placeholder); + } } @NonNull @@ -66,6 +86,15 @@ public class AsyncDrawable extends Drawable { // if not null -> means we are attached if (callback != null) { + + // as we have a placeholder now, it's important to check it our placeholder + // has a proper callback at this point. This is not required in most cases, + // as placeholder should be static, but if it's not -> it can operate as usual + if (result != null + && result.getCallback() == null) { + result.setCallback(callback); + } + loader.load(destination, this); } else { if (result != null) { diff --git a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoader.java b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoader.java index f036aa7b..fe6506ee 100644 --- a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoader.java +++ b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoader.java @@ -12,6 +12,14 @@ import java.util.concurrent.Executors; public abstract class AsyncDrawableLoader { + /** + * @since 3.0.0 + */ + public interface DrawableProvider { + @Nullable + Drawable provide(); + } + /** * @since 3.0.0 */ @@ -33,6 +41,8 @@ public abstract class AsyncDrawableLoader { public abstract void cancel(@NonNull String destination); + @Nullable + public abstract Drawable placeholder(); public static class Builder { @@ -40,7 +50,8 @@ public abstract class AsyncDrawableLoader { final Map schemeHandlers = new HashMap<>(3); final Map mediaDecoders = new HashMap<>(3); MediaDecoder defaultMediaDecoder; - Drawable errorDrawable; + DrawableProvider placeholderDrawableProvider; + DrawableProvider errorDrawableProvider; @NonNull public Builder executorService(@NonNull ExecutorService executorService) { @@ -94,9 +105,21 @@ public abstract class AsyncDrawableLoader { return this; } + /** + * @since 3.0.0 + */ @NonNull - public Builder errorDrawable(Drawable errorDrawable) { - this.errorDrawable = errorDrawable; + public Builder placeholderDrawableProvider(@NonNull DrawableProvider placeholderDrawableProvider) { + this.placeholderDrawableProvider = placeholderDrawableProvider; + return this; + } + + /** + * @since 3.0.0 + */ + @NonNull + public Builder errorDrawableProvider(@NonNull DrawableProvider errorDrawableProvider) { + this.errorDrawableProvider = errorDrawableProvider; return this; } diff --git a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderImpl.java b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderImpl.java index 281d61fc..fd7c3ad1 100644 --- a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderImpl.java +++ b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderImpl.java @@ -5,6 +5,7 @@ import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import java.io.IOException; import java.io.InputStream; @@ -20,7 +21,8 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader { private final Map schemeHandlers; private final Map mediaDecoders; private final MediaDecoder defaultMediaDecoder; - private final Drawable errorDrawable; + private final DrawableProvider placeholderDrawableProvider; + private final DrawableProvider errorDrawableProvider; private final Handler mainThread; @@ -31,7 +33,8 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader { this.schemeHandlers = builder.schemeHandlers; this.mediaDecoders = builder.mediaDecoders; this.defaultMediaDecoder = builder.defaultMediaDecoder; - this.errorDrawable = builder.errorDrawable; + this.placeholderDrawableProvider = builder.placeholderDrawableProvider; + this.errorDrawableProvider = builder.errorDrawableProvider; this.mainThread = new Handler(Looper.getMainLooper()); } @@ -49,6 +52,14 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader { } } + @Nullable + @Override + public Drawable placeholder() { + return placeholderDrawableProvider != null + ? placeholderDrawableProvider.provide() + : null; + } + private Future execute(@NonNull final String destination, @NonNull AsyncDrawable drawable) { final WeakReference reference = new WeakReference(drawable); @@ -109,7 +120,9 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader { // if result is null, we assume it's an error if (result == null) { - result = errorDrawable; + result = errorDrawableProvider != null + ? errorDrawableProvider.provide() + : null; } if (result != null) { diff --git a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderNoOp.java b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderNoOp.java index cef634a4..74520fb2 100644 --- a/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderNoOp.java +++ b/markwon-core/src/main/java/ru/noties/markwon/image/AsyncDrawableLoaderNoOp.java @@ -1,6 +1,8 @@ package ru.noties.markwon.image; +import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader { @Override @@ -12,4 +14,10 @@ class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader { public void cancel(@NonNull String destination) { } + + @Nullable + @Override + public Drawable placeholder() { + return null; + } }