如何使状态栏透明而保留导航栏不透明?

17
我想在我的应用程序上拥有一个透明的状态栏(使背景穿过),但我希望底部的导航栏保持黑色。
通过设置 getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); 我可以使两者都透明。
通过设置 <item name="android:windowTranslucentStatus">true</item>,我可以使顶部半透明。
但是,我无法让顶部完全透明,而不使底部也变透明。使用 <item name="android:statusBarColor">@android:color/transparent</item> 或类似的方法不起作用。
有人知道如何制作一个完全透明的状态栏,而不影响导航栏吗?

我在另一篇帖子中回答了这个问题,它完美地工作使状态栏透明,同时导航栏保持稳定):Android完全透明状态栏 - ParSa
5个回答

18

要独立控制KitKat上状态和导航栏的半透明度,您可以在onCreate()方法中使用窗口管理器标志FLAG_TRANSLUSCENT_STATUSFLAG_TRANSLUSCENT_NAVIGATION。但是,在KitKat上,系统可能会在状态栏上绘制一个半透明的渐变遮罩层。这似乎是设备特定的:在我的KitKat设备上,它是完全透明的,但在Android Studio模拟器上它显示一个遮罩层。

在Lollipop或更高的版本中,您可以使用Window#setStatusBarColor(int)方法以及FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS窗口管理器标志来设置状态栏颜色。请注意,在这种情况下,您需要清除FLAG_TRANSLUSCENT_STATUS标志。如果您想要颜色是透明的,则意味着您的应用支持全屏模式并设置系统UI可见性,因此您的应用程序负责管理状态栏背景颜色。

将所有内容整合如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Window window = getWindow();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(0x00000000);  // transparent
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        int flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        window.addFlags(flags);
    }
    setContentView(R.layout.main);
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
}

使用的布局示例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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:background="#ff00ff00"
    android:fitsSystemWindows="false"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Hello World!"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </LinearLayout>

</RelativeLayout>

示例截图。

棒棒糖:

Lollipop+

奇巧巧克力:

Kitkat


谢谢。我尝试了这段代码(我的设备肯定是运行的 Android KitKat 以上版本),但它并没有创建一个透明的状态栏或导航栏,只有一个半透明的(所以状态栏/导航栏有一个比下面背景更暗的叠加层)。就好像它的颜色设置是 alpha 0.5。看到这个情况,我尝试在样式中将其颜色设置为 alpha 0 和 transparent,但都没有解决问题。我知道你说,“在这种情况下,半透明实际上意味着完全透明:没有应用任何颜色或 alpha 通道”,但我无法让它变得不再是半透明的。你知道为什么吗? - Elliptica
我在设置了标志后也尝试了Window#setNavigationBarColor(TransparentColor),但似乎对其半透明性没有任何影响(上面忘记提到了)。 - Elliptica
你说得很对。在某些设备上(或者可能是大多数设备!),它确实会在状态栏背景上显示一个半透明的遮罩层。只是碰巧在我的KitKat设备(Asus Transformer TF701T)上,它是完全透明的。我已经更新了答案,使用全屏布局和控制系统UI可见性来显示Lollipop+上完全透明的状态栏。但是我还没有找到一种可靠的方法来使KitKat上的状态栏完全透明。 - AGDownie
终于!!有东西可以用了!感谢楼主和AGDownie。 - ravindu1024

6

从API级别30开始,大多数窗口标志已被弃用,

使用WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS将使活动与导航栏重叠,并使其变为透明。

因此,在API级别30上使其工作的方法是使用setDecorFitsSystemWindows()

if (Build.VERSION.SDK_INT in 21..29) { 
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    window.decorView.systemUiVisibility =
        SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or SYSTEM_UI_FLAG_LAYOUT_STABLE
    window.statusBarColor = Color.TRANSPARENT
}

if (Build.VERSION.SDK_INT >= 30) {
    // Setting status bar color as not working with XML attribute
    window.statusBarColor = Color.TRANSPARENT
    // Making status bar overlaps with the activity
    WindowCompat.setDecorFitsSystemWindows(window, false)
}

请在styles.xml中保留以下内容:

<item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>

更新

如果你发现布局底部被底部导航栏遮挡了,请查看这个答案,以获取更详细的信息。


2
我搞定了 :D
private void setTransparentStatusBarOnly(Activity activity) {
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    // this lines ensure only the status-bar to become transparent without affecting the nav-bar
    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

如何相反地显示状态,但使导航栏透明? - Leo DroidCoder
您是个天才先生。 - A.I.Shakil

0

希望我的回答能够帮助到某个人。

fun setTransparentStatusBar(activity: Activity) {
            activity?.let {
                it.window?.let {
                    it.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                    it.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                    it.statusBarColor = Color.TRANSPARENT
                    it.decorView.systemUiVisibility =
                        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                }
            }
        }

0

我在 Kotlin 中重新发布了适用于我的正确答案:

在您的活动中的 setContentView 之前粘贴下面给出的代码

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.setStatusBarColor(0x00000000) // transparent
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        val flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
        window.addFlags(flags)
    }

在您的样式中,将下面两行粘贴到主题中:
    <item name="android:windowDrawsSystemBarBackgrounds">false</item>
    <item name="android:navigationBarColor">@color/colorBlack</item>

在您的布局中,只需将android:fitsSystemWindows="true"粘贴到父布局中,然后在您想要显示在状态栏背景中的子布局中也粘贴相同的android:fitsSystemWindows="true",如下所示:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/dish_details_rootLayout"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".bottomnav.menu.dishdetail.DishDetail"
android:fitsSystemWindows="true">



    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/dish_details_appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/dish_details_collapsingToolbar"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:fitsSystemWindows="true"
            app:expandedTitleTextAppearance="@color/colorTransparentwhite"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/dish_details_dish_imageView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:contentDescription="@null"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                android:fitsSystemWindows="true"/>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/dish_details_nestedScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="@+id/dish_details_horizontalGuideline1"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/dish_details_dishName"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="8dp"
                        android:fontFamily="@font/roboto"
                        android:padding="12dp"
                        android:text="Food Name"
                        android:textColor="@color/colorBlack"
                        android:textSize="24sp" />

                    <TextView
                        android:id="@+id/dish_details_dishPrice"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="8dp"
                        android:fontFamily="@font/roboto"
                        android:padding="12dp"
                        android:text="Rs. 200"
                        android:textSize="18sp"
                        android:textStyle="bold" />

                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">

                        <TextView
                            android:id="@+id/dish_details_dishRatingtxt"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="bottom"
                            android:layout_marginStart="12dp"
                            android:fontFamily="@font/roboto"
                            android:text="4.5"
                            android:textSize="24sp" />
                        <ImageView
                            android:layout_width="wrap_content"
                            android:layout_height="24sp"
                            android:layout_gravity="bottom"
                            android:layout_marginBottom="5dp"
                            android:src="@drawable/rating_star"/>
                    </LinearLayout>

                    <TextView
                        android:id="@+id/dish_details_dishDespricption"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="8dp"
                        android:fontFamily="@font/roboto"
                        android:padding="12dp"
                        android:text="Food Description"
                        android:textColor="@color/colorBlack"
                        android:textSize="16sp" />
                </LinearLayout>
            </androidx.cardview.widget.CardView>
        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:id="@+id/dish_detail_add_to_cartbtn"
android:text="Add to Cart"
android:textColor="@color/colorWhite"
android:layout_marginBottom="10dp"
android:background="@drawable/soothingred_btn_bg"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接