I am trying to use both AppBarLayout
and BottomNavigationLayout
in a single CoordinatorLayout
and I'm having difficulties hiding the BottomNavigationLayout
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 the BottomNavigationView
- neither for the view itself, nor for its siblings. The existing appbar_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.
CoordinatorLayout is a super-powered FrameLayout . CoordinatorLayout is intended for two primary use cases: As a top-level application decor or chrome layout. As a container for a specific interaction with one or more child views.
It is an implementation of material design bottom navigation. Bottom navigation bars make it easy for users to explore and switch between top-level views in a single tap. They should be used when an application has three to five top-level destinations.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With