Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting Statusbar padding to NavigationView in Android

Tags:

I have an activity which hosts a DrawerLayout and NavigationView from support library. I'm setting a header layout to the navigation view and I want the navigation header height to be "wrap_content". So when I set the height to "wrap_content" the header layout goes behind the status bar.

The result I want is that the navigation drawer should draw behind the status bar but the navigation header should be pushed down by the statusbar height.

Below is the screenshot of what I am getting. Note the "SIGN IN" button going behind the status bar.

screenshot

Activity layout

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_drawer"
android:fitsSystemWindows="true">

<android.support.design.widget.CoordinatorLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v4.view.ViewPager>
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

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

        <android.support.design.widget.TabLayout
            app:theme="@style/ThemeOverlay.AppCompat.Dark"
            style="@style/MyCustomTabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/tabs"
            />

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

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

<android.support.design.widget.NavigationView
    android:id="@+id/navigation_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    app:headerLayout="@layout/nav_header"
    app:menu="@menu/menu_navigation"
    android:fitsSystemWindows="true"
    android:layout_gravity="start"/>

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

Navigation View Header Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:background="?attr/colorPrimaryDark"
          android:padding="16dp"
          android:theme="@style/ThemeOverlay.AppCompat.Dark"
          android:orientation="vertical"
          android:fitsSystemWindows="true"
          android:gravity="bottom">

<TextView
    android:visibility="gone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/text_user_name"
    android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

<TextView
    android:visibility="gone"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/text_email"
    android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>

<Button
    android:id="@+id/button_sign_in"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Sign In"/>

</LinearLayout>

I've searched through StackOverflow for a solution but couldn't find it. So someone please shed some light. Thanks in advance.

like image 692
Sreekanth Avatar asked Nov 05 '15 09:11

Sreekanth


People also ask

How can I change my status bar padding?

Go to Settings -> Display -> Advanced -> Device Theme The desired padding should be back again.

What is NavigationView in Android?

com.google.android.material.navigation.NavigationView. Represents a standard navigation menu for application. The menu contents can be populated by a menu resource file. NavigationView is typically placed inside a DrawerLayout .

How to use Navigation drawer in android app?

The user can view the navigation drawer when the user swipes a finger from the left edge of the activity. They can also find it from the home activity by tapping the app icon in the action bar. The drawer icon is displayed on all top-level destinations that use a DrawerLayout.


2 Answers

First, remember that you cannot draw behind status bar before Lollipop.

Solution

For Lollipop+, you should set the android:fitsSystemWindows="true" for DrawerLayout and leave the default for NavigationView .

Then on your activity or fragment after setting the header:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
    navigationView.setOnApplyWindowInsetsListener { v, insets ->

        val header = navigationView.getHeaderView(0)
        header.setPadding(
            header.paddingLeft, 
            header.paddingTop + insets.systemWindowInsetTop,
            header.paddingRight, 
            header.paddingBottom
        )
        insets.consumeSystemWindowInsets()
    }
}

Explanation

The window is passing a object called insets (with dimensions for top, left, bottom, right) to it's childs views. The child views that have the fitSystemWindows=true will do nothing with this insets and may send it forward to its children. The views that have it false may use the values to add extra padding or margin to itself.

Set fitSystemWindows=false of the NavigationView is not working because it is using the insets to apply extra margin to itself. What you want is your header view LinearLayout to apply this margin. But there is two intermediate container views inside NavigationView that will not pass forward the insets to your LinearLayout, so you have to intercept the windows inset before these containers and apply yourself the margin or padding of your header view.

What you should never do

Never assume that the window insets will be a fixed value or get them from resources, no matter what the Android version is. Specific devices have specific values for window insets, some have thicker "notches" to fit big cameras, some manufacturers decide to make it thinner than Android recommended specs.

like image 45
Allan Veloso Avatar answered Sep 19 '22 07:09

Allan Veloso


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

android:fitsSystemWindows="false"

and CoordinatorLayout => android:fitsSystemWindows="false"

like image 136
PanCrucian Avatar answered Sep 21 '22 07:09

PanCrucian