I am working on morphing a floating action button (FAB) to a toolbar and things work smoothly and perfectly with the following code:
layout file:
<?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();
}
}
The circular reveal works as expected for the above layout. However thing break up when I change the layout_gravity of the fab and toolbar to bottom instead of top. The rotate animation works and then the toolbar just appears without the circular reveal animation. I am completely stumped by how that breaks the circular reveal animation.

The fix for you would be to replace:
private void revealToolbar() {
....
int x = (int)fab.getX() + fab.getWidth()/2;
int y = (int)fab.getY() + fab.getHeight()/2;
....
}
by
private void revealToolbar() {
...
int x = (int)fab.getX() + fab.getWidth()/2;
int y = fab.getHeight()/2;
...
}
The reason is that createCircularReveal is taking parameters centerY and centerX as coordinates of the center of the animating circle, relative to view (i.e. Toolbar, in our case).
See 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. */
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With