CoordinatorLayout content child overlaps BottomNavigationView CoordinatorLayout content child overlaps BottomNavigationView android android

CoordinatorLayout content child overlaps BottomNavigationView


I came up with a different approach (not battle tested yet though):

I subclassed AppBarLayout.ScrollingViewBehavior to adjust the bottom margin of the content view based on the height of the BottomNavigationView (if present). This way it should be future proof (hopefully) if the height of the BottomNavigationView changes for any reason.

The subclass (Kotlin):

class ScrollingViewWithBottomNavigationBehavior(context: Context, attrs: AttributeSet) : AppBarLayout.ScrollingViewBehavior(context, attrs) {    // We add a bottom margin to avoid the bottom navigation bar    private var bottomMargin = 0    override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean {        return super.layoutDependsOn(parent, child, dependency) || dependency is BottomNavigationView    }    override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean {        val result = super.onDependentViewChanged(parent, child, dependency)        if(dependency is BottomNavigationView && dependency.height != bottomMargin) {            bottomMargin = dependency.height            val layout = child.layoutParams as CoordinatorLayout.LayoutParams            layout.bottomMargin = bottomMargin            child.requestLayout()            return true        } else {            return result        }    }}

And then in the layout XML you put:

app:layout_behavior=".ScrollingViewWithBottomNavigationBehavior"

instead of

app:layout_behavior="@string/appbar_scrolling_view_behavior"


Basically what you have to do is create a Relativelayout as parent and put BottomNavigationView and CoordinatorLayout as children. Then align BottomNavigationView at the bottom and set CoordinatorLayout above that. Please try the below code. It might have few attribute erros, because I wrote it here itself. And sorry for the messed up indentation.

<?xml version="1.0" encoding="utf-8"?>    <RelativeLayout        xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:app="http://schemas.android.com/apk/res-auto"        xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        tools:context=".MainActivity">    <android.support.design.widget.CoordinatorLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_above="@+id/navigation"        >        <android.support.design.widget.AppBarLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:fitsSystemWindows="true"            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:layout_scrollFlags="enterAlways|scroll"                app:popupTheme="@style/AppTheme.PopupOverlay"/>        </android.support.design.widget.AppBarLayout>        <android.support.v4.view.ViewPager            android:id="@+id/pager"            android:layout_width="match_parent"            android:layout_height="match_parent"            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>    </android.support.design.widget.CoordinatorLayout><android.support.design.widget.BottomNavigationView            android:id="@+id/navigation"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:background="?android:attr/windowBackground"            app:itemIconTint="?colorPrimaryDark"            app:itemTextColor="?colorPrimaryDark"            app:menu="@menu/navigation"/>    </RelativeLayout>


This is caused by app:layout_behavior="@string/appbar_scrolling_view_behavior" in your ViewPager. If you remove this line, you will see now it fits the CoordinatorLayout container (unfortunately, this includes now being underneath the Toolbar).

I found it helped to treat CoordinatorLayout as just a FrameLayout, with a few extra tricks. The app:layout_behavior attribute above is necessary to allow the toolbar to appear to scroll in and out... in reality, the layout is doing this by having the view linked to the collapsing toolbar (in your case, your ViewPager) be exactly a toolbar's height larger than the bounds. Scrolling up brings the view up to the bottom within the bounds, and pushes the toolbar up extending beyond the bounds. Scrolling down, vice versa.

Now, onto the BottomNavigationView! If, as I did, you want the BottomNavigationView visible the whole time, then move it outside the CoordinatorLayout, as Anoop said. Use CoordinatorLayout only for things that need to coordinate, everything else outside. I happened to use a ConstraintLayout for my parent view (you could use RelativeLayout or whatever works for you though). With ConstraintLayout, for you it would look like this:

 <android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><android.support.design.widget.CoordinatorLayout    android:layout_width="0dp"    android:layout_height="0dp"    app:layout_constraintBottom_toTopOf="@id/navigation"    app:layout_constraintEnd_toEndOf="parent"    app:layout_constraintStart_toStartOf="parent"    app:layout_constraintTop_toTopOf="parent"    tools:context=".MainActivity">    <android.support.design.widget.AppBarLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:fitsSystemWindows="true"        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:layout_scrollFlags="enterAlways|scroll"            app:popupTheme="@style/AppTheme.PopupOverlay" />    </android.support.design.widget.AppBarLayout>    <android.support.v4.view.ViewPager        android:id="@+id/pager"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:layout_behavior="@string/appbar_scrolling_view_behavior" /></android.support.design.widget.CoordinatorLayout><android.support.design.widget.BottomNavigationView    android:id="@+id/navigation"    android:layout_width="0dp"    android:layout_height="wrap_content"    android:background="?android:attr/windowBackground"    app:itemIconTint="?colorPrimaryDark"    app:itemTextColor="?colorPrimaryDark"    app:layout_constraintBottom_toBottomOf="parent"    app:layout_constraintEnd_toEndOf="parent"    app:layout_constraintStart_toStartOf="parent"    app:menu="@menu/navigation" /> </android.support.constraint.ConstraintLayout>

In Android Studio design view, you're still going to see the ViewPager appear to be larger than the container (probably looks like it's behind the Bottom Nav still). But that's ok, when you get to the bottom of the ViewPager's content, it will show (i.e. won't be behind the bottom navigation). This quirk in the design view is just the way the CoordinatorLayout makes the toolbar show/hide, as mentioned earlier.