Rolling FloatingActionButton Behavior

Nikola Despotoski
Nov 20, 2015 · 2 min read

I have a sort of habit browsing materialup.com for specific keywords from Material guidelines or newest posts. Few days ago I came across this concept:

A rolling fab, freaking lolz.

Rolling in

Idea behind this is building the rolling behavior on top of the existing FloatinghActionButton.Behavior to preserve the SnackBar behavior.

We need to roll the FAB only when scrolling for all the views that implement nested scrolling:

@Override
public boolean layoutDependsOn(....View dependency) {
return super.layoutDependsOn(parent, child, dependency) || dependency instanceof NestedScrollingChild;
}

@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, ..., int nestedScrollAxes) {
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
  1. Start rolling out the FAB when we have scrolled around its height.
  2. Apply tension threshold of 0.5f, upon which we are going to start rolling it out completely.
  3. Roll in the FAB when we start scrolling down.
@Override
public void onNestedPreScroll(... FloatingActionButton child... int dx, int dy, ..) {
if (dy > 0 && mTotalDy < 0) {
mTotalDy = 0;
if (mTensionFactor <= 0.5f)
rollInFabCompletely(child);
} else if (dy < 0 && mTotalDy > 0) {
mTotalDy = 0;
}

mTotalDy += dy;
if (mTotalDy >= child.getHeight() && getRollingFabState() == IDLE) {
float rollBy = (float) (mTotalDy - child.getHeight()) / child.getHeight();
rollOutFabBy(child, rollBy);
} else if (mTotalDy < -child.getHeight()) {
if (getRollingFabState() == RollingFabState.ROLLED_OUT) {
rollInFabCompletely(child);
} else if (getRollingFabState() == RollingFabState.ROLLING_OUT) {
ViewCompat.animate(child).cancel();
rollInFabCompletely(child);
}
}
}

Tension will be used to restore original FAB position and rotation if we haven’t scrolled enough.

@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target) {
if (mTensionFactor >= 0.5)
postRollFabOutCompletely(child);
else if (mTensionFactor < 0.5 && getRollingFabState() != RollingFabState.ROLLED_OUT)
postRollFabInCompletely(child);
}

Code:

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store