Add an image asset delegate
This allows the user to provide their own bitmaps from wherever
they need to retrieve them from.
Fixes #177
diff --git a/LottieSample/src/main/java/com/airbnb/lottie/samples/AnimationFragment.java b/LottieSample/src/main/java/com/airbnb/lottie/samples/AnimationFragment.java
index acb6172..1087bfc 100644
--- a/LottieSample/src/main/java/com/airbnb/lottie/samples/AnimationFragment.java
+++ b/LottieSample/src/main/java/com/airbnb/lottie/samples/AnimationFragment.java
@@ -6,6 +6,8 @@
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -26,8 +28,10 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.airbnb.lottie.ImageAssetDelegate;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieComposition;
+import com.airbnb.lottie.LottieImageAsset;
import com.airbnb.lottie.OnCompositionLoadedListener;
import org.json.JSONException;
@@ -150,7 +154,23 @@
switch (requestCode) {
case RC_ASSET:
final String assetName = data.getStringExtra(EXTRA_ANIMATION_NAME);
- animationView.setImageAssetsFolder(assetFolders.get(assetName));
+ // animationView.setImageAssetsFolder(assetFolders.get(assetName));
+ animationView.setImageAssetDelegate(new ImageAssetDelegate() {
+ @Override public Bitmap fetchBitmap(LottieImageAsset asset) {
+ InputStream is;
+ try {
+ is = getContext().getAssets().open("Images/WeAccept/" + asset.getFileName());
+ } catch (IOException e) {
+ Log.w("Gabe", "Unable to open asset.", e);
+ return null;
+ }
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inScaled = true;
+ opts.inDensity = 160;
+ Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);
+ return bitmap;
+ }
+ });
LottieComposition.Factory.fromAssetFileName(getContext(), assetName,
new OnCompositionLoadedListener() {
@Override
diff --git a/lottie/src/main/java/com/airbnb/lottie/ImageAsset.java b/lottie/src/main/java/com/airbnb/lottie/ImageAsset.java
deleted file mode 100644
index de90a51..0000000
--- a/lottie/src/main/java/com/airbnb/lottie/ImageAsset.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.airbnb.lottie;
-
-import org.json.JSONObject;
-
-class ImageAsset {
- private final int width;
- private final int height;
- private final String id;
- private final String fileName;
-
- private ImageAsset(int width, int height, String id, String fileName) {
- this.width = width;
- this.height = height;
- this.id = id;
- this.fileName = fileName;
- }
-
- static class Factory {
- private Factory() {
- }
-
- static ImageAsset newInstance(JSONObject imageJson) {
- return new ImageAsset(imageJson.optInt("w"), imageJson.optInt("h"), imageJson.optString("id"),
- imageJson.optString("p"));
- }
- }
-
- int getWidth() {
- return width;
- }
-
- int getHeight() {
- return height;
- }
-
- String getId() {
- return id;
- }
-
- String getFileName() {
- return fileName;
- }
-}
diff --git a/lottie/src/main/java/com/airbnb/lottie/ImageAssetBitmapManager.java b/lottie/src/main/java/com/airbnb/lottie/ImageAssetBitmapManager.java
index 26c7e0e..fe38da3 100644
--- a/lottie/src/main/java/com/airbnb/lottie/ImageAssetBitmapManager.java
+++ b/lottie/src/main/java/com/airbnb/lottie/ImageAssetBitmapManager.java
@@ -4,6 +4,7 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -19,19 +20,17 @@
class ImageAssetBitmapManager {
private final Context context;
private String imagesFolder;
- private final Map<String, ImageAsset> imageAssets;
+ @Nullable private ImageAssetDelegate assetDelegate;
+ private final Map<String, LottieImageAsset> imageAssets;
private final Map<String, Bitmap> bitmaps = new HashMap<>();
ImageAssetBitmapManager(Drawable.Callback callback, String imagesFolder,
- Map<String, ImageAsset> imageAssets) {
+ ImageAssetDelegate assetDelegate, Map<String, LottieImageAsset> imageAssets) {
assertNotNull(callback);
- if (TextUtils.isEmpty(imagesFolder)) {
- throw new IllegalStateException("You must specify an image assets folder by calling " +
- "setImageAssetsFolder on LottieAnimationView or LottieDrawable.");
- }
this.imagesFolder = imagesFolder;
- if (this.imagesFolder.charAt(this.imagesFolder.length() - 1) != '/') {
+ if (!TextUtils.isEmpty(imagesFolder) &&
+ this.imagesFolder.charAt(this.imagesFolder.length() - 1) != '/') {
this.imagesFolder += '/';
}
@@ -44,15 +43,26 @@
context = ((View) callback).getContext();
this.imageAssets = imageAssets;
+ setAssetDelegate(assetDelegate);
+ }
+
+ void setAssetDelegate(@Nullable ImageAssetDelegate assetDelegate) {
+ this.assetDelegate = assetDelegate;
}
Bitmap bitmapForId(String id) {
Bitmap bitmap = bitmaps.get(id);
if (bitmap == null) {
- ImageAsset imageAsset = imageAssets.get(id);
+ LottieImageAsset imageAsset = imageAssets.get(id);
if (imageAsset == null) {
return null;
}
+ if (assetDelegate != null) {
+ bitmap = assetDelegate.fetchBitmap(imageAsset);
+ bitmaps.put(id, bitmap);
+ return bitmap;
+ }
+
InputStream is;
try {
if (TextUtils.isEmpty(imagesFolder)) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/ImageAssetDelegate.java b/lottie/src/main/java/com/airbnb/lottie/ImageAssetDelegate.java
new file mode 100644
index 0000000..ed46ee7
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/ImageAssetDelegate.java
@@ -0,0 +1,12 @@
+package com.airbnb.lottie;
+
+import android.graphics.Bitmap;
+
+/**
+ * Delegate to handle the loading of bitmaps that are not packaged in the assets of your app.
+ *
+ * @see LottieDrawable#setImageAssetDelegate(ImageAssetDelegate)
+ */
+public interface ImageAssetDelegate {
+ Bitmap fetchBitmap(LottieImageAsset asset);
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
index 7f0fd5f..495efa1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
@@ -360,6 +360,15 @@
lottieDrawable.setSpeed(speed);
}
+ /**
+ * Use this if you can't bundle images with your app. This may be useful if you download the
+ * animations from the network or have the images saved to an SD Card. In that case, Lottie
+ * will defer the loading of the bitmap to this delegate.
+ */
+ public void setImageAssetDelegate(ImageAssetDelegate assetDelegate) {
+ lottieDrawable.setImageAssetDelegate(assetDelegate);
+ }
+
void setScale(float scale) {
lottieDrawable.setScale(scale);
setImageDrawable(null);
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java b/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
index 6d23f5e..161c727 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
@@ -29,7 +29,7 @@
public class LottieComposition {
private final Map<String, List<Layer>> precomps = new HashMap<>();
- private final Map<String, ImageAsset> images = new HashMap<>();
+ private final Map<String, LottieImageAsset> images = new HashMap<>();
private final LongSparseArray<Layer> layerMap = new LongSparseArray<>();
private final List<Layer> layers = new ArrayList<>();
private final Rect bounds;
@@ -77,7 +77,7 @@
return !images.isEmpty();
}
- Map<String, ImageAsset> getImages() {
+ Map<String, LottieImageAsset> getImages() {
return images;
}
@@ -239,7 +239,7 @@
if (!assetJson.has("p")) {
continue;
}
- ImageAsset image = ImageAsset.Factory.newInstance(assetJson);
+ LottieImageAsset image = LottieImageAsset.Factory.newInstance(assetJson);
composition.images.put(image.getId(), image);
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index 03dbf82..e8b9519 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -32,6 +32,7 @@
@Nullable private ImageAssetBitmapManager imageAssetBitmapManager;
@Nullable private String imageAssetsFolder;
+ @Nullable private ImageAssetDelegate imageAssetDelegate;
private boolean playAnimationWhenLayerAdded;
private boolean reverseAnimationWhenLayerAdded;
private boolean systemAnimationsAreDisabled;
@@ -278,6 +279,19 @@
updateBounds();
}
+ /**
+ * Use this if you can't bundle images with your app. This may be useful if you download the
+ * animations from the network or have the images saved to an SD Card. In that case, Lottie
+ * will defer the loading of the bitmap to this delegate.
+ */
+ @SuppressWarnings({"unused", "WeakerAccess"}) public void setImageAssetDelegate(
+ @SuppressWarnings("NullableProblems") ImageAssetDelegate assetDelegate) {
+ this.imageAssetDelegate = assetDelegate;
+ if (imageAssetBitmapManager != null) {
+ imageAssetBitmapManager.setAssetDelegate(assetDelegate);
+ }
+ }
+
@SuppressWarnings("WeakerAccess") public float getScale() {
return scale;
}
@@ -345,7 +359,7 @@
if (imageAssetBitmapManager == null) {
imageAssetBitmapManager = new ImageAssetBitmapManager(getCallback(),
- imageAssetsFolder, composition.getImages());
+ imageAssetsFolder, imageAssetDelegate, composition.getImages());
}
return imageAssetBitmapManager;
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieImageAsset.java b/lottie/src/main/java/com/airbnb/lottie/LottieImageAsset.java
new file mode 100644
index 0000000..2cfb2f5
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieImageAsset.java
@@ -0,0 +1,46 @@
+package com.airbnb.lottie;
+
+import org.json.JSONObject;
+
+/**
+ * Data class describing an image asset exported by bodymovin.
+ */
+public class LottieImageAsset {
+ private final int width;
+ private final int height;
+ private final String id;
+ private final String fileName;
+
+ private LottieImageAsset(int width, int height, String id, String fileName) {
+ this.width = width;
+ this.height = height;
+ this.id = id;
+ this.fileName = fileName;
+ }
+
+ static class Factory {
+ private Factory() {
+ }
+
+ static LottieImageAsset newInstance(JSONObject imageJson) {
+ return new LottieImageAsset(imageJson.optInt("w"), imageJson.optInt("h"), imageJson.optString("id"),
+ imageJson.optString("p"));
+ }
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+}