Cleaned up LottieValueAnimator classes (#608)

Reduced the number of LottieValueCallback classes and added optional constructor initialization.
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java b/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java
index 1d6d152..d110ee0 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java
@@ -17,10 +17,9 @@
 
 import com.airbnb.happo.SnapshotProvider;
 import com.airbnb.lottie.model.KeyPath;
-import com.airbnb.lottie.value.LottieStaticInterpolatedIntegerValue;
-import com.airbnb.lottie.value.LottieStaticRelativeFloatValue;
-import com.airbnb.lottie.value.LottieStaticRelativePointValue;
-import com.airbnb.lottie.value.LottieStaticValue;
+import com.airbnb.lottie.value.LottieInterpolatedIntegerValue;
+import com.airbnb.lottie.value.LottieRelativeFloatValueCallback;
+import com.airbnb.lottie.value.LottieRelativePointValueCallback;
 import com.airbnb.lottie.value.LottieValueCallback;
 import com.airbnb.lottie.value.ScaleXY;
 
@@ -219,225 +218,223 @@
   }
 
   private void testDynamicProperties() {
-    LottieStaticValue<Integer> value = new LottieStaticValue<>(Color.GREEN);
     testDynamicProperty(
         "Fill color (Green)",
         new KeyPath("Shape Layer 1", "Rectangle", "Fill 1"),
         LottieProperty.COLOR,
-        value);
+        new LottieValueCallback<>(Color.GREEN));
 
