diff --git a/.gitignore b/.gitignore index 0dbd2e3798..fef2d3e4ce 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ .idea/**/usage.statistics.xml .idea/**/dictionaries .idea/**/shelf -.idea/runConfigurations +.idea/runConfigurations.xml +.idea/caches # Generated files .idea/**/contentModel.xml diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/RoundedCornersContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/RoundedCornersContent.java index d4453be0ef..3d92432a1f 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/content/RoundedCornersContent.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/RoundedCornersContent.java @@ -51,6 +51,10 @@ public BaseKeyframeAnimation getRoundedCorners() { return roundedCorners; } + @Override public void addUpdateListener(BaseKeyframeAnimation.AnimationListener listener) { + roundedCorners.addUpdateListener(listener); + } + /** * Rounded corner algorithm: * Iterate through each vertex. diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java index 0386945800..b2deb2da22 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeContent.java @@ -62,6 +62,7 @@ private void invalidate() { if (shapeModifierContents == null) { shapeModifierContents = new ArrayList<>(); } + ((ShapeModifierContent) content).addUpdateListener(this); shapeModifierContents.add((ShapeModifierContent) content); } } diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeModifierContent.java b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeModifierContent.java index 759ede7f97..3119b58b9e 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeModifierContent.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/content/ShapeModifierContent.java @@ -1,7 +1,9 @@ package com.airbnb.lottie.animation.content; +import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation; import com.airbnb.lottie.model.content.ShapeData; public interface ShapeModifierContent extends Content { + void addUpdateListener(BaseKeyframeAnimation.AnimationListener listener); ShapeData modifyShape(ShapeData shapeData); } diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java index cb63438708..b7e6a407ac 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java @@ -158,7 +158,7 @@ public A getValue() { A value; float linearProgress = getLinearCurrentKeyframeProgress(); - if (valueCallback == null && keyframesWrapper.isCachedValueEnabled(linearProgress)) { + if (valueCallback == null && keyframesWrapper.isCachedValueEnabled(linearProgress) && !skipCache()) { return cachedGetValue; } final Keyframe keyframe = getCurrentKeyframe(); @@ -176,6 +176,10 @@ public A getValue() { return value; } + protected boolean skipCache() { + return false; + } + public float getProgress() { return progress; } diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java index 43cc1857ee..89b01489c2 100644 --- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java +++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/ShapeKeyframeAnimation.java @@ -1,9 +1,7 @@ package com.airbnb.lottie.animation.keyframe; import android.graphics.Path; - import androidx.annotation.Nullable; - import com.airbnb.lottie.animation.content.ShapeModifierContent; import com.airbnb.lottie.model.content.ShapeData; import com.airbnb.lottie.utils.MiscUtils; @@ -23,6 +21,15 @@ public ShapeKeyframeAnimation(List> keyframes) { super(keyframes); } + @Override protected boolean skipCache() { + // If there are shape modifiers but no animation on the shape itself, the shape animation + // will think nothing changed and will keep returning its cached value. + // Ideally, we would have a dirty flag rather than permanently disabling the cache + // when there is a modifier. However, because shape modifiers can be reused across multiple + // other contents, it isn't trivial to know when to flip dirty to false. + return shapeModifiers != null && !shapeModifiers.isEmpty(); + } + @Override public Path getValue(Keyframe keyframe, float keyframeProgress) { ShapeData startShapeData = keyframe.startValue; ShapeData endShapeData = keyframe.endValue; diff --git a/snapshot-tests/src/main/assets/Tests/RoundedCornersOnlyAnimation.json b/snapshot-tests/src/main/assets/Tests/RoundedCornersOnlyAnimation.json new file mode 100644 index 0000000000..77aab5398c --- /dev/null +++ b/snapshot-tests/src/main/assets/Tests/RoundedCornersOnlyAnimation.json @@ -0,0 +1 @@ +{"v":"5.12.2","fr":30,"ip":0,"op":30,"w":500,"h":500,"nm":"closedpath","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"closed","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[350,272,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,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-125,-97],[-215,-17],[-135,52],[-56,-19]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"圆角 1","r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":29,"s":[46]}],"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0.004289215896,0.004289215896,0.004289215896,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"bg","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2,"l":2},"a":{"a":0,"k":[250,250,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"sw":500,"sh":500,"sc":"#ffffff","ip":0,"op":30,"st":0,"bm":0}],"markers":[],"props":{}} \ No newline at end of file