[go: nahoru, domu]

FlingAnimationUtils.java revision efbd7e3bb8244efae2561f0d9d7cedb36b1730bd
187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi/*
287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Copyright (C) 2014 The Android Open Source Project
387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi *
487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * you may not use this file except in compliance with the License.
687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * You may obtain a copy of the License at
787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi *
887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi *
1087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Unless required by applicable law or agreed to in writing, software
1187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
1287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * See the License for the specific language governing permissions and
1487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * limitations under the License
1587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */
1687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
1787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggipackage com.android.systemui.statusbar;
1887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
1987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.animation.ValueAnimator;
2087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.content.Context;
2187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.AnimationUtils;
2287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.Interpolator;
2387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggiimport android.view.animation.PathInterpolator;
2487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
2587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi/**
2687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi * Utility class to calculate general fling animation when the finger is released.
2787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi */
2887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggipublic class FlingAnimationUtils {
2987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
301d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    private static final float LINEAR_OUT_SLOW_IN_X2 = 0.35f;
31efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    private static final float LINEAR_OUT_FASTER_IN_Y2_MIN = 0.7f;
32efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    private static final float LINEAR_OUT_FASTER_IN_Y2_MAX = 1f;
3387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    private static final float MIN_VELOCITY_DP_PER_SECOND = 250;
34efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    private static final float HIGH_VELOCITY_DP_PER_SECOND = 3000;
3587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
3687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    /**
3787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * Crazy math. http://en.wikipedia.org/wiki/B%C3%A9zier_curve
3887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     */
391d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    private static final float LINEAR_OUT_SLOW_IN_START_GRADIENT = 1.0f / LINEAR_OUT_SLOW_IN_X2;
4087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
4187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    private Interpolator mLinearOutSlowIn;
4287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    private Interpolator mFastOutSlowIn;
431d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    private Interpolator mFastOutLinearIn;
441d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi
4587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    private float mMinVelocityPxPerSecond;
461d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    private float mMaxLengthSeconds;
47efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    private float mHighVelocityPxPerSecond;
4887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
491d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    public FlingAnimationUtils(Context ctx, float maxLengthSeconds) {
501d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        mMaxLengthSeconds = maxLengthSeconds;
511d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        mLinearOutSlowIn = new PathInterpolator(0, 0, LINEAR_OUT_SLOW_IN_X2, 1);
5287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        mFastOutSlowIn
5387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi                = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in);
541d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        mFastOutLinearIn
551d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi                = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_linear_in);
5687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        mMinVelocityPxPerSecond
5787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi                = MIN_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density;
58efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        mHighVelocityPxPerSecond
59efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi                = HIGH_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density;
6087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    }
6187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
6287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    /**
6387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * Applies the interpolator and length to the animator, such that the fling animation is
6487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * consistent with the finger motion.
6587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     *
6687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * @param animator the animator to apply
6787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * @param currValue the current value
6887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * @param endValue the end value of the animator
6987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * @param velocity the current velocity of the motion
7087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     */
7187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    public void apply(ValueAnimator animator, float currValue, float endValue, float velocity) {
721d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        apply(animator, currValue, endValue, velocity, Math.abs(endValue - currValue));
731d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    }
741d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi
751d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    /**
761d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * Applies the interpolator and length to the animator, such that the fling animation is
771d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * consistent with the finger motion.
781d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     *
791d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param animator the animator to apply
801d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param currValue the current value
811d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param endValue the end value of the animator
821d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param velocity the current velocity of the motion
831d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param maxDistance the maximum distance for this interaction; the maximum animation length
841d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     *                    gets multiplied by the ratio between the actual distance and this value
851d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     */
861d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    public void apply(ValueAnimator animator, float currValue, float endValue, float velocity,
871d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            float maxDistance) {
881d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        float maxLengthSeconds = (float) (mMaxLengthSeconds
891d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi                * Math.sqrt(Math.abs(endValue - currValue) / maxDistance));
9087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        float diff = Math.abs(endValue - currValue);
9187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        float velAbs = Math.abs(velocity);
9287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        float durationSeconds = LINEAR_OUT_SLOW_IN_START_GRADIENT * diff / velAbs;
931d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        if (durationSeconds <= maxLengthSeconds) {
9487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            animator.setInterpolator(mLinearOutSlowIn);
9587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        } else if (velAbs >= mMinVelocityPxPerSecond) {
9687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
9787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            // Cross fade between fast-out-slow-in and linear interpolator with current velocity.
981d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            durationSeconds = maxLengthSeconds;
9987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            VelocityInterpolator velocityInterpolator
10087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi                    = new VelocityInterpolator(durationSeconds, velAbs, diff);
10187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator(
10287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi                    velocityInterpolator, mLinearOutSlowIn, mLinearOutSlowIn);
10387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            animator.setInterpolator(superInterpolator);
10487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        } else {
10587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
10687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            // Just use a normal interpolator which doesn't take the velocity into account.
1071d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            durationSeconds = maxLengthSeconds;
10887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            animator.setInterpolator(mFastOutSlowIn);
10987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        }
11087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        animator.setDuration((long) (durationSeconds * 1000));
11187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    }
11287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
11387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    /**
1141d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * Applies the interpolator and length to the animator, such that the fling animation is
1151d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * consistent with the finger motion for the case when the animation is making something
1161d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * disappear.
1171d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     *
1181d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param animator the animator to apply
1191d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param currValue the current value
1201d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param endValue the end value of the animator
1211d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param velocity the current velocity of the motion
1221d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @param maxDistance the maximum distance for this interaction; the maximum animation length
1231d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     *                    gets multiplied by the ratio between the actual distance and this value
1241d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     */
1251d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    public void applyDismissing(ValueAnimator animator, float currValue, float endValue,
1261d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            float velocity, float maxDistance) {
1271d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        float maxLengthSeconds = (float) (mMaxLengthSeconds
1281d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi                * Math.pow(Math.abs(endValue - currValue) / maxDistance, 0.5f));
1291d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        float diff = Math.abs(endValue - currValue);
1301d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        float velAbs = Math.abs(velocity);
131efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        float y2 = calculateLinearOutFasterInY2(velAbs);
132efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi
133efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        // The gradient at the start of the curve is just y2.
134efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        float startGradient = y2;
135efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        Interpolator mLinearOutFasterIn = new PathInterpolator(0, 0, 1, y2);
136efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        float durationSeconds = startGradient * diff / velAbs;
1371d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        if (durationSeconds <= maxLengthSeconds) {
1381d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            animator.setInterpolator(mLinearOutFasterIn);
1391d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        } else if (velAbs >= mMinVelocityPxPerSecond) {
1401d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi
1411d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            // Cross fade between linear-out-faster-in and linear interpolator with current
1421d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            // velocity.
1431d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            durationSeconds = maxLengthSeconds;
1441d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            VelocityInterpolator velocityInterpolator
1451d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi                    = new VelocityInterpolator(durationSeconds, velAbs, diff);
1461d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator(
1471d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi                    velocityInterpolator, mLinearOutFasterIn, mLinearOutSlowIn);
1481d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            animator.setInterpolator(superInterpolator);
1491d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        } else {
1501d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi
1511d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            // Just use a normal interpolator which doesn't take the velocity into account.
1521d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            durationSeconds = maxLengthSeconds;
1531d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi            animator.setInterpolator(mFastOutLinearIn);
1541d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        }
1551d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        animator.setDuration((long) (durationSeconds * 1000));
1561d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    }
1571d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi
1581d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    /**
159efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi     * Calculates the y2 control point for a linear-out-faster-in path interpolator depending on the
160efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi     * velocity. The faster the velocity, the more "linear" the interpolator gets.
161efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi     *
162efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi     * @param velocity the velocity of the gesture.
163efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi     * @return the y2 control point for a cubic bezier path interpolator
164efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi     */
165efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    private float calculateLinearOutFasterInY2(float velocity) {
166efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        float t = (velocity - mMinVelocityPxPerSecond)
167efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi                / (mHighVelocityPxPerSecond - mMinVelocityPxPerSecond);
168efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        t = Math.max(0, Math.min(1, t));
169efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi        return (1 - t) * LINEAR_OUT_FASTER_IN_Y2_MIN + t * LINEAR_OUT_FASTER_IN_Y2_MAX;
170efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    }
171efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi
172efbd7e3bb8244efae2561f0d9d7cedb36b1730bdJorim Jaggi    /**
1731d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     * @return the minimum velocity a gesture needs to have to be considered a fling
1741d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi     */
1751d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    public float getMinVelocityPxPerSecond() {
1761d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi        return mMinVelocityPxPerSecond;
1771d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    }
1781d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi
1791d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi    /**
18087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * An interpolator which interpolates two interpolators with an interpolator.
18187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     */
18287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    private static final class InterpolatorInterpolator implements Interpolator {
18387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
18487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private Interpolator mInterpolator1;
18587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private Interpolator mInterpolator2;
18687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private Interpolator mCrossfader;
18787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
18887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        InterpolatorInterpolator(Interpolator interpolator1, Interpolator interpolator2,
18987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi                Interpolator crossfader) {
19087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            mInterpolator1 = interpolator1;
19187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            mInterpolator2 = interpolator2;
19287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            mCrossfader = crossfader;
19387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        }
19487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
19587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        @Override
19687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        public float getInterpolation(float input) {
19787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            float t = mCrossfader.getInterpolation(input);
19887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            return (1 - t) * mInterpolator1.getInterpolation(input)
19987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi                    + t * mInterpolator2.getInterpolation(input);
20087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        }
20187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    }
20287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
20387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    /**
20487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     * An interpolator which interpolates with a fixed velocity.
20587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi     */
20687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    private static final class VelocityInterpolator implements Interpolator {
20787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
20887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private float mDurationSeconds;
20987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private float mVelocity;
21087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private float mDiff;
21187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
21287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        private VelocityInterpolator(float durationSeconds, float velocity, float diff) {
21387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            mDurationSeconds = durationSeconds;
21487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            mVelocity = velocity;
21587cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            mDiff = diff;
21687cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        }
21787cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi
21887cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        @Override
21987cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        public float getInterpolation(float input) {
22087cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            float time = input * mDurationSeconds;
22187cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi            return time * mVelocity / mDiff;
22287cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi        }
22387cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi    }
22487cd5e71ec087e191b8baaa8913a878f92d4e10dJorim Jaggi}
225