-    value.setValue(Color.YELLOW);
     testDynamicProperty(
         "Fill color (Yellow)",
         new KeyPath("Shape Layer 1", "Rectangle", "Fill 1"),
         LottieProperty.COLOR,
-        value);
+        new LottieValueCallback<>(Color.YELLOW));
 
     testDynamicProperty(
         "Fill opacity",
         new KeyPath("Shape Layer 1", "Rectangle", "Fill 1"),
         LottieProperty.OPACITY,
-        new LottieStaticValue<>(50));
+        new LottieValueCallback<>(50));
 
     testDynamicProperty(
         "Stroke color",
         new KeyPath("Shape Layer 1", "Rectangle", "Stroke 1"),
         LottieProperty.STROKE_COLOR,
-        new LottieStaticValue<>(Color.GREEN));
+        new LottieValueCallback<>(Color.GREEN));
 
     testDynamicProperty(
         "Stroke width",
         new KeyPath("Shape Layer 1", "Rectangle", "Stroke 1"),
         LottieProperty.STROKE_WIDTH,
-        new LottieStaticRelativeFloatValue(50f));
+        new LottieRelativeFloatValueCallback(50f));
 
     testDynamicProperty(
         "Stroke opacity",
         new KeyPath("Shape Layer 1", "Rectangle", "Stroke 1"),
         LottieProperty.OPACITY,
-        new LottieStaticValue<>(50));
+        new LottieValueCallback<>(50));
 
     testDynamicProperty(
         "Transform anchor point",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_ANCHOR_POINT,
-        new LottieStaticRelativePointValue(new PointF(20f, 20f)));
+        new LottieRelativePointValueCallback(new PointF(20f, 20f)));
 
     testDynamicProperty(
         "Transform position",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_POSITION,
-        new LottieStaticRelativePointValue(new PointF(20f, 20f)));
+        new LottieRelativePointValueCallback(new PointF(20f, 20f)));
 
     testDynamicProperty(
         "Transform position (relative)",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_POSITION,
-        new LottieStaticRelativePointValue(new PointF(20f, 20f)));
+        new LottieRelativePointValueCallback(new PointF(20f, 20f)));
 
     testDynamicProperty(
         "Transform opacity",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_OPACITY,
-        new LottieStaticValue<>(50));
+        new LottieValueCallback<>(50));
 
     testDynamicProperty(
         "Transform rotation",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_ROTATION,
-        new LottieStaticValue<>(45f));
+        new LottieValueCallback<>(45f));
 
     testDynamicProperty(
         "Transform scale",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_SCALE,
-        new LottieStaticValue<>(new ScaleXY(0.5f, 0.5f)));
+        new LottieValueCallback<>(new ScaleXY(0.5f, 0.5f)));
 
     testDynamicProperty(
         "Ellipse position",
         new KeyPath("Shape Layer 1", "Ellipse", "Ellipse Path 1"),
         LottieProperty.POSITION,
-        new LottieStaticRelativePointValue(new PointF(20f, 20f)));
+        new LottieRelativePointValueCallback(new PointF(20f, 20f)));
 
     testDynamicProperty(
         "Ellipse size",
         new KeyPath("Shape Layer 1", "Ellipse", "Ellipse Path 1"),
         LottieProperty.ELLIPSE_SIZE,
-        new LottieStaticRelativePointValue(new PointF(40f, 60f)));
+        new LottieRelativePointValueCallback(new PointF(40f, 60f)));
 
     testDynamicProperty(
         "Star points",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POLYSTAR_POINTS,
-        new LottieStaticValue<>(8f));
+        new LottieValueCallback<>(8f));
 
     testDynamicProperty(
         "Star rotation",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POLYSTAR_ROTATION,
-        new LottieStaticValue<>(10f));
+        new LottieValueCallback<>(10f));
 
     testDynamicProperty(
         "Star position",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POSITION,
-        new LottieStaticRelativePointValue(new PointF(20f, 20f)));
+        new LottieRelativePointValueCallback(new PointF(20f, 20f)));
 
     testDynamicProperty(
         "Star inner radius",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POLYSTAR_INNER_RADIUS,
-        new LottieStaticValue<>(10f));
+        new LottieValueCallback<>(10f));
 
     testDynamicProperty(
         "Star inner roundedness",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POLYSTAR_INNER_ROUNDEDNESS,
-        new LottieStaticValue<>(100f));
+        new LottieValueCallback<>(100f));
 
     testDynamicProperty(
         "Star outer radius",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POLYSTAR_OUTER_RADIUS,
-        new LottieStaticValue<>(60f));
+        new LottieValueCallback<>(60f));
 
     testDynamicProperty(
         "Star outer roundedness",
         new KeyPath("Shape Layer 1", "Star", "Polystar Path 1"),
         LottieProperty.POLYSTAR_OUTER_ROUNDEDNESS,
-        new LottieStaticValue<>(100f));
+        new LottieValueCallback<>(100f));
 
     testDynamicProperty(
         "Polygon points",
         new KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"),
         LottieProperty.POLYSTAR_POINTS,
-        new LottieStaticValue<>(8f));
+        new LottieValueCallback<>(8f));
 
     testDynamicProperty(
         "Polygon rotation",
         new KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"),
         LottieProperty.POLYSTAR_ROTATION,
-        new LottieStaticValue<>(10f));
+        new LottieValueCallback<>(10f));
 
     testDynamicProperty(
         "Polygon position",
         new KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"),
         LottieProperty.POSITION,
-        new LottieStaticRelativePointValue(new PointF(20f, 20f)));
+        new LottieRelativePointValueCallback(new PointF(20f, 20f)));
 
     testDynamicProperty(
         "Polygon radius",
         new KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"),
         LottieProperty.POLYSTAR_OUTER_RADIUS,
-        new LottieStaticRelativeFloatValue(60f));
+        new LottieRelativeFloatValueCallback(60f));
 
     testDynamicProperty(
         "Polygon roundedness",
         new KeyPath("Shape Layer 1", "Polygon", "Polystar Path 1"),
         LottieProperty.POLYSTAR_OUTER_ROUNDEDNESS,
-        new LottieStaticValue<>(100f));
+        new LottieValueCallback<>(100f));
 
     testDynamicProperty(
         "Repeater transform position",
         new KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"),
         LottieProperty.TRANSFORM_POSITION,
-        new LottieStaticRelativePointValue(new PointF(100f, 100f)));
+        new LottieRelativePointValueCallback(new PointF(100f, 100f)));
 
     testDynamicProperty(
         "Repeater transform start opacity",
         new KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"),
         LottieProperty.TRANSFORM_START_OPACITY,
-        new LottieStaticValue<>(25f));
+        new LottieValueCallback<>(25f));
 
     testDynamicProperty(
         "Repeater transform end opacity",
         new KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"),
         LottieProperty.TRANSFORM_END_OPACITY,
-        new LottieStaticValue<>(25f));
+        new LottieValueCallback<>(25f));
 
     testDynamicProperty(
         "Repeater transform rotation",
         new KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"),
         LottieProperty.TRANSFORM_ROTATION,
-        new LottieStaticValue<>(45f));
+        new LottieValueCallback<>(45f));
 
     testDynamicProperty(
         "Repeater transform scale",
         new KeyPath("Shape Layer 1", "Repeater Shape", "Repeater 1"),
         LottieProperty.TRANSFORM_SCALE,
-        new LottieStaticValue<>(new ScaleXY(2f, 2f)));
+        new LottieValueCallback<>(new ScaleXY(2f, 2f)));
 
     testDynamicProperty(
         "Time remapping",
         new KeyPath("Circle 1"),
         LottieProperty.TIME_REMAP,
-        new LottieStaticValue<>(1f));
+        new LottieValueCallback<>(1f));
 
     testDynamicProperty(
         "Color Filter",
         new KeyPath("**"),
         LottieProperty.COLOR_FILTER,
-        new LottieStaticValue<ColorFilter>(new SimpleColorFilter(Color.GREEN)));
+        new LottieValueCallback<ColorFilter>(new SimpleColorFilter(Color.GREEN)));
 
     testDynamicProperty(
         "Opacity interpolation (0)",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_OPACITY,
-        new LottieStaticInterpolatedIntegerValue(10, 100),
+        new LottieInterpolatedIntegerValue(10, 100),
         0f);
 
     testDynamicProperty(
         "Opacity interpolation (0.5)",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_OPACITY,
-        new LottieStaticInterpolatedIntegerValue(10, 100),
+        new LottieInterpolatedIntegerValue(10, 100),
         0.5f);
 
     testDynamicProperty(
         "Opacity interpolation (1)",
         new KeyPath("Shape Layer 1", "Rectangle"),
         LottieProperty.TRANSFORM_OPACITY,
-        new LottieStaticInterpolatedIntegerValue(10, 100),
+        new LottieInterpolatedIntegerValue(10, 100),
         1f);
   }
 
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
index b617b78..24a0826 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java
@@ -25,7 +25,6 @@
 import com.airbnb.lottie.model.KeyPath;
 import com.airbnb.lottie.utils.Utils;
 import com.airbnb.lottie.value.LottieFrameInfo;
