在 Android N 多窗口模式下删除导航视图顶部填充

Posted

技术标签:

【中文标题】在 Android N 多窗口模式下删除导航视图顶部填充【英文标题】:Removing navigation view top padding in Android N Multi-Window mode 【发布时间】:2017-01-02 00:37:18 【问题描述】:

我想在 android N 的多窗口模式下从导航视图中删除 paddingTop/marginTop。就像 Gmail 一样。 如果你看到下面的图片,我说的是正常的填充,大小等于导航视图开头的状态栏。

所以基本上在多窗口模式下(见下图),当我的应用位于屏幕的第二部分时,我必须删除该填充。

不幸的是,从新的 api 24 开始,您拥有 isInMultiWindowMode(),但无法知道您的应用位于屏幕的哪个部分。

【问题讨论】:

【参考方案1】:

您需要让导航视图标题尊重系统窗口插入,而不是试图弄清楚您是否处于多窗口模式以及屏幕的哪个部分。

通常你只关心一个窗口——你的应用程序被绘制的那个窗口。通常你甚至不认为有任何窗口。你的应用不是全屏绘制的吗?嗯,其实没有。通常会为系统栏保留一些空间,例如顶部的状态栏和底部的导航栏。它们被绘制在单独的窗口 - 系统窗口中。 (哦,现在我们在 N 中有了多窗口模式。更像是多应用程序窗口模式,因为如果你计算系统窗口,那么多窗口已经存在了一段时间。)

您可以让导航视图标题根据它是否在系统窗口下(在本例中为:状态栏)调整其插图,只需进行一些简单的调整。

假设导航视图是这样定义的:

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

nav_header_main.xml 中有一个简单的标题布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    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_
        android:layout_
        android:src="@android:drawable/default_profile_picture" />

    ...

</LinearLayout>

你只需要像这样改变它:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:background="@drawable/nav_header_background"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

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

    ...

</LinearLayout>
    首先您需要将android:fitsSystemWindows="true" 添加到布局中。 现在您需要将顶部填充变小,因为fitsSystemWindows 会自动添加填充状态栏的大小。因此,以前您的顶部填充来自标题的顶部,现在它仅来自状态栏的底部。 而且您必须将所有填充从布局中移到其他位置(例如,我将它们移动到子视图的边距),因为fitsSystemWindows 会覆盖这些填充。

在此之后,如果您的应用处于多窗口拆分的底部,则不会添加状态栏的填充。它还可以让您的导航视图在任何其他情况下看起来正常,如果它不在状态栏下方,或者状态栏在任何未来版本的 Android 或某些疯狂的自定义 ROM 中改变大小。

【讨论】:

我认为 NavigationView 中的 android:fitsSystemWindows="true" 就足够了。在标题布局中添加 android:fitsSystemWindows 也可以解决问题。谢谢 我刚刚发现这个解决方案只适用于 api 24+【参考方案2】:

对我来说没有任何效果,所以我最终选择了这条路线并完成了工作:

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

从技术上讲,插图仍然存在,但由于用于绘制它们的 insetForeground 资源现在为空,因此 logic is skipped in ScrimInsetsFrameLayout's onDraw method(它是 NavigationView 的父类)。

所以当所有其他方法都失败时,这是一条相当有效的路线。

【讨论】:

以上是关于在 Android N 多窗口模式下删除导航视图顶部填充的主要内容,如果未能解决你的问题,请参考以下文章

在Android N多窗口模式下按下主页按钮时未调用Activity onStop()

Unity3D3D 视图操作 ( 视图基本元素 | 导航器 | 栅格 | 天空盒 | 3D 视图操作 | 视图旋转 | 视图缩放 | 视图平移 | 导航器操作 | 恢复方向 | 顶右前视图 )

mfc中MDI模式下实现单文档多视图多窗口

Android N 多窗口布局 省电模式 全新通知功能

SwiftUI LandScape 导航顶栏不会隐藏

如何在android中删除底部导航视图的图标动画