Works
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
index 4932ded..b9ec204 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
@@ -74,6 +74,7 @@
* [0,100]
*/
Integer OPACITY = 4;
+ Integer DROP_SHADOW_COLOR = 5;
/**
* In Px
*/
@@ -167,6 +168,22 @@
* In Dp
*/
Float TEXT_SIZE = 14f;
+ /**
+ * [0,100]
+ */
+ Float DROP_SHADOW_OPACITY = 15f;
+ /**
+ * Degrees from 12 o'clock.
+ */
+ Float DROP_SHADOW_DIRECTION = 16f;
+ /**
+ * In Px
+ */
+ Float DROP_SHADOW_DISTANCE = 17f;
+ /**
+ * In Px
+ */
+ Float DROP_SHADOW_RADIUS = 18f;
ColorFilter COLOR_FILTER = new ColorFilter();
/**
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
index c257238..643d9ce 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/BaseStrokeContent.java
@@ -20,6 +20,7 @@
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.animation.LPaint;
import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.DropShadowKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.IntegerKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
@@ -57,6 +58,8 @@
@Nullable private BaseKeyframeAnimation<Float, Float> blurAnimation;
float blurMaskFilterRadius = 0f;
+ @Nullable private DropShadowKeyframeAnimation dropShadowAnimation;
+
BaseStrokeContent(final LottieDrawable lottieDrawable, BaseLayer layer, Paint.Cap cap,
Paint.Join join, float miterLimit, AnimatableIntegerValue opacity, AnimatableFloatValue width,
List<AnimatableFloatValue> dashPattern, AnimatableFloatValue offset) {
@@ -102,13 +105,14 @@
dashPatternOffsetAnimation.addUpdateListener(this);
}
- if (layer.getBlurEffect() == null) {
- blurAnimation = null;
- } else {
+ if (layer.getBlurEffect() != null) {
blurAnimation = layer.getBlurEffect().getBlurriness().createAnimation();
blurAnimation.addUpdateListener(this);
layer.addAnimation(blurAnimation);
}
+ if (layer.getDropShadowEffect() != null) {
+ dropShadowAnimation = new DropShadowKeyframeAnimation(this, layer, layer.getDropShadowEffect());
+ }
}
@Override public void onValueChanged() {
@@ -180,6 +184,9 @@
}
blurMaskFilterRadius = blurRadius;
}
+ if (dropShadowAnimation != null) {
+ dropShadowAnimation.applyTo(paint);
+ }
for (int i = 0; i < pathGroups.size(); i++) {
PathGroup pathGroup = pathGroups.get(i);
@@ -359,6 +366,16 @@
blurAnimation.addUpdateListener(this);
layer.addAnimation(blurAnimation);
}
+ } else if (property == LottieProperty.DROP_SHADOW_COLOR && dropShadowAnimation != null) {
+ dropShadowAnimation.setColorCallback((LottieValueCallback<Integer>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_OPACITY && dropShadowAnimation != null) {
+ dropShadowAnimation.setOpacityCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_DIRECTION && dropShadowAnimation != null) {
+ dropShadowAnimation.setDirectionCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_DISTANCE && dropShadowAnimation != null) {
+ dropShadowAnimation.setDistanceCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_RADIUS && dropShadowAnimation != null) {
+ dropShadowAnimation.setRadiusCallback((LottieValueCallback<Float>) callback);
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
index 0578295..35f472f 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/FillContent.java
@@ -18,7 +18,7 @@
import com.airbnb.lottie.animation.LPaint;
import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.ColorKeyframeAnimation;
-import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.DropShadowKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.content.ShapeFill;
@@ -44,18 +44,21 @@
@Nullable private BaseKeyframeAnimation<Float, Float> blurAnimation;
float blurMaskFilterRadius;
+ @Nullable private DropShadowKeyframeAnimation dropShadowAnimation;
+
public FillContent(final LottieDrawable lottieDrawable, BaseLayer layer, ShapeFill fill) {
this.layer = layer;
name = fill.getName();
hidden = fill.isHidden();
this.lottieDrawable = lottieDrawable;
- if (layer.getBlurEffect() == null) {
- blurAnimation = null;
- } else {
+ if (layer.getBlurEffect() != null) {
blurAnimation = layer.getBlurEffect().getBlurriness().createAnimation();
blurAnimation.addUpdateListener(this);
layer.addAnimation(blurAnimation);
}
+ if (layer.getDropShadowEffect() != null) {
+ dropShadowAnimation = new DropShadowKeyframeAnimation(this, layer, layer.getDropShadowEffect());
+ }
if (fill.getColor() == null || fill.getOpacity() == null) {
colorAnimation = null;
@@ -107,12 +110,15 @@
float blurRadius = blurAnimation.getValue();
if (blurRadius == 0f) {
paint.setMaskFilter(null);
- } else if (blurRadius != blurMaskFilterRadius){
+ } else if (blurRadius != blurMaskFilterRadius) {
BlurMaskFilter blur = layer.getBlurMaskFilter(blurRadius);
paint.setMaskFilter(blur);
}
blurMaskFilterRadius = blurRadius;
}
+ if (dropShadowAnimation != null) {
+ dropShadowAnimation.applyTo(paint);
+ }
path.reset();
for (int i = 0; i < paths.size(); i++) {
@@ -173,6 +179,16 @@
blurAnimation.addUpdateListener(this);
layer.addAnimation(blurAnimation);
}
+ } else if (property == LottieProperty.DROP_SHADOW_COLOR && dropShadowAnimation != null) {
+ dropShadowAnimation.setColorCallback((LottieValueCallback<Integer>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_OPACITY && dropShadowAnimation != null) {
+ dropShadowAnimation.setOpacityCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_DIRECTION && dropShadowAnimation != null) {
+ dropShadowAnimation.setDirectionCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_DISTANCE && dropShadowAnimation != null) {
+ dropShadowAnimation.setDistanceCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_RADIUS && dropShadowAnimation != null) {
+ dropShadowAnimation.setRadiusCallback((LottieValueCallback<Float>) callback);
}
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
index c5a4478..8d3c5ca 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/GradientFillContent.java
@@ -23,6 +23,7 @@
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.animation.LPaint;
import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
+import com.airbnb.lottie.animation.keyframe.DropShadowKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.FloatKeyframeAnimation;
import com.airbnb.lottie.animation.keyframe.ValueCallbackKeyframeAnimation;
import com.airbnb.lottie.model.KeyPath;
@@ -62,6 +63,7 @@
private final int cacheSteps;
@Nullable private BaseKeyframeAnimation<Float, Float> blurAnimation;
float blurMaskFilterRadius = 0f;
+ @Nullable private DropShadowKeyframeAnimation dropShadowAnimation;
public GradientFillContent(final LottieDrawable lottieDrawable, BaseLayer layer, GradientFill fill) {
this.layer = layer;
@@ -88,13 +90,14 @@
endPointAnimation.addUpdateListener(this);
layer.addAnimation(endPointAnimation);
- if (layer.getBlurEffect() == null) {
- blurAnimation = null;
- } else {
+ if (layer.getBlurEffect() != null) {
blurAnimation = layer.getBlurEffect().getBlurriness().createAnimation();
blurAnimation.addUpdateListener(this);
layer.addAnimation(blurAnimation);
}
+ if (layer.getDropShadowEffect() != null) {
+ dropShadowAnimation = new DropShadowKeyframeAnimation(this, layer, layer.getDropShadowEffect());
+ }
}
@Override public void onValueChanged() {
@@ -145,6 +148,9 @@
}
blurMaskFilterRadius = blurRadius;
}
+ if (dropShadowAnimation != null) {
+ dropShadowAnimation.applyTo(paint);
+ }
int alpha = (int) ((parentAlpha / 255f * opacityAnimation.getValue() / 100f) * 255);
paint.setAlpha(clamp(alpha, 0, 255));
@@ -295,6 +301,16 @@
blurAnimation.addUpdateListener(this);
layer.addAnimation(blurAnimation);
}
+ } else if (property == LottieProperty.DROP_SHADOW_COLOR && dropShadowAnimation != null) {
+ dropShadowAnimation.setColorCallback((LottieValueCallback<Integer>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_OPACITY && dropShadowAnimation != null) {
+ dropShadowAnimation.setOpacityCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_DIRECTION && dropShadowAnimation != null) {
+ dropShadowAnimation.setDirectionCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_DISTANCE && dropShadowAnimation != null) {
+ dropShadowAnimation.setDistanceCallback((LottieValueCallback<Float>) callback);
+ } else if (property == LottieProperty.DROP_SHADOW_RADIUS && dropShadowAnimation != null) {
+ dropShadowAnimation.setRadiusCallback((LottieValueCallback<Float>) callback);
}
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/DropShadowKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/DropShadowKeyframeAnimation.java
new file mode 100644
index 0000000..128913a
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/DropShadowKeyframeAnimation.java
@@ -0,0 +1,100 @@
+package com.airbnb.lottie.animation.keyframe;
+
+import android.graphics.Color;
+import android.graphics.Paint;
+
+import androidx.annotation.Nullable;
+
+import com.airbnb.lottie.model.layer.BaseLayer;
+import com.airbnb.lottie.parser.DropShadowEffect;
+import com.airbnb.lottie.value.LottieFrameInfo;
+import com.airbnb.lottie.value.LottieValueCallback;
+
+public class DropShadowKeyframeAnimation implements BaseKeyframeAnimation.AnimationListener {
+ private static final double DEG_TO_RAD = Math.PI / 180.0;
+
+ private final BaseKeyframeAnimation.AnimationListener listener;
+ private final BaseKeyframeAnimation<Integer, Integer> color;
+ private final BaseKeyframeAnimation<Float, Float> opacity;
+ private final BaseKeyframeAnimation<Float, Float> direction;
+ private final BaseKeyframeAnimation<Float, Float> distance;
+ private final BaseKeyframeAnimation<Float, Float> radius;
+
+ private boolean isDirty = true;
+
+ public DropShadowKeyframeAnimation(BaseKeyframeAnimation.AnimationListener listener, BaseLayer layer, DropShadowEffect dropShadowEffect) {
+ this.listener = listener;
+ color = dropShadowEffect.getColor().createAnimation();
+ color.addUpdateListener(this);
+ layer.addAnimation(color);
+ opacity = dropShadowEffect.getOpacity().createAnimation();
+ opacity.addUpdateListener(this);
+ layer.addAnimation(opacity);
+ direction = dropShadowEffect.getDirection().createAnimation();
+ direction.addUpdateListener(this);
+ layer.addAnimation(direction);
+ distance = dropShadowEffect.getDistance().createAnimation();
+ distance.addUpdateListener(this);
+ layer.addAnimation(distance);
+ radius = dropShadowEffect.getRadius().createAnimation();
+ radius.addUpdateListener(this);
+ layer.addAnimation(radius);
+ }
+
+ @Override public void onValueChanged() {
+ isDirty = true;
+ listener.onValueChanged();
+ }
+
+ public void applyTo(Paint paint) {
+ if (!isDirty) {
+ return;
+ }
+ isDirty = false;
+
+ double directionRad = ((double) direction.getValue()) * DEG_TO_RAD;
+ float distance = this.distance.getValue();
+ float x = ((float) Math.sin(directionRad)) * distance;
+ float y = ((float) Math.cos(directionRad + Math.PI)) * distance;
+ int baseColor = color.getValue();
+ int opacity = Math.round(this.opacity.getValue());
+ int color = Color.argb(opacity, Color.red(baseColor), Color.green(baseColor), Color.blue(baseColor));
+ float radius = this.radius.getValue();
+ paint.setShadowLayer(radius, x, y, color);
+ }
+
+ public void setColorCallback(@Nullable LottieValueCallback<Integer> callback) {
+ color.setValueCallback(callback);
+ }
+
+ public void setOpacityCallback(@Nullable final LottieValueCallback<Float> callback) {
+ if (callback == null) {
+ opacity.setValueCallback(null);
+ return;
+ }
+ opacity.setValueCallback(new LottieValueCallback<Float>() {
+ @Nullable
+ @Override
+ public Float getValue(LottieFrameInfo<Float> frameInfo) {
+ Float value = callback.getValue(frameInfo);
+ if (value == null) {
+ return null;
+ }
+ // Convert [0,100] to [0,255] because other dynamic properties use [0,100].
+ return value * 2.55f;
+ }
+ });
+ }
+
+ public void setDirectionCallback(@Nullable LottieValueCallback<Float> callback) {
+ direction.setValueCallback(callback);
+ }
+
+ public void setDistanceCallback(@Nullable LottieValueCallback<Float> callback) {
+ distance.setValueCallback(callback);
+ }
+
+ public void setRadiusCallback(@Nullable LottieValueCallback<Float> callback) {
+ radius.setValueCallback(callback);
+ }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
index bc496da..c0a1cb1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
@@ -31,6 +31,7 @@
import com.airbnb.lottie.model.content.BlurEffect;
import com.airbnb.lottie.model.content.Mask;
import com.airbnb.lottie.model.content.ShapeData;
+import com.airbnb.lottie.parser.DropShadowEffect;
import com.airbnb.lottie.utils.Logger;
import com.airbnb.lottie.utils.Utils;
import com.airbnb.lottie.value.LottieValueCallback;
@@ -606,6 +607,11 @@
return blurMaskFilter;
}
+ @Nullable
+ public DropShadowEffect getDropShadowEffect() {
+ return layerModel.getDropShadowEffect();
+ }
+
@Override
public void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
// Do nothing
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
index 18d2a95..c20ae75 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
@@ -28,7 +28,7 @@
private final List<BaseLayer> layers = new ArrayList<>();
private final RectF rect = new RectF();
private final RectF newClipRect = new RectF();
- private Paint layerPaint = new Paint();
+ private final Paint layerPaint = new Paint();
@Nullable private Boolean hasMatte;
@Nullable private Boolean hasMasks;
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
index f7f5531..e2fa79d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
@@ -10,6 +10,7 @@
import com.airbnb.lottie.model.content.BlurEffect;
import com.airbnb.lottie.model.content.ContentModel;
import com.airbnb.lottie.model.content.Mask;
+import com.airbnb.lottie.parser.DropShadowEffect;
import com.airbnb.lottie.value.Keyframe;
import java.util.List;
@@ -59,6 +60,7 @@
private final MatteType matteType;
private final boolean hidden;
@Nullable private final BlurEffect blurEffect;
+ @Nullable private final DropShadowEffect dropShadowEffect;
public Layer(List<ContentModel> shapes, LottieComposition composition, String layerName, long layerId,
LayerType layerType, long parentId, @Nullable String refId, List<Mask> masks,
@@ -66,7 +68,8 @@
float timeStretch, float startFrame, int preCompWidth, int preCompHeight,
@Nullable AnimatableTextFrame text, @Nullable AnimatableTextProperties textProperties,
List<Keyframe<Float>> inOutKeyframes, MatteType matteType,
- @Nullable AnimatableFloatValue timeRemapping, boolean hidden, @Nullable BlurEffect blurEffect) {
+ @Nullable AnimatableFloatValue timeRemapping, boolean hidden, @Nullable BlurEffect blurEffect,
+ @Nullable DropShadowEffect dropShadowEffect) {
this.shapes = shapes;
this.composition = composition;
this.layerName = layerName;
@@ -90,6 +93,7 @@
this.timeRemapping = timeRemapping;
this.hidden = hidden;
this.blurEffect = blurEffect;
+ this.dropShadowEffect = dropShadowEffect;
}
LottieComposition getComposition() {
@@ -188,6 +192,10 @@
return blurEffect;
}
+ @Nullable public DropShadowEffect getDropShadowEffect() {
+ return dropShadowEffect;
+ }
+
public String toString(String prefix) {
StringBuilder sb = new StringBuilder();
sb.append(prefix).append(getName()).append("\n");
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
index b8d83a7..4250d8e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/ShapeLayer.java
@@ -13,6 +13,7 @@
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.content.BlurEffect;
import com.airbnb.lottie.model.content.ShapeGroup;
+import com.airbnb.lottie.parser.DropShadowEffect;
import java.util.Collections;
import java.util.List;
@@ -48,6 +49,14 @@
return compositionLayer.getBlurEffect();
}
+ @Nullable @Override public DropShadowEffect getDropShadowEffect() {
+ DropShadowEffect layerDropShadow = super.getDropShadowEffect();
+ if (layerDropShadow != null) {
+ return layerDropShadow;
+ }
+ return compositionLayer.getDropShadowEffect();
+ }
+
@Override
protected void resolveChildKeyPath(KeyPath keyPath, int depth, List<KeyPath> accumulator,
KeyPath currentPartialKeyPath) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffect.java b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffect.java
new file mode 100644
index 0000000..4d15a07
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffect.java
@@ -0,0 +1,41 @@
+package com.airbnb.lottie.parser;
+
+import com.airbnb.lottie.model.animatable.AnimatableColorValue;
+import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
+
+public class DropShadowEffect {
+ private final AnimatableColorValue color;
+ private final AnimatableFloatValue opacity;
+ private final AnimatableFloatValue direction;
+ private final AnimatableFloatValue distance;
+ private final AnimatableFloatValue radius;
+
+ DropShadowEffect(AnimatableColorValue color, AnimatableFloatValue opacity, AnimatableFloatValue direction,
+ AnimatableFloatValue distance, AnimatableFloatValue radius) {
+ this.color = color;
+ this.opacity = opacity;
+ this.direction = direction;
+ this.distance = distance;
+ this.radius = radius;
+ }
+
+ public AnimatableColorValue getColor() {
+ return color;
+ }
+
+ public AnimatableFloatValue getOpacity() {
+ return opacity;
+ }
+
+ public AnimatableFloatValue getDirection() {
+ return direction;
+ }
+
+ public AnimatableFloatValue getDistance() {
+ return distance;
+ }
+
+ public AnimatableFloatValue getRadius() {
+ return radius;
+ }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffectParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffectParser.java
new file mode 100644
index 0000000..e4bb5d8
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/DropShadowEffectParser.java
@@ -0,0 +1,87 @@
+package com.airbnb.lottie.parser;
+
+import androidx.annotation.Nullable;
+
+import com.airbnb.lottie.LottieComposition;
+import com.airbnb.lottie.model.animatable.AnimatableColorValue;
+import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
+import com.airbnb.lottie.parser.moshi.JsonReader;
+
+import java.io.IOException;
+
+public class DropShadowEffectParser {
+
+ private static final JsonReader.Options DROP_SHADOW_EFFECT_NAMES = JsonReader.Options.of(
+ "ef"
+ );
+ private static final JsonReader.Options INNER_EFFECT_NAMES = JsonReader.Options.of(
+ "nm",
+ "v"
+ );
+
+ private AnimatableColorValue color;
+ private AnimatableFloatValue opacity;
+ private AnimatableFloatValue direction;
+ private AnimatableFloatValue distance;
+ private AnimatableFloatValue radius;
+
+ @Nullable
+ DropShadowEffect parse(JsonReader reader, LottieComposition composition) throws IOException {
+ while (reader.hasNext()) {
+ switch (reader.selectName(DROP_SHADOW_EFFECT_NAMES)) {
+ case 0:
+ reader.beginArray();
+ while (reader.hasNext()) {
+ maybeParseInnerEffect(reader, composition);
+ }
+ reader.endArray();
+ break;
+ default:
+ reader.skipName();
+ reader.skipValue();
+ }
+ }
+ if (color != null && opacity != null && direction != null && distance != null && radius != null) {
+ return new DropShadowEffect(color, opacity, direction, distance, radius);
+ }
+ return null;
+ }
+
+ private void maybeParseInnerEffect(JsonReader reader, LottieComposition composition) throws IOException {
+ String currentEffectName = "";
+ reader.beginObject();
+ while (reader.hasNext()) {
+ switch (reader.selectName(INNER_EFFECT_NAMES)) {
+ case 0:
+ currentEffectName = reader.nextString();
+ break;
+ case 1:
+ switch (currentEffectName) {
+ case "Shadow Color":
+ color = AnimatableValueParser.parseColor(reader, composition);
+ break;
+ case "Opacity":
+ opacity = AnimatableValueParser.parseFloat(reader, composition, false);
+ break;
+ case "Direction":
+ direction = AnimatableValueParser.parseFloat(reader, composition, false);
+ break;
+ case "Distance":
+ distance = AnimatableValueParser.parseFloat(reader, composition);
+ break;
+ case "Softness":
+ radius = AnimatableValueParser.parseFloat(reader, composition);
+ break;
+ default:
+ reader.skipValue();
+ break;
+ }
+ break;
+ default:
+ reader.skipName();
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+ }
+}
diff --git a/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java b/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
index 5bd7544..6881a02 100644
--- a/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
+++ b/lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
@@ -59,7 +59,7 @@
Layer.LayerType.PRE_COMP, -1, null, Collections.<Mask>emptyList(),
new AnimatableTransform(), 0, 0, 0, 0, 0,
bounds.width(), bounds.height(), null, null, Collections.<Keyframe<Float>>emptyList(),
- Layer.MatteType.NONE, null, false, null);
+ Layer.MatteType.NONE, null, false, null, null);
}
private static final JsonReader.Options TEXT_NAMES = JsonReader.Options.of(
@@ -92,6 +92,7 @@
String cl = null;
boolean hidden = false;
BlurEffect blurEffect = null;
+ DropShadowEffect dropShadowEffect = null;
Layer.MatteType matteType = Layer.MatteType.NONE;
AnimatableTransform transform = null;
@@ -207,6 +208,8 @@
int type = reader.nextInt();
if (type == 29) {
blurEffect = BlurEffectParser.parse(reader, composition);
+ } else if (type == 25) {
+ dropShadowEffect = new DropShadowEffectParser().parse(reader, composition);
}
break;
case 1:
@@ -284,6 +287,6 @@
return new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId,
masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startFrame,
preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType,
- timeRemapping, hidden, blurEffect);
+ timeRemapping, hidden, blurEffect, dropShadowEffect);
}
}
diff --git a/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt b/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
index 9d1b1b3..92239d6 100644
--- a/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
+++ b/sample/src/androidTest/java/com/airbnb/lottie/samples/LottieTest.kt
@@ -714,6 +714,27 @@
LottieInterpolatedIntegerValue(10, 100),
1f)
+ testDynamicProperty(
+ "Drop Shadow Color",
+ KeyPath("Shape Layer 1", "**"),
+ LottieProperty.DROP_SHADOW_COLOR,
+ LottieValueCallback(Color.RED),
+ assetName = "Tests/AnimatedShadow.json")
+
+ testDynamicProperty(
+ "Drop Shadow Distance",
+ KeyPath("Shape Layer 1", "**"),
+ LottieProperty.DROP_SHADOW_DISTANCE,
+ LottieValueCallback(30f),
+ assetName = "Tests/AnimatedShadow.json")
+
+ testDynamicProperty(
+ "Drop Shadow Distance",
+ KeyPath("Shape Layer 1", "**"),
+ LottieProperty.DROP_SHADOW_DIRECTION,
+ LottieValueCallback(30f),
+ assetName = "Tests/AnimatedShadow.json")
+
withDrawable("Tests/DynamicGradient.json", "Gradient Colors", "Linear Gradient Fill") { drawable ->
val value = object : LottieValueCallback<Array<Int>>() {
override fun getValue(frameInfo: LottieFrameInfo<Array<Int>>?): Array<Int> {
diff --git a/sample/src/main/assets/Tests/AnimatedShadow.json b/sample/src/main/assets/Tests/AnimatedShadow.json
new file mode 100644
index 0000000..ec86bb8
--- /dev/null
+++ b/sample/src/main/assets/Tests/AnimatedShadow.json
@@ -0,0 +1 @@
+{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0,0,0,1]},{"t":151.000006150356,"s":[0,0.371857702732,1,1]}],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[127.5]},{"t":151.000006150356,"s":[127.5]}],"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":151.000006150356,"s":[360]}],"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[10]},{"t":151.000006150356,"s":[15]}],"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[20]},{"t":151.000006150356,"s":[50]}],"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/sample/src/main/assets/Tests/StaticShadow.json b/sample/src/main/assets/Tests/StaticShadow.json
new file mode 100644
index 0000000..e842acd
--- /dev/null
+++ b/sample/src/main/assets/Tests/StaticShadow.json
@@ -0,0 +1 @@
+{"v":"5.7.7","fr":29.9700012207031,"ip":0,"op":181.000007372281,"w":375,"h":375,"nm":"Square","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[187.5,187.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":25,"nm":"Drop Shadow2","np":8,"mn":"ADBE Drop Shadow","ix":1,"en":1,"ef":[{"ty":2,"nm":"Shadow Color","mn":"ADBE Drop Shadow-0001","ix":1,"v":{"a":0,"k":[0,1,0.609851837158,1],"ix":1}},{"ty":0,"nm":"Opacity","mn":"ADBE Drop Shadow-0002","ix":2,"v":{"a":0,"k":127.5,"ix":2}},{"ty":0,"nm":"Direction","mn":"ADBE Drop Shadow-0003","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":0,"nm":"Distance","mn":"ADBE Drop Shadow-0004","ix":4,"v":{"a":0,"k":10,"ix":4}},{"ty":0,"nm":"Softness","mn":"ADBE Drop Shadow-0005","ix":5,"v":{"a":0,"k":20,"ix":5}},{"ty":7,"nm":"Shadow Only","mn":"ADBE Drop Shadow-0006","ix":6,"v":{"a":0,"k":0,"ix":6}}]}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[217.641,217.641],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-4.68,-1.68],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":184.000007494474,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file