1

I created a new App with Android Studio 2.0 and I want to have my Navigation Drawer below the Toolbar. I know the Material Design specs say it should be above the Toolbar but my Drawer won't have that much entries and I want to see the neat icon animation provided by Google.

I maged to get what I want by placing the DrawerLayout within the top level CoordinatorLayout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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"
    android:fitsSystemWindows="true"
    tools:context="com.company.app.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:openDrawer="start">

        <include layout="@layout/content_main" />

        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:menu="@menu/activity_main_drawer" />

    </android.support.v4.widget.DrawerLayout>

</android.support.design.widget.CoordinatorLayout>

I am using android:fitsSystemWindow="true" on the top level layout so I can tint the status bar. But when I do that, the Navigation Drawer does have a gray top border.

enter image description here

When I would be using it the way Google specified it (above the Toolbar) then the border would be fine but this way it just looks ugly. Is there any way to remove this?

I experimented with overriding NavigationView.onInsetsChanged(Rect rect) and was able to place the items at the top but the gray border remained.

Saenic
  • 1,593
  • 13
  • 14
  • What do you mean by "tinting" the status bar? That color comes from your `colorPrimaryDark` – Pztar Apr 15 '16 at 14:54
  • Yes this is true. But in order to have the tint effect from `colorPrimaryDark` you have to use `android:fitsSystemWindow="true"` on the root element. And this causes this gray border in `NavigationView` – Saenic Apr 16 '16 at 17:10

1 Answers1

10

I had a headache trying to figure this out also and managed to find this which describes how CoordinatorLayout passes fitsSystemWindows to its child. I definitely think this is a bug since NavigationView already has it set to false, but then I read this:

NavigationView takes care of the scrim protection of the status bar for you, ensuring that your NavigationView interacts with the status bar appropriately on API21+ devices.

from the Android Developers Blog. So I'm not sure what to think of it. I think it might be due to the fact that NavigationView was never intended to be used this way.

Nonetheless, here's a solution you can try that fixes the gray bar issue, but I haven't figured out if it might cause anymore problems. If so please post back.

In the activity_main.xml:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_marginTop="100dp"
        android:fitsSystemWindows="false"/>

</android.support.design.widget.CoordinatorLayout>

In MainActivity class:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        if (navigationView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            navigationView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
                    return insets;
                }
            });
        }
    }
}

Should get you this:

Screenshot

Community
  • 1
  • 1
Brian
  • 176
  • 1
  • 5
  • Wow thanks, the `OnApplyWindowInsetsListener` really did the trick. – Saenic Apr 22 '16 at 15:09
  • Glad it worked. I have a feeling there might be issues when the view gets updated later during runtime. I would think that's why the `View` parameter gets passed. If that's the case just need an `if` condition that the view applying the insets is the `CoordinatorLayout` before returning back the insets. Let me know if you do run into this because I haven't gotten that far along yet. – Brian Apr 22 '16 at 15:27