-import com.airbnb.lottie.value.LottieStaticValue;
 import com.airbnb.lottie.value.LottieValueCallback;
 import com.airbnb.lottie.value.SimpleLottieValueCallback;
 
@@ -160,8 +159,7 @@
       SimpleColorFilter filter = new SimpleColorFilter(
           ta.getColor(R.styleable.LottieAnimationView_lottie_colorFilter, Color.TRANSPARENT));
       KeyPath keyPath = new KeyPath("**");
-      LottieStaticValue<ColorFilter> callback =
-          new LottieStaticValue<ColorFilter>(filter);
+      LottieValueCallback<ColorFilter> callback = new LottieValueCallback<ColorFilter>(filter);
       addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback);
     }
     if (ta.hasValue(R.styleable.LottieAnimationView_lottie_scale)) {
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedFloatValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedFloatValue.java
similarity index 61%
rename from lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedFloatValue.java
rename to lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedFloatValue.java
index b555534..3e96dbf 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedFloatValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedFloatValue.java
@@ -4,13 +4,14 @@
 
 import com.airbnb.lottie.utils.MiscUtils;
 
-public class LottieStaticInterpolatedFloatValue extends LottieStaticInterpolatedValue<Float> {
+@SuppressWarnings("unused")
+public class LottieInterpolatedFloatValue extends LottieInterpolatedValue<Float> {
 
-  public LottieStaticInterpolatedFloatValue(Float startValue, Float endValue) {
+  public LottieInterpolatedFloatValue(Float startValue, Float endValue) {
     super(startValue, endValue);
   }
 
-  public LottieStaticInterpolatedFloatValue(Float startValue, Float endValue,
+  public LottieInterpolatedFloatValue(Float startValue, Float endValue,
       Interpolator interpolator) {
     super(startValue, endValue, interpolator);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedIntegerValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedIntegerValue.java
similarity index 60%
rename from lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedIntegerValue.java
rename to lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedIntegerValue.java
index c64f6fb..3f41d89 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedIntegerValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedIntegerValue.java
@@ -4,13 +4,14 @@
 
 import com.airbnb.lottie.utils.MiscUtils;
 
-public class LottieStaticInterpolatedIntegerValue extends LottieStaticInterpolatedValue<Integer> {
+@SuppressWarnings("unused")
+public class LottieInterpolatedIntegerValue extends LottieInterpolatedValue<Integer> {
 
-  public LottieStaticInterpolatedIntegerValue(Integer startValue, Integer endValue) {
+  public LottieInterpolatedIntegerValue(Integer startValue, Integer endValue) {
     super(startValue, endValue);
   }
 
-  public LottieStaticInterpolatedIntegerValue(Integer startValue, Integer endValue,
+  public LottieInterpolatedIntegerValue(Integer startValue, Integer endValue,
       Interpolator interpolator) {
     super(startValue, endValue, interpolator);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedPointValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedPointValue.java
similarity index 69%
rename from lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedPointValue.java
rename to lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedPointValue.java
index a553837..0488895 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedPointValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedPointValue.java
@@ -5,14 +5,15 @@
 
 import com.airbnb.lottie.utils.MiscUtils;
 
-public class LottieStaticInterpolatedPointValue extends LottieStaticInterpolatedValue<PointF> {
+@SuppressWarnings("unused")
+public class LottieInterpolatedPointValue extends LottieInterpolatedValue<PointF> {
   private final PointF point = new PointF();
 
-  public LottieStaticInterpolatedPointValue(PointF startValue, PointF endValue) {
+  public LottieInterpolatedPointValue(PointF startValue, PointF endValue) {
     super(startValue, endValue);
   }
 
-  public LottieStaticInterpolatedPointValue(PointF startValue, PointF endValue,
+  public LottieInterpolatedPointValue(PointF startValue, PointF endValue,
       Interpolator interpolator) {
     super(startValue, endValue, interpolator);
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedValue.java
similarity index 75%
rename from lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedValue.java
rename to lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedValue.java
index f80370b..99788e5 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticInterpolatedValue.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieInterpolatedValue.java
@@ -3,17 +3,17 @@
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 
-abstract class LottieStaticInterpolatedValue<T> extends LottieValueCallback<T> {
+abstract class LottieInterpolatedValue<T> extends LottieValueCallback<T> {
 
   private final T startValue;
   private final T endValue;
   private final Interpolator interpolator;
 
-  LottieStaticInterpolatedValue(T startValue, T endValue) {
+  LottieInterpolatedValue(T startValue, T endValue) {
     this(startValue, endValue, new LinearInterpolator());
   }
 
-  LottieStaticInterpolatedValue(T startValue, T endValue, Interpolator interpolator) {
+  LottieInterpolatedValue(T startValue, T endValue, Interpolator interpolator) {
     this.startValue = startValue;
     this.endValue = endValue;
     this.interpolator = interpolator;
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeFloatValueCallback.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeFloatValueCallback.java
index 4836b7a..a2db77e 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeFloatValueCallback.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeFloatValueCallback.java
@@ -1,12 +1,23 @@
 package com.airbnb.lottie.value;
 
+import android.support.annotation.NonNull;
+
 import com.airbnb.lottie.utils.MiscUtils;
 
 /**
  * {@link LottieValueCallback} that provides a value offset from the original animation
  * rather than an absolute value.
  */
-public abstract class LottieRelativeFloatValueCallback extends LottieValueCallback<Float> {
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class LottieRelativeFloatValueCallback extends LottieValueCallback<Float> {
+
+  public LottieRelativeFloatValueCallback() {
+  }
+
+  public LottieRelativeFloatValueCallback(@NonNull Float staticValue) {
+    super(staticValue);
+  }
+
   @Override
   public Float getValue(LottieFrameInfo<Float> frameInfo) {
     float originalValue = MiscUtils.lerp(
@@ -18,5 +29,11 @@
     return originalValue + offset;
   }
 
-  public abstract Float getOffset(LottieFrameInfo<Float> frameInfo);
+  public Float getOffset(LottieFrameInfo<Float> frameInfo) {
+    if (value == null) {
+      throw new IllegalArgumentException("You must provide a static value in the constructor " +
+          ", call setValue, or override getValue.");
+    }
+    return value;
+  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeIntegerValueCallback.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeIntegerValueCallback.java
index 6cea324..4444ecf 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeIntegerValueCallback.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativeIntegerValueCallback.java
@@ -6,7 +6,8 @@
  * {@link LottieValueCallback} that provides a value offset from the original animation
  * rather than an absolute value.
  */
-public abstract class LottieRelativeIntegerValueCallback extends LottieValueCallback<Integer> {
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class LottieRelativeIntegerValueCallback extends LottieValueCallback<Integer> {
   @Override
   public Integer getValue(LottieFrameInfo<Integer> frameInfo) {
     int originalValue = MiscUtils.lerp(
@@ -18,5 +19,14 @@
     return originalValue + newValue;
   }
 
-  public abstract Integer getOffset(LottieFrameInfo<Integer> frameInfo);
+  /**
+   * Override this to provide your own offset on every frame.
+   */
+  public Integer getOffset(LottieFrameInfo<Integer> frameInfo) {
+    if (value == null) {
+      throw new IllegalArgumentException("You must provide a static value in the constructor " +
+          ", call setValue, or override getValue.");
+    }
+    return value;
+  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativePointValueCallback.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativePointValueCallback.java
index 64ca55a..ed49510 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativePointValueCallback.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieRelativePointValueCallback.java
@@ -1,6 +1,7 @@
 package com.airbnb.lottie.value;
 
 import android.graphics.PointF;
+import android.support.annotation.NonNull;
 
 import com.airbnb.lottie.utils.MiscUtils;
 
@@ -8,9 +9,17 @@
  * {@link LottieValueCallback} that provides a value offset from the original animation
  * rather than an absolute value.
  */
-public abstract class LottieRelativePointValueCallback extends LottieValueCallback<PointF> {
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class LottieRelativePointValueCallback extends LottieValueCallback<PointF> {
   private final PointF point = new PointF();
 
+  public LottieRelativePointValueCallback() {
+  }
+
+  public LottieRelativePointValueCallback(@NonNull PointF staticValue) {
+    super(staticValue);
+  }
+
   @Override
   public final PointF getValue(LottieFrameInfo<PointF> frameInfo) {
     point.set(
@@ -29,5 +38,14 @@
     return point;
   }
 
-  public abstract PointF getOffset(LottieFrameInfo<PointF> frameInfo);
+  /**
+   * Override this to provide your own offset on every frame.
+   */
+  public PointF getOffset(LottieFrameInfo<PointF> frameInfo) {
+    if (value == null) {
+      throw new IllegalArgumentException("You must provide a static value in the constructor " +
+          ", call setValue, or override getValue.");
+    }
+    return value;
+  }
 }
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativeFloatValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativeFloatValue.java
deleted file mode 100644
index 92e776f..0000000
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativeFloatValue.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.airbnb.lottie.value;
-
-/**
- * Static value version of {@link LottieRelativeFloatValueCallback}.
- */
-public class LottieStaticRelativeFloatValue extends LottieRelativeFloatValueCallback {
-
-  private final float offset;
-
-  public LottieStaticRelativeFloatValue(float offset) {
-    this.offset = offset;
-  }
-
-  @Override
-  public Float getOffset(LottieFrameInfo<Float> frameInfo) {
-    return offset;
-  }
-}
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativeIntegerValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativeIntegerValue.java
deleted file mode 100644
index da66a3e..0000000
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativeIntegerValue.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.airbnb.lottie.value;
-
-/**
- * Static value version of {@link LottieRelativeIntegerValueCallback}.
- */
-public class LottieStaticRelativeIntegerValue extends LottieRelativeIntegerValueCallback {
-
-  private final Integer offset;
-
-  public LottieStaticRelativeIntegerValue(Integer offset) {
-    this.offset = offset;
-  }
-
-
-  @Override
-  public Integer getOffset(LottieFrameInfo<Integer> frameInfo) {
-    return offset;
-  }
-}
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativePointValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativePointValue.java
deleted file mode 100644
index bcf94f1..0000000
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticRelativePointValue.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.airbnb.lottie.value;
-
-import android.graphics.PointF;
-
-/**
- * Static value version of {@link LottieRelativePointValueCallback}.
- */
-public class LottieStaticRelativePointValue extends LottieRelativePointValueCallback {
-
-  private final PointF offset;
-
-  public LottieStaticRelativePointValue(PointF offset) {
-    this.offset = offset;
-  }
-
-  @Override
-  public PointF getOffset(LottieFrameInfo<PointF> frameInfo) {
-    return offset;
-  }
-}
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticValue.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticValue.java
deleted file mode 100644
index 47d8c05..0000000
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieStaticValue.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.airbnb.lottie.value;
-
-public class LottieStaticValue<T> extends LottieValueCallback<T> {
-
-  private final T value;
-
-  public LottieStaticValue(T value) {
-    this.value = value;
-  }
-
-  @Override public T getValue(LottieFrameInfo<T> frameInfo) {
-    return value;
-  }
-}
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/LottieValueCallback.java b/lottie/src/main/java/com/airbnb/lottie/value/LottieValueCallback.java
index 0a16bd4..fb1fb77 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/LottieValueCallback.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/LottieValueCallback.java
@@ -10,8 +10,6 @@
 /**
  * Allows you to set a callback on a resolved {@link com.airbnb.lottie.model.KeyPath} to modify
  * its animation values at runtime.
- *
- * This API is not ready for public use yet.
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class LottieValueCallback<T> {
@@ -22,7 +20,7 @@
    * This can be set with {@link #setValue(Object)} to use a value instead of deferring
    * to the callback.
    **/
-  @Nullable private T value = null;
+  @Nullable protected T value = null;
 
   public LottieValueCallback() {
   }
@@ -59,9 +57,6 @@
       float interpolatedKeyframeProgress,
       float overallProgress
   ) {
-    if (value != null) {
-      return value;
-    }
     return getValue(
         frameInfo.set(
             startFrame,
diff --git a/lottie/src/main/java/com/airbnb/lottie/value/SimpleLottieValueCallback.java b/lottie/src/main/java/com/airbnb/lottie/value/SimpleLottieValueCallback.java
index 7b40c98..70b6608 100644
--- a/lottie/src/main/java/com/airbnb/lottie/value/SimpleLottieValueCallback.java
+++ b/lottie/src/main/java/com/airbnb/lottie/value/SimpleLottieValueCallback.java
@@ -1,5 +1,10 @@
 package com.airbnb.lottie.value;
 
+/**
+ * Delegate interface for {@link LottieValueCallback}. This is helpful for the Kotlin API because you can use a SAM conversion to write the
+ * callback as a single abstract method block like this:
+ * animationView.addValueCallback(keyPath, LottieProperty.TRANSFORM_OPACITY) { 50 }
+ */
 public interface SimpleLottieValueCallback<T> {
   T getValue(LottieFrameInfo<T> frameInfo);
 }