浮动操作按钮动画

4
当一个组件显示时,它使用缩放动画进行呈现;当它被隐藏时,它使用缩小动画消失。
因此,这是一种缩放进入和缩放退出的动画。
如何制作这个动画?
6个回答

13

从@Zielony的回答中,我成功地实现了我的目标。

以下是正确应用效果的代码。

scale_fab_in.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXScale="0"
    android:fromYScale="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="1"
    android:toYScale="1"
    android:interpolator="@android:interpolator/overshoot"/>

scale_fab_out.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="400"
    android:fromXScale="1"
    android:fromYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="0"
    android:toYScale="0"
    android:interpolator="@android:interpolator/overshoot"/>

编辑于2016年2月16日 - 另一种方法:

将下面的代码放入您的FAB代码或任何其他视图中。

//global
    private static final int FAB_ANIM_DURATION = 200;

public void hide() {
        // Only use scale animation if FAB is visible
        if (getVisibility() == View.VISIBLE) {
            // Pivots indicate where the animation begins from
            float pivotX = getPivotX() + getTranslationX();
            float pivotY = getPivotY() + getTranslationY();

            // Animate FAB shrinking
            ScaleAnimation anim = new ScaleAnimation(1, 0, 1, 0, pivotX, pivotY);
            anim.setDuration(FAB_ANIM_DURATION);
            anim.setInterpolator(getInterpolator());
            startAnimation(anim);
        }
        setVisibility(View.INVISIBLE);
    }


    public void show() {
        show(0, 0);
    }

    public void show(float translationX, float translationY) {

        // Set FAB's translation
        setTranslation(translationX, translationY);

        // Only use scale animation if FAB is hidden
        if (getVisibility() != View.VISIBLE) {
            // Pivots indicate where the animation begins from
            float pivotX = getPivotX() + translationX;
            float pivotY = getPivotY() + translationY;

            ScaleAnimation anim;
            // If pivots are 0, that means the FAB hasn't been drawn yet so just use the
            // center of the FAB
            if (pivotX == 0 || pivotY == 0) {
                anim = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, 0.5f);
            } else {
                anim = new ScaleAnimation(0, 1, 0, 1, pivotX, pivotY);
            }

            // Animate FAB expanding
            anim.setDuration(FAB_ANIM_DURATION);
            anim.setInterpolator(getInterpolator());
            startAnimation(anim);
        }
        setVisibility(View.VISIBLE);
    }

    private void setTranslation(float translationX, float translationY) {
        if (Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
            animate().setInterpolator(getInterpolator()).setDuration(FAB_ANIM_DURATION)
                    .translationX(translationX).translationY(translationY);
        }
    }

    private Interpolator getInterpolator() {
        return AnimationUtils.loadInterpolator(getContext(), R.interpolator.fab_interpolator);
    }


<item name="fab_interpolator" type="interpolator">@android:interpolator/decelerate_cubic</item>

1
这更好地模拟了新材料设计规范中暴露的行为,应该得到支持(参考:https://www.google.com/design/spec/components/buttons-floating-action-button.html) - shkschneider

11

它可以工作,但是放大动画从FAB的左侧开始而不是从中心开始动画,有什么想法如何修复它? - brettbrdls
你可以设置 pivotX 和 pivotY 来改变动画的中心点。 - Zielony

3
你可以使用这种方法来动画缩放任何视图。如果你反转0和1,你将得到缩小的动画效果。
 public static void scale(View view, long delay) {
        view.setScaleX(0);
        view.setScaleY(0);
        view.animate()
                .scaleX(1)
                .scaleY(1)
                .setDuration(500)
                .setStartDelay(delay)
                .setInterpolator(new OvershootInterpolator())
                .start();
    }

1
对我而言,这种类型的比例动画设置了startOffset值更好看。这对我很有效:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
       android:duration="400"
       android:fillBefore="true"
       android:fillAfter="true"
       android:fillEnabled="true"
       android:startOffset="500"
       android:fromXScale="0"
       android:fromYScale="0"
       android:pivotX="50%"
       android:pivotY="50%"
       android:toXScale="1"
       android:toYScale="1"
       android:interpolator="@android:interpolator/overshoot"/>

1
使用以下代码可以获得相同的效果。
    ScaleAnimation anim = new ScaleAnimation(0, 1, 0, 1, 50, 50);
    anim.setFillBefore(true);
    anim.setFillAfter(true);
    anim.setFillEnabled(true);
    anim.setDuration(400);
    anim.setInterpolator(new OvershootInterpolator());
    imageView.startAnimation(anim);

1
假设要对 FloatingActionButton 进行调整大小的动画处理,我首先从子类化 Animation 开始,以一般方式处理 View (从this answer改编为Kotlin)...
open class ResizeAnimation(
    private val view: View,
    private val toHeight: Float,
    private val fromHeight: Float,
    private val toWidth: Float,
    private val fromWidth: Float,
    duration: Long
) : Animation() {

    init {
        this.duration = duration
    }

    override fun applyTransformation(
        interpolatedTime: Float,
        t: Transformation?
    ) {
        val height = (toHeight - fromHeight) * interpolatedTime + fromHeight
        val width = (toWidth - fromWidth) * interpolatedTime + fromWidth
        val layoutParams = view.layoutParams
        layoutParams.height = height.toInt()
        layoutParams.width = width.toInt()
        view.requestLayout()
    }
}

...为了专门处理 FloatingActionButton,我对 _ResizeAnimation_ 进行了子类化(主要是为了更新浮动操作按钮的 customSize 属性)...

class FabResizeAnimation(
    private val view: FloatingActionButton,
    private val toSize: Float,
    private val fromSize: Float,
    duration: Long
) : ResizeAnimation(
    view,
    toSize,
    fromSize,
    toSize,
    fromSize,
    duration
) {

    override fun applyTransformation(
        interpolatedTime: Float,
        t: Transformation?
    ) {
        val fabSize = ((toSize - fromSize) * interpolatedTime + fromSize).toInt()
        view.customSize = fabSize
        super.applyTransformation(interpolatedTime, t)
    }
}

...使用方法...

    val animation = FabResizeAnimation(fab, 800.0f, 100.0f, 2000)
    fab.startAnimation(animation)

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