安卓導航抽屜 Navigation Drawer 實現沉浸通知欄

AaronLin發表於2022-05-10

在使用 Navigation Drawer Activity 模版的時候,遇到了通知欄無法完全沉浸的問題,嘗試搜尋一些現有的解決方法,但是或多或少都會存在一些問題,通過反覆嘗試找到找到了一種比較靠譜的思路

環境

測試模擬器:Pixel 3A

compileSdk:32

minSdk:28

targetSdk:32

建立工程


預設效果展示:


修改步驟

  1. 設定狀態列變為透明:修改主題配置
 <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>

修改為:

<item name="android:statusBarColor">@android:color/transparent</item>

修改後完整檔案:

<resources>
    <!-- Base application theme. -->
    <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
+       <item name="android:statusBarColor">@android:color/transparent</item>
        <!-- Customize your theme here. -->
    </style>

    <style name="Theme.MyApplication.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="Theme.MyApplication.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="Theme.MyApplication.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

修改後的效果:

開啟抽屜發現已經透明,但是會覆蓋一層淺色陰影

  1. 在佈局中增加 fitsSystemWindows 屬性

app_bar_main.xmlandroidx.coordinatorlayout.widget.CoordinatorLayoutcom.google.android.material.appbar.AppBarLayout 中增加:android:fitsSystemWindows="true",這樣它會自動的給View增加一個值等於狀態列高度的 PaddingTop,讓它的背景顏色佔據狀態列

完整程式碼:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
+   android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
+       android:fitsSystemWindows="true"
        android:theme="@style/Theme.MyApplication.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.MyApplication.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

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

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginEnd="@dimen/fab_margin"
        android:layout_marginBottom="16dp"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

效果:


  1. 修改 activity_main.xml,給 com.google.android.material.navigation.NavigationView 增加上 app:insetForeground="@android:color/transparent",去除抽屜狀態列淺色陰影,

效果:

  1. 相容深色模式

切換到深色模式的效果:

修改:night/themes.xml

android:statusBarColor 設定為:@android:color/transparent

<item name="android:statusBarColor">@android:color/transparent</item>

開啟抽屜發現,這個時候狀態列已經透明瞭,但是狀態列背景還是會有一個黑色的背景色


修改 app_bar_main.xml,在 <com.google.android.material.appbar.AppBarLayout 中增加背景色,就可以了

android:background="?attr/colorPrimary"

最終效果:

fitsSystemWindows 屬性

android:fitsSystemWindows="true"官方文件描述

Boolean internal attribute to adjust view layout based on system windows such as the status bar.
If true, adjusts the padding of this view to leave space for the system windows.
Will only take effect if this view is in a non-embedded activity.

對某個 View 設定 fitsSystemWindows 為 true,本質就是給這個 View 設定了 padding,所以在 app_bar_main.xml 的 AppBarLayout 設定 fitsSystemWindows,這樣可以使得 AppBarLayout 的背景可以通過 padding 延展到狀態列,通過對 AppBarLayout 設定背景,就可以到達沉浸狀態列的效果

其他常用配置

設定狀態列為淺色模式(文字為黑字)

程式碼:

val controller = ViewCompat.getWindowInsetsController(binding.root)
controller?.isAppearanceLightStatusBars = true

或者使用主題 xml 來定義:

<item name="android:windowLightStatusBar">true</item>

參考資料

深色主題背景
What exactly does fitsSystemWindows do?
No Action Bar & Transparent Status Bar
Android沉浸式狀態列(透明狀態列)最佳實現
透明狀態列、全屏應用、沉浸模式
NavigationView陰影
定製你的Toolbar
Android 的style和theme

相關文章