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

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

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

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

【问题讨论】:

    标签: android android-navigationview android-statusbar android-7.0-nougat


    【解决方案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_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>
    

    你只需要像这样改变它:

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

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

    【讨论】:

      猜你喜欢
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多