点击时动画Fab按钮(缩放)

21

我正在尝试模仿以下悬浮操作按钮的动画和颜色变化。

该悬浮操作按钮的工作方式是白色为关闭状态,蓝色为打开状态。

输入图像描述

然而,我尝试实现这种动画和颜色变化时一直失败。

这是我的尝试,你可以看到我已经注释掉了所有我尝试过的不同方法。

这是我的代码:

    @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();
        }
    }

非常感谢任何建议。


我建议尝试使用两个浮动操作按钮。淡出并隐藏一个,同时淡入和显示另一个。 - Angel Koh
@AngelKoh 我正在寻找只使用一个 fab 的解决方案。 - ant2009
@ant2009 嗯,我借助库 https://github.com/jd-alexander/LikeButton 实现了这个功能。如果你想要实现它,我可以提供帮助。 - PN10
@PN10 谢谢,我会看一下的。 - ant2009
1个回答

59
这个动画分为两个阶段。第一阶段缩放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.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        set.start();
    }
});

结果:

enter image description here

Source code at github


这是我见过的最好的设置动画教程之一,如果不是最好的。感谢您花费这么多精力来回答这个问题,它对我帮助很大。 - Neglected Sanity
1
嘿@azizbekian,你能帮我解决这个问题吗?https://stackoverflow.com/questions/53577838/how-to-animate-a-fab-button-zoom-in-out-continuously 上面的代码在Lollipop及以上设备上运行良好,但在KitKat上无法正常工作。 - Goku

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