Skip to content

Instantly share code, notes, and snippets.

@Polyterative
Last active April 6, 2017 15:05
Show Gist options
  • Save Polyterative/1b24f5423871a4d15dd5d00c36317328 to your computer and use it in GitHub Desktop.
Save Polyterative/1b24f5423871a4d15dd5d00c36317328 to your computer and use it in GitHub Desktop.
import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;
import java.util.List;
/**
* @author Polyterative
* @version 3
* as a part of "Abit" project
* The code works by magic, with help by
* @see <a href="https://github.com/cstew">Chris Stewart</a>
* and
* @see <a href="https://lab.getbase.com/introduction-to-coordinator-layout-on-android/">Grzesiek-Gajewski</a>
* and
* Google's codebase
*/
public class FABScrollBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
private int toolbarHeight;
public FABScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
this.toolbarHeight = getToolbarHeight(context);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
if (dependency instanceof AppBarLayout) {
return true;
} else return dependency instanceof Snackbar.SnackbarLayout;
}
/**
* The method decides which behaviour apply through dependency intanceof checking
*
* @param parent
* @param fab
* @param dependency
* @return true if fab was changed in size/moved
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
if (dependency instanceof AppBarLayout) {
onAppBarLayoutHide(fab, dependency);
} else if (dependency instanceof Snackbar.SnackbarLayout) {
onSnackBarScale(parent, fab, dependency);
// onSnackBarHide(parent, fab, dependency);
// onSnackBarRotate(parent, fab, dependency);
}
return true;
}
/**
* Alternative SnackBar behavior
*
* @param parent
* @param fab
* @param dependency
*/
private void onSnackBarRotate(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
float translationY = getFabTranslationYForSnackbar(parent, fab);
float percentComplete = -translationY / dependency.getHeight();
fab.setRotation(-90 * percentComplete);
fab.setTranslationY(translationY);
}
/**
* Alternative behavior
*
* @param parent
* @param fab
* @param dependency
*/
private void onSnackBarHide(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
fab.setTranslationY(translationY);
}
/**
* Main snack movement, coherent with AppBarLayout's
*
* @param parent
* @param fab
* @param dependency
*/
private void onSnackBarScale(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
float translationY = getFabTranslationYForSnackbar(parent, fab);
float percentComplete = -translationY / dependency.getHeight();
float scaleFactor = 1 - percentComplete;
fab.setScaleX(scaleFactor);
fab.setScaleY(scaleFactor);
}
/**
* Main behavior on on AppBarLayout movement
* @param fab
* @param dependency
*/
private void onAppBarLayoutHide(FloatingActionButton fab, View dependency) {
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
int fabBottomMargin = lp.bottomMargin;
int distanceToScroll = fab.getHeight() + fabBottomMargin;
float ratio = dependency.getY() / (float) toolbarHeight;
fab.setTranslationY(-distanceToScroll * ratio);
}
/**
* Utility method
* @param parent
* @param fab
* @return
*/
private float getFabTranslationYForSnackbar(CoordinatorLayout parent,
FloatingActionButton fab) {
float minOffset = 0;
final List<View> dependencies = parent.getDependencies(fab);
for (int i = 0, z = dependencies.size(); i < z; i++) {
final View view = dependencies.get(i);
if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(fab, view)) {
minOffset = Math.min(minOffset,
ViewCompat.getTranslationY(view) - view.getHeight());
}
}
return minOffset;
}
public static int getToolbarHeight(Context context) {
//for behavior, utility class
final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
new int[]{R.attr.actionBarSize});
int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
return toolbarHeight;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment