Setting Statusbar padding to NavigationView in Android
我有一个活动,它承载来自支持库的 DrawerLayout 和 NavigationView。我正在为导航视图设置标题布局,并且我希望导航标题高度为"wrap_content"。因此,当我将高度设置为"wrap_content"时,标题布局位于状态栏后面。
我想要的结果是导航抽屉应该在状态栏后面绘制,但导航标题应该被状态栏高度向下推。
下面是我得到的截图。请注意状态栏后面的"登录"按钮。
活动布局
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <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> |
导航视图标题布局
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?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> |
我已经通过 StackOverflow 搜索解决方案,但找不到。所以有人请阐明一下。提前致谢。
1 2 3 4 5 6 7 8 | <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"
和 CoordinatorLayout => android:fitsSystemWindows="false"
首先,请记住,您不能在 Lollipop 之前在状态栏后面绘图。
解决方案
对于 Lollipop,您应该为
然后在你的activity或fragment上设置header:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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() } } |
解释
窗口正在将一个名为
Set
你不应该做的事
永远不要假设窗口插图是固定值或从资源中获取它们,无论 Android 版本是什么。特定设备对窗口嵌入有特定的值,有些具有较厚的"凹槽"以适应大型相机,有些制造商决定使其比 Android 推荐的规格更薄。
您正在使用
这些信息来自 Ian Lake 的这篇文章,"我为什么要适应 SystemWindows?"。
While the basic layouts (FrameLayout, LinearLayout, etc) use the default behavior, there are a number of layouts that already customize how they react to fitsSystemWindows to fit specific use cases.
...
CoordinatorLayout also takes advantage of overriding how it handles window insets, allowing the Behavior set on child Views to intercept and change how Views react to window insets, before calling dispatchApplyWindowInsets() on each child themselves. It also uses the fitsSystemWindows flag to know if it needs to paint the status bar background.
要实现您想要的,请确保遵循此布局结构。
布局/activity_xxxxx.xml
1 2 3 4 5 6 7 8 9 10 11 12 | <android.support.v4.widget.DrawerLayout ... android:fitsSystemWindows="true"> <!-- content --> ... <!-- drawer --> <android.support.design.widget.NavigationView ... android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header" /> |
布局/nav_header.xml
1 2 3 4 5 6 | <android.support.design.widget.CoordinatorLayout ... android:fitsSystemWindows="true"> <!-- content --> ... |