Mobile
Article

Animating an Android Floating Action Button

By Valdio Veliu

Since Material design was introduced, the Floating Action Button (FAB) has become one of the simplest components to implement, becoming a fast and essential favorite amongst designers and developers.

In this tutorial I will show you how to make your apps FAB interactive and how to make your own animations. But let’s start simple, adding the Floating Action Button to an Android project.

The Floating Action Button looks something like this in a layout file and will be auto generated if create an Android Studio project with a Blank Activity:

Create a Project

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    android:src="@android:drawable/ic_menu_help"
    />

Floating Action Button

Floating action buttons can be one of two sizes. The default (56dp) and mini (40dp). For further discussion on the design principles of using a FAB, I recommend you read Google’s official guidelines.

In most recent Android apps, the FAB reacts to the scrolling of a list of elements and in my opinion, should be hidden whilst scrolling. Here is what I mean:

Hiding Fab when scrolling

To show this animation I created a recyclerView so the FAB can react to scrolling.

There are a lot a libraries that can help achieve this in 1 or 2 lines of code, but for those who are curious, here is an example:

public class FAB_Hide_on_Scroll extends FloatingActionButton.Behavior {

    public FAB_Hide_on_Scroll(Context context, AttributeSet attrs) {
        super();
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);

        //child -> Floating Action Button
        if (child.getVisibility() == View.VISIBLE && dyConsumed > 0) {
            child.hide();
        } else if (child.getVisibility() == View.GONE && dyConsumed < 0) {
            child.show();
        }
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }
}

I’m using the FloatingActionButton.Behavior() class which according to the official documentation, its main function is to move FloatingActionButton views so that any displayed Snackbars do not cover them. But in our case this class is extended so that we can implement our own behavior.

Let’s get into more detail about this behavior class. Its intention is that whenever a scroll is initiated, the onStartNestedScroll() method will return true if the scroll is vertical and from there the onNestedScroll() method will hide or show the Floating Action Button, depending on its current visibility status.

The constructor of this class is an important part of this view’s behavior, making this inflatable from the XML file

    public FAB_Hide_on_Scroll(Context context, AttributeSet attrs) {
        super();
    }

To use this behavior, add the layout_behavior attribute to the Floating Action Button. The attribute contains the package name, plus the class name at the end or to put it differently differently, the exact location of this class in the project. In my case it looks like this:

app:layout_behavior="com.valdio.valdioveliu.floatingactionbuttonproject.Scrolling_Floating_Action_Button.FAB_Hide_on_Scroll"

This animation looks cool, but it could be better. I personally prefer floating the FAB out of the screen while I scroll through the apps content, it’s more realistic. Here’s what I mean:

Floating FAB

The same logic as previously is applied, only the way the FAB hides changes.

The animation is simple. The FAB floats off the screen vertically using a LinearInterpolator. The FAB floats a distance down calculated by its height plus bottom margin to remove it completely of the screen and is floated back to its original position on scroll up.

If you take a closer look at the code, I removed the View.VISIBLE and the View.GONE checks in the if statements because the view doesn’t hide in this case, just floats off screen.

public class FAB_Float_on_Scroll extends FloatingActionButton.Behavior {

    public FAB_Float_on_Scroll(Context context, AttributeSet attrs) {
        super();
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);

        //child -> Floating Action Button
        if (dyConsumed > 0) {
            CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
            int fab_bottomMargin = layoutParams.bottomMargin;
            child.animate().translationY(child.getHeight() + fab_bottomMargin).setInterpolator(new LinearInterpolator()).start();
        } else if (dyConsumed < 0) {
            child.animate().translationY(0).setInterpolator(new LinearInterpolator()).start();
        }
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }
}

Making a Menu of Floating Action Buttons

I’ve seen many Android apps making impressive Floating Action Button menus that look and work well. Here is an example:

FAB Menu

Now you have an idea of what we’re making, let’s start building.

The first step into building this menu is the layout containing the 3 small buttons.

All the small buttons are invisible and are located at the bottom of the layout, under the primary FAB.

