SnowWolf
SnowWolf

Reputation: 469

Android NavigationDrawer overlap by status bar

I've seen a lot questions about having a translucent status bar on top of navigation bar like this:

enter image description here

But what I want to achieve is to have a non-translucent status bar and make navigation drawer header view same height as action bar. This works find for pre-lollipop devices (API < 21). But for API 21+, the entire navigation drawer just moved up and overlapped by status bar, instead of place below status bar. The only work around I can think of is to manually set layout_marginTop on the header view for devices later than API 21+. Is there a better solution to fix this for all devices?

API < 21:

enter image description here

API > 21:

enter image description here

styles.xml(v21):

<resources>
    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
</resources>

DrawerLayout:

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

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

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

I've tried to set fitsSystemWindows to both true or false. No changes.

Here is my hack solution when initialize navigation drawer (and this is also answered by @AkashBhave):

    LinearLayout navigationHeader = (LinearLayout) navigationView.getHeaderView(0);
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        // This is make sure navigation header is below status bar
        // This only required for devices API >= 21
        LinearLayout.LayoutParams layoutParams =
                (LinearLayout.LayoutParams) navigationHeader.getLayoutParams();
        layoutParams.setMargins(0, getStatusBarHeight(), 0, 0);
        navigationHeader.setLayoutParams(layoutParams);
    }

Upvotes: 5

Views: 7323

Answers (5)

Harish
Harish

Reputation: 141

Add -> In DrawerLayout:

android:fitsSystemWindows="true"

and in NavigationView:

android:fitsSystemWindows="false"

Upvotes: 10

Vishal Nagvadiya
Vishal Nagvadiya

Reputation: 1278

try this android:fitsSystemWindows="false"

<androidx.drawerlayout.widget.DrawerLayout
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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
tools:openDrawer="start">

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<com.google.android.material.navigation.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

Upvotes: 0

Thomas
Thomas

Reputation: 329

Make sure that fitsSystemWindows is set to false not only in your NavigationView but also in your root DrawerLayout element as well as in any of your content layouts.

I struggled with this problem for a while until I noticed an android:fitsSystemWindows="true" which has been set in my old root layout element before I wrapped it up inside the DrawerLayout.

I removed all occurences of android:fitsSystemWindows and the status bar got respected for API 21+ as well.

<android.support.v4.widget.DrawerLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/drawer_layout"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      >

      <android.support.design.widget.CoordinatorLayout
        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=".ui.ImprintActivity">

        <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"
            app:theme="@style/AppTheme.Toolbar"
            app:titleTextAppearance="@style/Toolbar.TitleText"
            app:contentInsetStartWithNavigation="0dp"
            app:contentInsetStart="0dp"
            >

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

          </android.support.v7.widget.Toolbar>

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

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

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

      <android.support.design.widget.NavigationView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/navigation_view"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_view_header"
        app:menu="@menu/navigation_view_menu"
        android:background="@color/primary_light"
        />

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

Upvotes: 11

jaibatrik
jaibatrik

Reputation: 7533

You can try setting the status bar color to transparent when the drawer is opened -

getWindow().setStatusBarColor(Color.TRANSPARENT);

Upvotes: 0

AkashBhave
AkashBhave

Reputation: 749

I think you should just set a margin_top attribute to devices higher than API 21 +. You can retrieve the system API level with:

Build.VERSION_CODES.LOLLIPOP

This is how you could check for it and set it:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 
    params.setMargins(left, top, right, bottom);
    yourbutton.setLayoutParams(params);
}

Hope it helps!

Upvotes: 2

Related Questions