• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.airbnb.lottie.value;
2 
3 import android.graphics.PointF;
4 import android.view.animation.Interpolator;
5 
6 import androidx.annotation.FloatRange;
7 import androidx.annotation.Nullable;
8 
9 import com.airbnb.lottie.LottieComposition;
10 
11 public class Keyframe<T> {
12   private static final float UNSET_FLOAT = -3987645.78543923f;
13   private static final int UNSET_INT = 784923401;
14 
15   @Nullable private final LottieComposition composition;
16   @Nullable public final T startValue;
17   @Nullable public T endValue;
18   @Nullable public final Interpolator interpolator;
19   @Nullable public final Interpolator xInterpolator;
20   @Nullable public final Interpolator yInterpolator;
21   public final float startFrame;
22   @Nullable public Float endFrame;
23 
24   private float startValueFloat = UNSET_FLOAT;
25   private float endValueFloat = UNSET_FLOAT;
26 
27   private int startValueInt = UNSET_INT;
28   private int endValueInt = UNSET_INT;
29 
30   private float startProgress = Float.MIN_VALUE;
31   private float endProgress = Float.MIN_VALUE;
32 
33   // Used by PathKeyframe but it has to be parsed by KeyFrame because we use a JsonReader to
34   // deserialzie the data so we have to parse everything in order
35   public PointF pathCp1 = null;
36   public PointF pathCp2 = null;
37 
38 
Keyframe(@uppressWarnings"NullableProblems") LottieComposition composition, @Nullable T startValue, @Nullable T endValue, @Nullable Interpolator interpolator, float startFrame, @Nullable Float endFrame)39   public Keyframe(@SuppressWarnings("NullableProblems") LottieComposition composition,
40       @Nullable T startValue, @Nullable T endValue,
41       @Nullable Interpolator interpolator, float startFrame, @Nullable Float endFrame) {
42     this.composition = composition;
43     this.startValue = startValue;
44     this.endValue = endValue;
45     this.interpolator = interpolator;
46     xInterpolator = null;
47     yInterpolator = null;
48     this.startFrame = startFrame;
49     this.endFrame = endFrame;
50   }
51 
Keyframe(@uppressWarnings"NullableProblems") LottieComposition composition, @Nullable T startValue, @Nullable T endValue, @Nullable Interpolator xInterpolator, @Nullable Interpolator yInterpolator, float startFrame, @Nullable Float endFrame)52   public Keyframe(@SuppressWarnings("NullableProblems") LottieComposition composition,
53       @Nullable T startValue, @Nullable T endValue,
54       @Nullable Interpolator xInterpolator, @Nullable Interpolator yInterpolator, float startFrame, @Nullable Float endFrame) {
55     this.composition = composition;
56     this.startValue = startValue;
57     this.endValue = endValue;
58     interpolator = null;
59     this.xInterpolator = xInterpolator;
60     this.yInterpolator = yInterpolator;
61     this.startFrame = startFrame;
62     this.endFrame = endFrame;
63   }
64 
Keyframe(@uppressWarnings"NullableProblems") LottieComposition composition, @Nullable T startValue, @Nullable T endValue, @Nullable Interpolator interpolator, @Nullable Interpolator xInterpolator, @Nullable Interpolator yInterpolator, float startFrame, @Nullable Float endFrame)65   protected Keyframe(@SuppressWarnings("NullableProblems") LottieComposition composition,
66       @Nullable T startValue, @Nullable T endValue,
67       @Nullable Interpolator interpolator, @Nullable Interpolator xInterpolator, @Nullable Interpolator yInterpolator,
68       float startFrame, @Nullable Float endFrame) {
69     this.composition = composition;
70     this.startValue = startValue;
71     this.endValue = endValue;
72     this.interpolator = interpolator;
73     this.xInterpolator = xInterpolator;
74     this.yInterpolator = yInterpolator;
75     this.startFrame = startFrame;
76     this.endFrame = endFrame;
77   }
78 
79   /**
80    * Non-animated value.
81    */
Keyframe(@uppressWarnings"NullableProblems") T value)82   public Keyframe(@SuppressWarnings("NullableProblems") T value) {
83     composition = null;
84     startValue = value;
85     endValue = value;
86     interpolator = null;
87     xInterpolator = null;
88     yInterpolator = null;
89     startFrame = Float.MIN_VALUE;
90     endFrame = Float.MAX_VALUE;
91   }
92 
getStartProgress()93   public float getStartProgress() {
94     if (composition == null) {
95       return 0f;
96     }
97     if (startProgress == Float.MIN_VALUE) {
98       startProgress = (startFrame - composition.getStartFrame()) / composition.getDurationFrames();
99     }
100     return startProgress;
101   }
102 
getEndProgress()103   public float getEndProgress() {
104     if (composition == null) {
105       return 1f;
106     }
107     if (endProgress == Float.MIN_VALUE) {
108       if (endFrame == null) {
109         endProgress = 1f;
110       } else {
111         float startProgress = getStartProgress();
112         float durationFrames = endFrame - startFrame;
113         float durationProgress = durationFrames / composition.getDurationFrames();
114         endProgress = startProgress + durationProgress;
115       }
116     }
117     return endProgress;
118   }
119 
isStatic()120   public boolean isStatic() {
121     return interpolator == null && xInterpolator == null && yInterpolator == null;
122   }
123 
containsProgress(@loatRangefrom = 0f, to = 1f) float progress)124   public boolean containsProgress(@FloatRange(from = 0f, to = 1f) float progress) {
125     return progress >= getStartProgress() && progress < getEndProgress();
126   }
127 
128   /**
129    * Optimization to avoid autoboxing.
130    */
getStartValueFloat()131   public float getStartValueFloat() {
132     if (startValueFloat == UNSET_FLOAT) {
133       startValueFloat = (float) (Float) startValue;
134     }
135     return startValueFloat;
136   }
137 
138   /**
139    * Optimization to avoid autoboxing.
140    */
getEndValueFloat()141   public float getEndValueFloat() {
142     if (endValueFloat == UNSET_FLOAT) {
143       endValueFloat = (float) (Float) endValue;
144     }
145     return endValueFloat;
146   }
147 
148   /**
149    * Optimization to avoid autoboxing.
150    */
getStartValueInt()151   public int getStartValueInt() {
152     if (startValueInt == UNSET_INT) {
153       startValueInt = (int) (Integer) startValue;
154     }
155     return startValueInt;
156   }
157 
158   /**
159    * Optimization to avoid autoboxing.
160    */
getEndValueInt()161   public int getEndValueInt() {
162     if (endValueInt == UNSET_INT) {
163       endValueInt = (int) (Integer) endValue;
164     }
165     return endValueInt;
166   }
167 
toString()168   @Override public String toString() {
169     return "Keyframe{" + "startValue=" + startValue +
170         ", endValue=" + endValue +
171         ", startFrame=" + startFrame +
172         ", endFrame=" + endFrame +
173         ", interpolator=" + interpolator +
174         '}';
175   }
176 }
177