Skip to content

Commit

Permalink
Fix rounded corner animations when the underlying shape doesn't anima…
Browse files Browse the repository at this point in the history
…te (#2567)

Previously, if there was a rounded corners animation but no animation on the shape, the shape would never be marked as dirty and would keep returning the cached value.

#2561
  • Loading branch information
gpeal authored Oct 27, 2024
1 parent 39796b3 commit e3a8fce
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
.idea/runConfigurations
.idea/runConfigurations.xml
.idea/caches

# Generated files
.idea/**/contentModel.xml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public BaseKeyframeAnimation<Float, Float> getRoundedCorners() {
return roundedCorners;
}

@Override public void addUpdateListener(BaseKeyframeAnimation.AnimationListener listener) {
roundedCorners.addUpdateListener(listener);
}

/**
* Rounded corner algorithm:
* Iterate through each vertex.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ private void invalidate() {
if (shapeModifierContents == null) {
shapeModifierContents = new ArrayList<>();
}
((ShapeModifierContent) content).addUpdateListener(this);
shapeModifierContents.add((ShapeModifierContent) content);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<K> keyframe = getCurrentKeyframe();
Expand All @@ -176,6 +176,10 @@ public A getValue() {
return value;
}

protected boolean skipCache() {
return false;
}

public float getProgress() {
return progress;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -23,6 +21,15 @@ public ShapeKeyframeAnimation(List<Keyframe<ShapeData>> 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<ShapeData> keyframe, float keyframeProgress) {
ShapeData startShapeData = keyframe.startValue;
ShapeData endShapeData = keyframe.endValue;
Expand Down
Original file line number Diff line number Diff line change
@@ -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":{}}

0 comments on commit e3a8fce

Please sign in to comment.