Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom android AccelerateDecelerateInterpolator

I am trying to use AccelerateDecelerateInterpolator and custom it. I can see that Interpolators like DecelerateInterpolator have a "factor" field so you can change its behaviors. but AccelerateDecelerateInterpolator has non. When I am using AccelerateDecelerateInterpolator I almost can't even notice that the interpolator is doing any thing. The animation looks very linear. So, is there any way to factor the AccelerateDecelerateInterpolator or change it in any way? Thanks

like image 712
roiberg Avatar asked Dec 04 '12 09:12

roiberg


3 Answers

You can implement standard easing function with your own Interpolator. For example, this would be the implementation for the easeInOutQuint:

public class MVAccelerateDecelerateInterpolator implements Interpolator {

    // easeInOutQuint
    public float getInterpolation(float t) {
        float x = t*2.0f;
        if (t<0.5f) return 0.5f*x*x*x*x*x;
        x = (t-0.5f)*2-1;
        return 0.5f*x*x*x*x*x+1;
    }
}

enter image description here

like image 148
ʞᴉɯ Avatar answered Oct 26 '22 10:10

ʞᴉɯ


I tried to define my own TimeInterpolator as a custom AccelerateDecelerateInterpolator. I'm not too happy with the result, but it might give a few ideas. There is also sort of the factor in the code: 0.05f. Check it out:

    TimeInterpolator interpolator = new TimeInterpolator() {
        @Override
        public float getInterpolation(float input) {
            return input + 0.05f * (float) Math.sin(2 * Math.PI * input);
        }
    };

Here is more refined solution. Tangent is probably a better function for the job, than sine. This solution acelerates at begining and in the end. There is also a factor to determine aceleration.

    TimeInterpolator interpolator = new TimeInterpolator() {
        private final float mFactor   = 1.1f; // less than pi/2
        private float       oldRetVal;
        private float       oldInputVal;
        private double      initValue = Math.tan(-mFactor);
        private double      endValue  = 2 * Math.tan(mFactor);

        @Override
        public float getInterpolation(float input) {
            if (oldInputVal != input) {
                oldInputVal = input;
                oldRetVal = (float) ((Math.tan(mFactor * (2 * input - 1)) - initValue) / endValue);
            }
            return oldRetVal;
        }
    };
like image 43
MSquare Avatar answered Oct 26 '22 12:10

MSquare


Android has added PathInterpolatorCompat to the v4 support library. Now using this: https://gist.github.com/ebabel/8ff41cad01e9ce1dd9ce you can specify a easeInOutQuint, easeInOutQuart, or an easeInOutExpo with ease!

public static void expand(final View v) {
        v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        final int targetHeight = v.getMeasuredHeight();

        if ( v.getHeight() != targetHeight ) {
            // Older versions of android (pre API 21) cancel animations for views with a height of 0 so use 1 instead.
            v.getLayoutParams().height = 1;
            v.setVisibility(View.VISIBLE);


            Animation a = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) {
                    v.getLayoutParams().height = interpolatedTime == 1
                            ? ViewGroup.LayoutParams.WRAP_CONTENT
                            : (int) (targetHeight * interpolatedTime);
                    v.requestLayout();
                }

                @Override
                public boolean willChangeBounds() {
                    return true;
                }
            };

            a.setInterpolator(EasingsConstants.easeInOutQuart);
            a.setDuration(computeDurationFromHeight(v));
            v.startAnimation(a);
        } else {
            Log.d("AnimationUtil", "expand Already expanded ");
        }
    }

/**
 * 1dp/ms * multiplier
 */
private static int computeDurationFromHeight(View v) {
    return (int) (v.getMeasuredHeight() / v.getContext().getResources().getDisplayMetrics().density) * DURATION_MULTIPLIER;
}

And don't forget your build.gradle:

compile "com.android.support:support-v4:22.2.0"
like image 37
Erik B Avatar answered Oct 26 '22 10:10

Erik B