package com.sxjs.common.widget.bottomnavigation.behaviour;
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.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.View;
import android.view.animation.Interpolator;
import com.sxjs.common.widget.bottomnavigation.BottomNavigationBar;
import java.util.List;
/**
* Class description
*
* @author ashokvarma
* @version 1.0
* @since 06 Jun 2016
*/
public class BottomNavBarFabBehaviour extends CoordinatorLayout.Behavior<FloatingActionButton> {
ViewPropertyAnimatorCompat mFabTranslationYAnimator;
// @BottomNavigationBar.FabBehaviour
// private int mFabBehaviour;
static final Interpolator FAST_OUT_SLOW_IN_INTERPOLATOR = new FastOutSlowInInterpolator();
///////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////
// public BottomNavBarFabBehaviour() {
// mFabBehaviour = BottomNavigationBar.FAB_BEHAVIOUR_TRANSLATE_AND_STICK;
// }
///////////////////////////////////////////////////////////////////////////
// Dependencies setup
///////////////////////////////////////////////////////////////////////////
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
return isDependent(dependency) || super.layoutDependsOn(parent, child, dependency);
}
@Override
public boolean onLayoutChild(CoordinatorLayout parent, FloatingActionButton child, int layoutDirection) {
// First let the parent lay it out
parent.onLayoutChild(child, layoutDirection);
updateFabTranslationForBottomNavigationBar(parent, child, null);
return super.onLayoutChild(parent, child, layoutDirection);
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
if (isDependent(dependency)) {
updateFabTranslationForBottomNavigationBar(parent, child, dependency);
return false;
}
return super.onDependentViewChanged(parent, child, dependency);
}
@Override
public void onDependentViewRemoved(CoordinatorLayout parent, FloatingActionButton child,
View dependency) {
if (isDependent(dependency)) {
updateFabTranslationForBottomNavigationBar(parent, child, dependency);
}
}
private boolean isDependent(View dependency) {
return dependency instanceof BottomNavigationBar || dependency instanceof Snackbar.SnackbarLayout;
}
///////////////////////////////////////////////////////////////////////////
// Animating Fab based on Changes
///////////////////////////////////////////////////////////////////////////
private void updateFabTranslationForBottomNavigationBar(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
float snackBarTranslation = getFabTranslationYForSnackBar(parent, fab);
float[] bottomBarParameters = getFabTranslationYForBottomNavigationBar(parent, fab);
float bottomBarTranslation = bottomBarParameters[0];
float bottomBarHeight = bottomBarParameters[1];
float targetTransY = 0;
if (snackBarTranslation >= bottomBarTranslation) {
// when snackBar is below BottomBar in translation present.
targetTransY = bottomBarTranslation;
} else {
targetTransY = snackBarTranslation;
}
// if (mFabBehaviour == BottomNavigationBar.FAB_BEHAVIOUR_DISAPPEAR) {
// if (targetTransY == 0) {
// fab.hide();
// } else {
// fab.show();
// }
// }
final float currentTransY = ViewCompat.getTranslationY(fab);
// Make sure that any current animation is cancelled
ensureOrCancelAnimator(fab);
if (fab.isShown()
&& Math.abs(currentTransY - targetTransY) > (fab.getHeight() * 0.667f)) {
// If the FAB will be travelling by more than 2/3 of it's height, let's animate it instead
mFabTranslationYAnimator.translationY(targetTransY).start();
} else {
// Now update the translation Y
ViewCompat.setTranslationY(fab, targetTransY);
}
}
///////////////////////////////////////////////////////////////////////////
// Fab Translation due to SnackBar and Due to BottomBar
///////////////////////////////////////////////////////////////////////////
private float[] getFabTranslationYForBottomNavigationBar(CoordinatorLayout parent,
FloatingActionButton fab) {
float minOffset = 0;
float viewHeight = 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 BottomNavigationBar) {
viewHeight = view.getHeight();
minOffset = Math.min(minOffset,
ViewCompat.getTranslationY(view) - viewHeight);
}
}
float[] returnValues = {minOffset, viewHeight};
return returnValues;
}
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 void setmFabBehaviour(int mFabBehaviour) {
// this.mFabBehaviour = mFabBehaviour;
// }
///////////////////////////////////////////////////////////////////////////
// Animator Initializer
///////////////////////////////////////////////////////////////////////////
private void ensureOrCancelAnimator(FloatingActionButton fab) {
if (mFabTranslationYAnimator == null) {
mFabTranslationYAnimator = ViewCompat.animate(fab);
mFabTranslationYAnimator.setDuration(400);
mFabTranslationYAnimator.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR);
} else {
mFabTranslationYAnimator.cancel();
}
}
}