5

I would like to remove paddingTop/marginTop from the navigation view in Multi-Window mode of Android N. Like Gmail already does. If you see the image below, I'm talking about the normal padding with size equals to the status bar at the beginning of the navigation view.

enter image description here

So basically in Multi-Window mode (see the image below) I have to remove that padding when my app is in the second part of the screen.

enter image description here

Unfortunately from the new api 24 you have isInMultiWindowMode() but it's not possible to know in which part of the screen is your app.

Marcin Koziński
  • 10,835
  • 3
  • 47
  • 61
br00
  • 1,391
  • 11
  • 21

2 Answers2

2

Instead of trying to figure out if you're in multi-window mode and on which part of the screen, you need to make your navigation view header respect system windows insets.

Normally you care about just one window - the one your app is drawn in. Usually you don't even think there are any windows. Isn't your app drawn fullscreen? Well, actually no. Usually there is some space reserved for system bars, like status bar at the top and navigation bar at the bottom. They are drawn in separate windows - system windows. (Oh, and now we've got multi-window mode in N. More like multi-app-window mode, because if you count system windows then multi-window has been around for a while.)

You can make your navigation view header adjust its insets depending on whether it is under a system window (in this case: status bar) or not with just a few simple tweaks.

Assuming the navigation view is defined like that:

<android.support.design.widget.NavigationView
    ...
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    ... />

and there is a simple header layout in nav_header_main.xml:

<?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="@dimen/nav_header_height"
    android:background="@drawable/nav_header_background"
    android:orientation="vertical"
    android:paddingBottom="16dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="32dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/default_profile_picture" />

    ...

</LinearLayout>

you just need change it like that:

<?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="@dimen/nav_header_height"
    android:background="@drawable/nav_header_background"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/sym_def_app_icon"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginTop="8dp"/>

    ...

</LinearLayout>
  1. First you need to add android:fitsSystemWindows="true" to the layout.
  2. Now you need to make top padding smaller, as fitsSystemWindows will automatically add padding the size of status bar. So previously your top padding was from the top of your header, now it is only from the bottom of the status bar.
  3. And you have to move all your paddings from the layout somewhere else (for example I moved them to margins on child views), because fitsSystemWindows will overwrite those paddings.

After this if your app is in the bottom part of multi-window split then the padding for status bar will not be added. It will also make your navigation view look properly in any other cases where it's not under the status bar or if the status bar changes size in any future version of Android or some crazy custom ROM.

Marcin Koziński
  • 10,835
  • 3
  • 47
  • 61
  • I thought android:fitsSystemWindows="true" in NavigationView was enough. Adding android:fitsSystemWindows also in the header layout fix the problem. Thanks – br00 Aug 26 '16 at 09:24
  • I've just found that this solution works only for the api 24+ – br00 Sep 02 '16 at 08:38
1

For me nothing was working so I ended up going this route and it got the job done:

<android.support.design.widget.NavigationView
    ...
    app:insetForeground="@null"/>

Technically, the insets are still present but since the insetForeground resource used to draw on them is now null, that logic is skipped in ScrimInsetsFrameLayout's onDraw method (which is the parent class of NavigationView).

So when all else fails, this is a fairly efficient route.

gMale
  • 17,147
  • 17
  • 91
  • 116