Inside fab_layout.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_menu_compass"
        android:visibility="invisible"
        app:backgroundTint="@color/colorFAB"
        app:fabSize="mini" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_menu_myplaces"
        android:visibility="invisible"
        app:backgroundTint="@color/colorFAB"
        app:fabSize="mini" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_menu_share"
        android:visibility="invisible"
        app:backgroundTint="@color/colorFAB"
        app:fabSize="mini" />
</FrameLayout>

Include this layout in the activity’s layout, under the primary FAB.

<include layout="@layout/fab_layout" />

Now that the layout is set, the next step is making the animations to show and hide each of the small FABs.

Caution!

While creating these animations I encountered the issue of touch events and small FABs. When the animation finishes the actual position of the small FABs does not change, only the view appears in the new position so you can’t actually perform touch events on the correct position. What I did to fix this issue was to set the layout parameters of each FAB to its new location and then perform the animation of pulling the view to the new position.

In the rest of this tutorial I will show the process of animating one of the small FABs. The process is the same for the others but with different relocation parameters.

Display Floating Action Button Menu

  FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fab1.getLayoutParams();
  layoutParams.rightMargin += (int) (fab1.getWidth() * 1.7);
  layoutParams.bottomMargin += (int) (fab1.getHeight() * 0.25);
  fab1.setLayoutParams(layoutParams);
  fab1.startAnimation(show_fab_1);
  fab1.setClickable(true);

Here I relocate fab1 by adding right and bottom margins to its layoutParams and starting the animation.

Hide Floating Action Button Menu

  FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fab1.getLayoutParams();
  layoutParams.rightMargin -= (int) (fab1.getWidth() * 1.7);
  layoutParams.bottomMargin -= (int) (fab1.getHeight() * 0.25);
  fab1.setLayoutParams(layoutParams);
  fab1.startAnimation(hide_fab_1);
  fab1.setClickable(false);

The process of hiding is the reverse of the previous animation.

The animations used on this FAB are:

  //Animations
  Animation show_fab_1 = AnimationUtils.loadAnimation(getApplication(), R.anim.fab1_show);
  Animation hide_fab_1 = AnimationUtils.loadAnimation(getApplication(), R.anim.fab1_hide);

Now all that remains are the animations. Inside the res/anim/ folder I created files for all the animations. There’s not much to these, but if you need help understanding what each tag or attribute does, read the official documentation.

Inside fab1_show.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <!-- Rotate -->
    <rotate
        android:duration="500"
        android:fromDegrees="30"
        android:interpolator="@android:anim/linear_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="4"
        android:repeatMode="reverse"
        android:toDegrees="0"></rotate>

    <!--Move-->
    <translate
        android:duration="1000"
        android:fromXDelta="170%"
        android:fromYDelta="25%"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="0%"
        android:toYDelta="0%"></translate>

    <!--Fade In-->
    <alpha
        android:duration="2000"
        android:fromAlpha="0.0"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:toAlpha="1.0"></alpha>

</set>

Inside fab1_hide.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <!--Move-->
    <translate
        android:duration="1000"
        android:fromXDelta="-170%"
        android:fromYDelta="-25%"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXDelta="0%"
        android:toYDelta="0%"></translate>

    <!--Fade Out-->
    <alpha
        android:duration="2000"
        android:fromAlpha="1.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toAlpha="0.0"></alpha>

</set>

Finally, if you look at the translate tag, responsible for moving the view, the factor by which I have relocated the FAB (170% and 25%) correspond to the factors with the margins are added and subtracted in the java code.

The same process applies to both the other FABs, but with relocation factors of (150% and 150%) fab2 and (25% and 170%) fab3.

The final project looks like this:

Final project

What’s Next?

I hope I’ve given you an idea of how to animate Floating Action Buttons in your own project. From here you should read Android’s Animation Resources and create your own animations for your apps. You can find the final code for this project on GitHub and I welcome any questions or comments you may have.

Valdio Veliu
Meet the author
Valdio is a Computer Engineering student. He is currently working on his bachelor thesis in "Cloud Computing". He has worked with languages such as C, Java, php and is currently focused on Java, mobile and web development.

No Reader comments

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in Mobile, once a week, for free.