// Path: material-intro/src/main/java/com/heinrichreimersoftware/materialintro/util/AnimUtils.java
// public class AnimUtils {
// 
//     private AnimUtils() { }
// 
//     private static Interpolator fastOutSlowIn;
// 
//     public static Interpolator getFastOutSlowInInterpolator(Context context) {
//         if (fastOutSlowIn == null) {
//             if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//                 fastOutSlowIn = AnimationUtils.loadInterpolator(context,
//                         android.R.interpolator.fast_out_slow_in);
//             }
//             else {
//                 fastOutSlowIn = new FastOutSlowInInterpolator();
//             }
//         }
//         return fastOutSlowIn;
//     }
// 
//     public static void applyShakeAnimation(Context context, View view) {
//         Animation shake;
//         shake = AnimationUtils.loadAnimation(context, R.anim.shake);
//         view.startAnimation(shake);
//     }
// 
// }


import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import com.heinrichreimersoftware.materialintro.R;
import com.heinrichreimersoftware.materialintro.util.AnimUtils;
import java.util.Arrays;
            final float moveTo, int was, int now, int steps) {

        // create the actual move animator
        ValueAnimator moveSelected = ValueAnimator.ofFloat(selectedDotX, moveTo);

        // also set up a pending retreat anim – this starts when the move is 75% complete
        retreatAnimation = new PendingRetreatAnimator(was, now, steps,
                now > was ?
                        new RightwardStartPredicate(moveTo - ((moveTo - selectedDotX) * 0.25f)) :
                        new LeftwardStartPredicate(moveTo + ((selectedDotX - moveTo) * 0.25f)));
        retreatAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                resetState();
                pageChanging = false;
            }
        });
        moveSelected.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                // todo avoid autoboxing
                selectedDotX = (Float) valueAnimator.getAnimatedValue();
                retreatAnimation.startIfNecessary(selectedDotX);
                if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    postInvalidateOnAnimation();
                }
                else{
                    postInvalidate();
                }
            }
// Path: material-intro/src/main/java/com/heinrichreimersoftware/materialintro/util/AnimUtils.java
// public class AnimUtils {
// 
//     private AnimUtils() { }
// 
//     private static Interpolator fastOutSlowIn;
// 
//     public static Interpolator getFastOutSlowInInterpolator(Context context) {
//         if (fastOutSlowIn == null) {
//             if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//                 fastOutSlowIn = AnimationUtils.loadInterpolator(context,
//                         android.R.interpolator.fast_out_slow_in);
//             }
//             else {
//                 fastOutSlowIn = new FastOutSlowInInterpolator();
//             }
//         }
//         return fastOutSlowIn;
//     }
// 
//     public static void applyShakeAnimation(Context context, View view) {
//         Animation shake;
//         shake = AnimationUtils.loadAnimation(context, R.anim.shake);
//         view.startAnimation(shake);
//     }
// 
// }


// Path: material-intro/src/main/java/com/heinrichreimersoftware/materialintro/view/InkPageIndicator.java
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import com.heinrichreimersoftware.materialintro.R;
import com.heinrichreimersoftware.materialintro.util.AnimUtils;
import java.util.Arrays;

            final float moveTo, int was, int now, int steps) {

        // create the actual move animator
        ValueAnimator moveSelected = ValueAnimator.ofFloat(selectedDotX, moveTo);

        // also set up a pending retreat anim – this starts when the move is 75% complete
        retreatAnimation = new PendingRetreatAnimator(was, now, steps,
                now > was ?
                        new RightwardStartPredicate(moveTo - ((moveTo - selectedDotX) * 0.25f)) :
                        new LeftwardStartPredicate(moveTo + ((selectedDotX - moveTo) * 0.25f)));
        retreatAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                resetState();
                pageChanging = false;
            }
        });
        moveSelected.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                // todo avoid autoboxing
                selectedDotX = (Float) valueAnimator.getAnimatedValue();
                retreatAnimation.startIfNecessary(selectedDotX);
                if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    postInvalidateOnAnimation();
                }
                else{
                    postInvalidate();
                }
            }
        });