14

我正在尝试使用 AccelerateDecelerateInterpolator 并对其进行自定义。我可以看到像 DecelerateInterpolator 这样的插值器有一个“因子”字段,所以你可以改变它的行为。但 AccelerateDecelerateInterpolator 没有。当我使用 AccelerateDecelerateInterpolator 时,我几乎没有注意到插值器正在做任何事情。动画看起来非常线性。那么,有没有办法考虑 AccelerateDecelerateInterpolator 或以任何方式改变它?谢谢

4

3 回答 3

14

您可以使用自己的Interpolator. 例如,这将是以下的实现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;
    }
}

在此处输入图像描述

于 2014-04-11T14:38:33.940 回答
2

我试图将自己的 TimeInterpolator 定义为自定义的 AccelerateDecelerateInterpolator。我对结果不太满意,但它可能会提供一些想法。代码中还有一个因素:0.05f。看看这个:

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

这是更精致的解决方案。切线可能比正弦函数更适合这项工作。该解决方案在开始和结束时都会加速。还有一个决定加速度的因素。

    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;
        }
    };
于 2013-09-17T16:42:10.477 回答
1

Android 已将 PathInterpolatorCompat 添加到 v4 支持库中。现在使用这个:https : //gist.github.com/ebabel/8ff41cad01e9ce1dd9ce 您可以轻松指定easeInOutQuint、easeInOutQuart 或easeInOutExpo!

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;
}

不要忘记你的 build.gradle:

compile "com.android.support:support-v4:22.2.0"
于 2015-08-07T00:44:10.103 回答