AsyncDrawable resume Animatable if was playing before

This commit is contained in:
Dimitry Ivanov 2020-06-09 17:04:27 +03:00
parent 9347208746
commit 1ba2da3757
4 changed files with 46 additions and 8 deletions

View File

@ -9,6 +9,8 @@
#### Changed
* `html` - `SimpleTagHandler` visits children tags if supplied tag is block one ([#235])
* `inline-parser` - `BangInlineProcessor` properly returns `null` if no image node is found (possible to define other inline parsers that use `!` as special character)
* `image` - `AsyncDrawable` won't trigger loading if it has result (aim: `RecyclerView` due to multiple attach/detach events of a View)
* `image` - `AsyncDrawable` will resume result if it is `Animatable` and was playing before detach event (aim: `RecyclerView`) ([#241])
#### Fixed
* `image-glide` cache `RequestManager` in `GlideImagesPlugin#create(Context)` factory method ([#259])
@ -20,6 +22,7 @@
* `image` - `AsyncDrawable#hasKnownDimentions` (deprecated in `4.2.1`)
[#235]: https://github.com/noties/Markwon/issues/235
[#241]: https://github.com/noties/Markwon/issues/241
[#259]: https://github.com/noties/Markwon/issues/259

View File

@ -18,6 +18,9 @@ public class AsyncDrawable extends Drawable {
private final ImageSize imageSize;
private final ImageSizeResolver imageSizeResolver;
// @since $nap;
private final Drawable placeholder;
private Drawable result;
private Callback callback;
@ -27,6 +30,10 @@ public class AsyncDrawable extends Drawable {
// @since 2.0.1 for use-cases when image is loaded faster than span is drawn and knows canvas width
private boolean waitingForDimensions;
// @since $nap; in case if result is Animatable and this drawable was detached, we
// keep the state to resume when we are going to be attached again (when used in RecyclerView)
private boolean wasPlayingBefore = false;
/**
* @since 1.0.1
*/
@ -41,7 +48,7 @@ public class AsyncDrawable extends Drawable {
this.imageSizeResolver = imageSizeResolver;
this.imageSize = imageSize;
final Drawable placeholder = loader.placeholder(this);
final Drawable placeholder = this.placeholder = loader.placeholder(this);
if (placeholder != null) {
setPlaceholderResult(placeholder);
}
@ -99,7 +106,6 @@ public class AsyncDrawable extends Drawable {
return result;
}
@SuppressWarnings("WeakerAccess")
public boolean hasResult() {
return result != null;
}
@ -108,8 +114,6 @@ public class AsyncDrawable extends Drawable {
return getCallback() != null;
}
// yeah
@SuppressWarnings("WeakerAccess")
public void setCallback2(@Nullable Callback cb) {
// @since 4.2.1
@ -132,7 +136,21 @@ public class AsyncDrawable extends Drawable {
result.setCallback(callback);
}
loader.load(this);
// @since $nap; we trigger loading only if we have no result (and result is not placeholder)
final boolean shouldLoad = result == null || result == placeholder;
if (result != null) {
result.setCallback(callback);
// @since $nap;
if (result instanceof Animatable && wasPlayingBefore) {
((Animatable) result).start();
}
}
if (shouldLoad) {
loader.load(this);
}
} else {
if (result != null) {
@ -140,9 +158,14 @@ public class AsyncDrawable extends Drawable {
// let's additionally stop if it Animatable
if (result instanceof Animatable) {
((Animatable) result).stop();
final Animatable animatable = (Animatable) result;
final boolean isPlaying = wasPlayingBefore = animatable.isRunning();
if (isPlaying) {
animatable.stop();
}
}
}
loader.cancel(this);
}
}
@ -206,6 +229,9 @@ public class AsyncDrawable extends Drawable {
public void setResult(@NonNull Drawable result) {
// @since $nap; revert this flag when we have new source
wasPlayingBefore = false;
// if we have previous one, detach it
if (this.result != null) {
this.result.setCallback(null);
@ -250,6 +276,7 @@ public class AsyncDrawable extends Drawable {
waitingForDimensions = false;
final Rect bounds = resolveBounds();
result.setBounds(bounds);
// @since 4.2.1, we set callback after bounds are resolved
// to reduce number of invalidations

View File

@ -60,6 +60,7 @@ dependencies {
implementation it['debug']
implementation it['adapt']
implementation it['android-svg']
implementation it['android-gif']
}
deps['annotationProcessor'].with {

View File

@ -3,12 +3,14 @@ package io.noties.markwon.sample.recycler;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.UpdateAppearance;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -87,8 +89,11 @@ public class RecyclerActivity extends Activity {
plugin
.addSchemeHandler(FileSchemeHandler.createWithAssets(context))
.addSchemeHandler(OkHttpNetworkSchemeHandler.create())
.addMediaDecoder(SvgMediaDecoder.create())
.placeholderProvider(drawable -> new ColorDrawable(0xFFff0000));
.placeholderProvider(drawable -> {
final Drawable placeholder = new ColorDrawable(0xFFff0000);
placeholder.setBounds(0, 0, 100, 100);
return placeholder;
});
}))
// .usePlugin(PicassoImagesPlugin.create(context))
// .usePlugin(GlideImagesPlugin.create(context))
@ -122,6 +127,8 @@ public class RecyclerActivity extends Activity {
// `RemoveUnderlineSpan` will be added AFTER original, thus it will remove underline applied by original
builder.appendFactory(Link.class, (configuration, props) -> new RemoveUnderlineSpan());
}
})
.build();
}