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