如何在Android中对视图应用缓动动画函数

14
我想在Android视图(按钮)上应用自定义插值器的翻译动画,其中缓动函数为:
public static float easeOut(float t,float b , float c, float d) {
    if ((t/=d) < (1/2.75f)) {
       return c*(7.5625f*t*t) + b;
    } else if (t < (2/2.75f)) {
       return c*(7.5625f*(t-=(1.5f/2.75f))*t + .75f) + b;
    } else if (t < (2.5/2.75)) {
       return c*(7.5625f*(t-=(2.25f/2.75f))*t + .9375f) + b;
    } else {
       return c*(7.5625f*(t-=(2.625f/2.75f))*t + .984375f) + b;
    }
}

我有一个例子,使用自定义插值器如下:

插值器如下:

public class HesitateInterpolator implements Interpolator {
    public HesitateInterpolator() {
    }

    public float getInterpolation(float t) {
        float x = 2.0f * t - 1.0f;
        return 0.5f * (x * x * x + 1.0f);
    }
}

"and" 的使用方式如下:
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
anim.setInterpolator(new HesitateInterpolator());

我的问题是: 这些值bcd是用来做什么的?

有一种替代方法.. https://dev59.com/T2Ah5IYBdhLWcg3wBfiM#39125948 - amalBit
5个回答

24

提示:对于只想使用缓动插值器的人,您可以使用 myAnimator.setInterpolator(new AccelerateDecelerateInterpolator());


或者:myAnimation.setInterpolator(mContext, android.R.interpolator.accelerate_decelerate); - felippe

15

2
很棒的库!我觉得有必要指出,你不应该导入Android的ObjectAnimator和AnimatorSet,而应该是com.nineoldandroids的,所以也需要编译'com.nineoldandroids:library:2.4.0'。 - marienke
2
谢谢提供这个库! :) 只需添加一些关于使用方法或需要注意的文档即可。 - marienke

12

1,2,3 go

  1. 使用这个超棒的网站,创建一个自定义的三次贝塞尔曲线,并获得该曲线的控制点。控制点应在 0,0 和 1,1 之间。
  2. Interpolator customInterpolator = PathInterpolatorCompat.create(cpX1,cpX2,cpY1,cpY2)
  3. 将此customInterpolator添加到您的任何动画中。

增加了一个代码片段。更多信息请参考此处


11
根据Robert Penner的缓动函数,如此处所述
t:当前时间,b:起始值,c:变化量,d:持续时间
如果您想实现自定义插值器,您需要创建类似于以下内容的内容:
(这将是easeInOutQuint的实现)
public class MVAccelerateDecelerateInterpolator implements Interpolator {

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

编辑: 要实现缓动函数,您需要一些数学知识,考虑到getInterpolation方法仅获取从0.0到1.0的t参数。

因此,基本上您需要开发一个y(t)函数,其中t从0到1,y值从0到1,如下所示:

enter image description here

您更改的是从0到1的曲线(例如,在图像中,绿色线是线性的)。您需要将缓动函数“标准化”,以保持在(0,1)x(0,1)正方形中,正如您可以在我的easeInOutQuint实现中看到的那样。


谢谢你的出色回答,但是你在回答中提到的这些函数是怎么得到的呢?如何将Robert编写的函数转换为仅关于t的Java函数? - Adham
非常感谢您的解释,您能否提供我学习如何将函数规范化为0-1函数的参考资料? - Adham
抱歉,这是数学知识的问题...我自己解决了。您可以使用可视化绘图工具来简化工作,例如http://rechneronline.de/function-graphs/。 - ʞᴉɯ
很抱歉我问了这么多问题 :(,如果我有这样的方程:easeInOutQuad: function (x, t, b, c, d) {if ((t/=d/2) < 1) return c/2tt + b;return -c/2 * ((--t)*(t-2) - 1) + b;},.. 我该如何使方程只有一个变量,即 y = f(x) .. 你会用什么常数? - Adham
easeInOutQuad的函数如下: 当t<0.5时,为(x*2)^2/2 当t>0.5时,为-((x-1)^2)*2+1 - ʞᴉɯ

0

这里有另一种解决方案,得益于 Android 支持库的最新添加: https://gist.github.com/ebabel/8ff41cad01e9ce1dd9ce

以及一个使用示例:

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

代码相关内容翻译:Gist链接无法访问。EasingsConstants是自定义类吗? - Rik van Velzen
1
@RikvanVelzen 对此感到抱歉,链接已从另一个答案中删除,因此我删除了要点。这是一个自定义类,其中包含一堆常量,定义了来自easings.net的值,例如:public static final Interpolator easeInOutQuad = PathInterpolatorCompat.create(0.455f, 0.03f, 0.515f, 0.955f); - Erik B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接