Two value animator fixes (#717)

* Take into account start and end frames for min and max progress
* Remove the frame callback before notifying the end listeners so that if they start an animation, the notification frame will not be removed.
Fixes #703
Fixes #663
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java b/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java
index e2c5b4d..c4c87eb 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/LottieSnapshotProvider.java
@@ -73,6 +73,7 @@
     testScaleTypes();
     testDynamicProperties();
     testSwitchingToDrawableAndBack();
+    testStartEndFrameWithStartEndProgress();
   }
 
   private void snapshotAssets(String[] animations) {
@@ -492,6 +493,35 @@
     recordSnapshot(view, 1080, "android", "Reset Animation", "Drawable and back", params);
   }
 
+  private void testStartEndFrameWithStartEndProgress() {
+    LottieComposition composition = LottieComposition.Factory.fromFileSync(context, "Tests/StartEndFrame.json");
+    LottieAnimationView view = new LottieAnimationView(context);
+    view.setComposition(composition);
+    ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
+        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+    view.setMinProgress(0f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "minProgress 0", params);
+    view.setMinProgress(0.25f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "minProgress 0.25", params);
+    view.setMinProgress(0.75f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "minProgress 0.75", params);
+    view.setMinProgress(0.1f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "minProgress 1", params);
+
+    view.setMaxProgress(0f);
+    view.setProgress(1f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "maxProgress 0", params);
+    view.setMaxProgress(0.25f);
+    view.setProgress(1f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "maxProgress 0.25", params);
+    view.setMaxProgress(0.75f);
+    view.setProgress(1f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "maxProgress 0.75", params);
+    view.setMaxProgress(0.1f);
+    view.setProgress(1f);
+    recordSnapshot(view, 1080, "android", "MinMaxFrame", "maxProgress 1", params);
+  }
+
   private int dpToPx(int dp) {
     Resources resources = context.getResources();
     return (int) TypedValue.applyDimension(1, (float) dp, resources.getDisplayMetrics());
diff --git a/LottieSample/src/main/assets/Tests/StartEndFrame.json b/LottieSample/src/main/assets/Tests/StartEndFrame.json
new file mode 100644
index 0000000..02cbe2c
--- /dev/null
+++ b/LottieSample/src/main/assets/Tests/StartEndFrame.json
@@ -0,0 +1 @@
+{"v":"4.11.1","fr":60,"ip":61,"op":119,"w":300,"h":300,"nm":"Move","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[67.637,61.285],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.928262987324,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[-115.346,-117.271],"e":[116.564,118.85],"to":[38.6516914367676,39.353515625],"ti":[-38.6516914367676,-39.353515625]},{"t":179}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":1,"nm":"Cyan Solid 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[150,150,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sw":300,"sh":300,"sc":"#00ffff","ip":0,"op":180,"st":0,"bm":0}]}
\ No newline at end of file
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index fc33535..edc115b 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -393,7 +393,7 @@
        });
        return;
      }
-    setMinFrame((int) (minProgress * composition.getDurationFrames()));
+   setMinFrame((int) MiscUtils.lerp(minProgress, composition.getStartFrame(), composition.getEndFrame()));
   }
 
   /**
@@ -422,7 +422,7 @@
       });
       return;
     }
-    setMaxFrame((int) (maxProgress * composition.getDurationFrames()));
+    setMaxFrame((int) MiscUtils.lerp(maxProgress, composition.getStartFrame(), composition.getEndFrame()));
   }
 
   /**
diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java b/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java
index 7db74ef..b78c76a 100644
--- a/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java
+++ b/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java
@@ -96,8 +96,8 @@
     if (ended) {
       if (getRepeatCount() != INFINITE && repeatCount >= getRepeatCount()) {
         frame = getMaxFrame();
-        notifyEnd(isReversed());
         removeFrameCallback();
+        notifyEnd(isReversed());
       } else {
         notifyRepeat();
         repeatCount++;