Created
October 20, 2016 17:16
-
-
Save NikolaDespotoski/a201165e1a3f0b6cc57852559843b0dc to your computer and use it in GitHub Desktop.
Updated bottom navigation behavior for BottomNavigationView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.os.Parcelable; | |
import android.support.annotation.IntDef; | |
import android.support.design.widget.CoordinatorLayout; | |
import android.support.v4.view.ViewCompat; | |
import android.support.v4.view.WindowInsetsCompat; | |
import android.util.AttributeSet; | |
import android.view.View; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
/** | |
* Created by Nikola on 11/22/2015. | |
*/ | |
public abstract class VerticalScrollingBehavior<V extends View> extends CoordinatorLayout.Behavior<V> { | |
private int mTotalDyUnconsumed = 0; | |
private int mTotalDy = 0; | |
@ScrollDirection | |
private int mOverScrollDirection = ScrollDirection.SCROLL_NONE; | |
@ScrollDirection | |
private int mScrollDirection = ScrollDirection.SCROLL_NONE; | |
public VerticalScrollingBehavior(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
public VerticalScrollingBehavior() { | |
super(); | |
} | |
@Retention(RetentionPolicy.SOURCE) | |
@IntDef({ScrollDirection.SCROLL_DIRECTION_UP, ScrollDirection.SCROLL_DIRECTION_DOWN}) | |
public @interface ScrollDirection { | |
int SCROLL_DIRECTION_UP = 1; | |
int SCROLL_DIRECTION_DOWN = -1; | |
int SCROLL_NONE = 0; | |
} | |
/* | |
@return Overscroll direction: SCROLL_DIRECTION_UP, CROLL_DIRECTION_DOWN, SCROLL_NONE | |
*/ | |
@ScrollDirection | |
public int getOverScrollDirection() { | |
return mOverScrollDirection; | |
} | |
/** | |
* @return Scroll direction: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN, SCROLL_NONE | |
*/ | |
@ScrollDirection | |
public int getScrollDirection() { | |
return mScrollDirection; | |
} | |
/** | |
* @param coordinatorLayout CoordinatoyLayout parent | |
* @param child View child | |
* @param direction Direction of the overscroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN | |
* @param currentOverScroll Unconsumed value, negative or positive based on the direction; | |
* @param totalOverScroll Cumulative value for current direction | |
*/ | |
public abstract void onNestedVerticalOverScroll(CoordinatorLayout coordinatorLayout, V child, @ScrollDirection int direction, int currentOverScroll, int totalOverScroll); | |
/** | |
* @param scrollDirection Direction of the overscroll: SCROLL_DIRECTION_UP, SCROLL_DIRECTION_DOWN | |
*/ | |
public abstract void onDirectionNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, @ScrollDirection int scrollDirection); | |
@Override | |
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) { | |
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; | |
} | |
@Override | |
public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) { | |
super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); | |
} | |
@Override | |
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { | |
super.onStopNestedScroll(coordinatorLayout, child, target); | |
} | |
@Override | |
public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { | |
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); | |
if (dyUnconsumed > 0 && mTotalDyUnconsumed < 0) { | |
mTotalDyUnconsumed = 0; | |
mOverScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP; | |
} else if (dyUnconsumed < 0 && mTotalDyUnconsumed > 0) { | |
mTotalDyUnconsumed = 0; | |
mOverScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN; | |
} | |
mTotalDyUnconsumed += dyUnconsumed; | |
onNestedVerticalOverScroll(coordinatorLayout, child, mOverScrollDirection, dyConsumed, mTotalDyUnconsumed); | |
} | |
@Override | |
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) { | |
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); | |
if (dy > 0 && mTotalDy < 0) { | |
mTotalDy = 0; | |
mScrollDirection = ScrollDirection.SCROLL_DIRECTION_UP; | |
} else if (dy < 0 && mTotalDy > 0) { | |
mTotalDy = 0; | |
mScrollDirection = ScrollDirection.SCROLL_DIRECTION_DOWN; | |
} | |
mTotalDy += dy; | |
onDirectionNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, mScrollDirection); | |
} | |
@Override | |
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, boolean consumed) { | |
super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); | |
mScrollDirection = velocityY > 0 ? ScrollDirection.SCROLL_DIRECTION_UP : ScrollDirection.SCROLL_DIRECTION_DOWN; | |
return onNestedDirectionFling(coordinatorLayout, child, target, velocityX, velocityY, mScrollDirection); | |
} | |
protected abstract boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, @ScrollDirection int scrollDirection); | |
@Override | |
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) { | |
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY); | |
} | |
@Override | |
public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, V child, WindowInsetsCompat insets) { | |
return super.onApplyWindowInsets(coordinatorLayout, child, insets); | |
} | |
@Override | |
public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) { | |
return super.onSaveInstanceState(parent, child); | |
} | |
} |
Hi Nikola, thanks for the great work, I wonder how can we expand the bottom bar manually with some method similar to appbar.setExpanded(boolean)?
[Updated]
I just wrote the method below based on your code:
private void expandBottomBar(View bottomBar){
if (ViewUnit.getWindowHeight(context) < (int) bottomBar.getY() + bottomBar.getHeight()){
ViewCompat.animate(bottomBar).setDuration(100)
.setInterpolator(BottomNavigationBehavior.INTERPOLATOR)
.translationY(0).start();
}
}
@ghost There is a method setHidden(V view, boolean bottomLayoutHidden)
it can be accessed:
BottomNavigationBehavior behavior = BottomNavigationBehavior.from(mBottomNavigationView);
if(behavior != null){
behavior.setHidden(mBottomNavigationView, true); //or false
}
I believe animateOffset should be called with +view.getHeight() when bottomLayoutHidden == true
as per te following fix
public void setHidden(V view, boolean bottomLayoutHidden) {
if (!bottomLayoutHidden && hidden) {
animateOffset(view, 0);
} else if (bottomLayoutHidden && !hidden) {
animateOffset(view, view.getHeight());
}
hidden = bottomLayoutHidden;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@laszlo-galosi Sorry for delayed response. Yes, Behavior MUST find the bottomnavigationview so it can set 8dp or do it in your xml.
Cheers,