当 FAB 重力处于底部时,Circular Reveal 不起作用

Circular Reveal not working when FAB gravity is bottom

我正在努力将浮动操作按钮 (FAB) 转变为工具栏,使用以下代码一切顺利且完美:

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="sg.com.saurabh.designlibraryexpirements.ToolbarMorphActivity">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|right"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:layout_marginRight="@dimen/activity_vertical_margin"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:src="@drawable/ic_add" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/ToolBarTheme"
        android:layout_height="?attr/actionBarSize"
        android:layout_gravity="top"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:visibility="invisible"
        tools:visibility="visible" />

</FrameLayout>

activity:

package sg.com.saurabh.designlibraryexpirements;

import android.animation.Animator;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;

public class ToolbarMorphActivity extends AppCompatActivity {

    Toolbar toolbar;
    FloatingActionButton fab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toolbar_morph);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(mFabClickListener);
    }

    private View.OnClickListener mFabClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            fab.animate()
                    .rotationBy(45)
                    .setInterpolator(new AnticipateOvershootInterpolator())
                    .setDuration(250)
                    .start();

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    fab.setVisibility(View.GONE);
                }
            },50);

            revealToolbar();
        }
    };

    private void revealToolbar() {
        toolbar.setVisibility(View.VISIBLE);

        int x = (int)fab.getX() + fab.getWidth()/2;
        int y = (int)fab.getY() + fab.getHeight()/2;

        Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, x, y, 0, toolbar.getWidth())
                .setDuration(400);
        animator.setInterpolator(new FastOutLinearInInterpolator());
        animator.start();
    }

    private void dismissToolbar() {
        int x = (int)fab.getX() + fab.getWidth()/2;
        int y = (int)fab.getY() + fab.getHeight()/2;

        Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, x, y, toolbar.getWidth(), 0)
                .setDuration(400);
        animator.setInterpolator(new LinearOutSlowInInterpolator());
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                toolbar.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                fab.setVisibility(View.VISIBLE);

                fab.animate()
                        .rotationBy(-45)
                        .setInterpolator(new AccelerateInterpolator())
                        .setDuration(100)
                        .start();
            }
        },200);
    }

    @Override
    public void onBackPressed() {
        if(toolbar.getVisibility() == View.VISIBLE) {
            dismissToolbar();
        }
        else
            super.onBackPressed();
    }
}

对于上述布局,圆形显示按预期工作。但是,当我将 fab 和工具栏的 layout_gravity 更改为 bottom 而不是 top 时,事情就崩溃了。旋转动画起作用,然后工具栏只出现而没有圆形显示动画。我完全被它如何打破圆形显示动画所困扰。

您的解决方法是替换:

private void revealToolbar() {
    ....
    int x = (int)fab.getX() + fab.getWidth()/2;
    int y = (int)fab.getY() + fab.getHeight()/2;
    ....
}

来自

 private void revealToolbar() {
    ...
    int x = (int)fab.getX() + fab.getWidth()/2;
    int y = fab.getHeight()/2;
    ...
 }

原因是因为createCircularReveal是以参数centerYcenterX作为动画圆心的坐标,相对于视图(即Toolbar,在我们的例子中)。

参见method ViewAnimationUtils.createCircularReveal definition

 ........
 * @param view The View will be clipped to the animating circle.
 * @param centerX The x coordinate of the center of the animating circle, relative to
 *                <code>view</code>.
 * @param centerY The y coordinate of the center of the animating circle, relative to
 *                <code>view</code>.
 * @param startRadius The starting radius of the animating circle.
 * @param endRadius The ending radius of the animating circle.
 */