Animating Fab on click (zoom in/out)

时间:2017-04-06 17:03:08

标签: java android animation android-animation floating-action-button

I am trying to mimic animation and the color change for the following floating action button.

The way the floating action button works is white is off and blue is on.

enter image description here

However, I have been unsuccessful with the animation and changing the color.

These have been my attempts at doing this, as you can see I have commented out all the different ways I have tried to do this.

This is my code:

    @SuppressWarnings("unused")
    @OnClick(R.id.fabMovieFavourite)
    public void addMovieFavourite(View view) {
 /*       final Animator animator = AnimatorInflater.loadAnimator(getActivity(), R.animator.add_favourite_movie);
        animator.setTarget(view);)
        animator.start();
 */
/*
        AnimatorSet animatorSet = new AnimatorSet();
        PropertyValuesHolder propertyValuesHolderX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1.1f);
        PropertyValuesHolder propertyValuesHolderY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.1f);
        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolderX, propertyValuesHolderY);
        objectAnimator.setDuration(300);
        objectAnimator.setInterpolator(new OvershootInterpolator(10f));
*/

        /*
        objectAnimator.setRepeatCount(1);
        objectAnimator.setRepeatMode(ObjectAnimator.REVERSE);
*/

/*
        PropertyValuesHolder propertyValuesHolderX2 = PropertyValuesHolder.ofFloat(View.SCALE_X, 0.9f);
        PropertyValuesHolder propertyValuesHolderY2 = PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.9f);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofPropertyValuesHolder(view, propertyValuesHolderX2, propertyValuesHolderY2);
        objectAnimator.setDuration(300);
        objectAnimator2.setInterpolator(new OvershootInterpolator(10f));

        animatorSet.playSequentially(objectAnimator, objectAnimator2);
        objectAnimator.start();
*/

      //  view.BackgroundTintList(ContextCompat.getColorStateList(getContext(), R.color.primary));
        //view.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.primary));

        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            Timber.d("start translationZ");
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, 12f);
            objectAnimator.setDuration(300);
            objectAnimator.setInterpolator(new OvershootInterpolator(10f));
            objectAnimator.setTarget(view);
            objectAnimator.start();
        }
    }

Many thanks for any suggestions.

1 个答案:

答案 0 :(得分:52)

这个动画中有两个阶段。第一个缩放X和Y轴,第二个缩小它。因此,我们可以将它们分成两个AnimatorSet并按顺序播放它们。

动画的关键点是为第二个AnimatorSet找到合适的插值器,因为它不是标准插值器。

enter image description here

看,我们希望fab超调,然后下冲,然后最终达到动画师的指定值。

幸运的是,有一个非常方便的PathInterpolator,它将为我们提供Path的内插器。

Path path = new Path();
path.moveTo(0.0f, 0.0f);
path.lineTo(0.5f, 1.3f);
path.lineTo(0.75f, 0.8f);
path.lineTo(1.0f, 1.0f);
PathInterpolator pathInterpolator = new PathInterpolator(path);

所以,让我们创建第一个动画:

final float from = 1.0f;
final float to = 1.3f;

ObjectAnimator scaleX = ObjectAnimator.ofFloat(fab, View.SCALE_X, from, to);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(fab, View.SCALE_Y,  from, to);
ObjectAnimator translationZ = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, from, to);

AnimatorSet set1 = new AnimatorSet();
set1.playTogether(scaleX, scaleY, translationZ);
set1.setDuration(100);
set1.setInterpolator(new AccelerateInterpolator());

set1.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        fab.setImageResource(isActive ? R.drawable.heart_active : R.drawable.heart_passive);
        fab.setBackgroundTintList(ColorStateList.valueOf(isActive ? colorActive : colorPassive));
        isActive = !isActive;
    }
});

我们正在缩放x,y。此外,我们正在改变z平移以具有适当的阴影效果。当动画结束时,我们想要改变fab状态(心脏颜色和fab背景)。

现在让我们创建动画来解决:

ObjectAnimator scaleXBack = ObjectAnimator.ofFloat(fab, View.SCALE_X, to, from);
ObjectAnimator scaleYBack = ObjectAnimator.ofFloat(fab, View.SCALE_Y, to, from);
ObjectAnimator translationZBack = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, to, from);

AnimatorSet set2 = new AnimatorSet();
set2.playTogether(scaleXBack, scaleYBack, translationZBack);
set2.setDuration(300);
set2.setInterpolator(pathInterpolator);

请参阅此处,我们使用了之前创建的pathInterpolator

我们希望按顺序播放这两个AnimatorSet

final AnimatorSet set = new AnimatorSet();
set.playSequentially(set1, set2);

set.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        fab.setClickable(true);
    }

    @Override
    public void onAnimationStart(Animator animation) {
        fab.setClickable(false);
    }
});

此外,我们希望在制作动画时禁用fab的点击次数。所以我们根据动画状态打开/关闭它。

最后,我们在点击发生时启动动画:

fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        set.start();
    }
});

结果:

enter image description here

<强> Source code at github