Show/hide BottomNavigationView on scroll in CoordinatorLayout with AppBarLayout
Solution 1
After a day or two of searching I settled with a custom Behavior
attached to the BottomNavigationView
. Its main idea is to detect when the BottomNavigationView's sibling is scrolled so that it can hide the BottomNavigationView. Something like this:
public class BottomNavigationBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {
public BottomNavigationBehavior() {
super();
}
public BottomNavigationBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, BottomNavigationView child, View dependency) {
boolean dependsOn = dependency instanceof FrameLayout;
return dependsOn;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target, int dx, int dy, int[] consumed) {
if(dy < 0) {
showBottomNavigationView(child);
}
else if(dy > 0) {
hideBottomNavigationView(child);
}
}
private void hideBottomNavigationView(BottomNavigationView view) {
view.animate().translationY(view.getHeight());
}
private void showBottomNavigationView(BottomNavigationView view) {
view.animate().translationY(0);
}
}
As you can see, I'm using simple ViewPropertyAnimator
, obtained using the child views's animate
method. This leads to a simple animation that doesn't really match the AppBarLayout
's behavior but it's decent enough to look good and at the same time it's simple enough to implement.
I expect that at some point the Android team will add a default Behavior for the BottomNavigationView in the support library so I don't think it's reasonable to invest a lot more time to exactly duplicate the AppBarLayout's behavior.
edit (April 2018): see the comments section for a minor clarification about onStartNestedScroll
and onNestedPreScroll
and their new versions.
Solution 2
You can also use HideBottomViewOnScrollBehavior. This behavior works in basically the same way, but also handles cancelling any existing animations that are running which should be better for performance.
Comments
-
stan0 almost 2 years
I am trying to use both
AppBarLayout
andBottomNavigationLayout
in a singleCoordinatorLayout
and I'm having difficulties hiding theBottomNavigationLayout
as required by the material guideline.I mean something like this:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="false"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_insetEdge="top" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/AppTheme.PopupOverlay" app:layout_scrollFlags="scroll|enterAlways"/> </android.support.design.widget.AppBarLayout> <android.support.design.widget.BottomNavigationView android:id="@+id/bottom_nav" android:layout_width="match_parent" android:layout_height="56dp" android:layout_gravity="bottom" app:menu="@menu/menu_bottom_navigation"/> <FrameLayout android:id="@+id/content_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.design.widget.CoordinatorLayout>
As you can see, I also have a
FrameLayout
that's used to contain a fragment with the actual content. Currently there are no default/built-in behaviors for theBottomNavigationView
- neither for the view itself, nor for its siblings. The existingappbar_scrolling_view_behavior
handles the content view in coordination with the appbar but ignores other siblings.I am looking for a solution to hide and show both the appbar and the bottom navigation view on scroll.
-
Jokus about 6 yearsThank you! Btw onStartNestedScroll and onNestedPreScroll are now deprecated. Both need
int type
as the last parameter ;-) -
stan0 about 6 yearsThanks @Jokus I haven't used the BottomNavBar since this post but i'll try to take a look and edit as needed. Thanks for the clarification - it could be useful for others.
-
Debjit almost 6 years
-
Debjit almost 6 yearsWhat do i do if I want the opposite. A header layout going off the screen.
-
stan0 almost 6 yearsThis looks promising! It's probably the correct way to do it nowadays but unfortunately I don't have the time to test it now. So I hope other users would be able to test and upvote in order to improve this question/answer.
-
stan0 almost 6 years@Debjit if you mean the App Bar Layout then you could use its default behaviour -> developer.android.com/reference/android/support/design/widget/…
-
Debjit almost 6 years@stan0 No not app bar. I have a layout on top which needs to quick return.
-
manish poddar almost 6 yearsHave you tested it till now? If yes, can you please tell me how to use this?
-
Cameron Ketcham almost 6 yearsTake a look at the source, it's pretty simple. github.com/material-components/material-components-android/blob/…
-
Softlion over 5 yearsSupport library has an integrated hide_bottom_view_on_scroll_behavior doing the same.
-
kelalaka over 4 yearsThis is not Material. you are using support library.