我搜索了文档,但只找到了这个: 链接。这是用来使酒吧半透明?我想做的是使状态栏完全透明(如下图所示),并使它向后兼容APK<19:

我的styles.xml:

<resources xmlns:tools="http://schemas.android.com/tools">

  <style name="AppTheme" parent="Theme.AppCompat.Light">
  <item name="android:actionBarStyle">@style/ThemeActionBar</item>
  <item name="android:windowActionBarOverlay">true</item>
  <!-- Support library compatibility -->
  <item name="actionBarStyle">@style/ThemeActionBar</item>
  <item name="windowActionBarOverlay">true</item>
  </style>

  <style name="ThemeActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid">
  <item name="android:background"> @null </item>
  <!-- Support library compatibility -->
  <item name="background">@null</item>
  <item name="android:displayOptions"> showHome | useLogo</item>
  <item name="displayOptions">showHome|useLogo</item>

  </style>

</resources>

我能做的是:


当前回答

这个解决方案是为那些谁想要一个完全透明的状态栏和导航栏不受影响。令人难以置信的是,这听起来如此简单,以至于导致包括我在内的不止一个人头疼。

这就是我所说的最终结果

结果

我们只需要两个函数,我建议在我们的活动的OnCreate中调用,第一个是setStatusBar(),这是负责使透明的同一个。

private fun setStatusBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.apply {
        clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        } else {
            decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        }
        statusBarColor = Color.TRANSPARENT
    }
}

第二个函数setedges()负责设置与顶部受限的视图相对应的边距,否则,这些视图将在StatusBar下面被看到。

private fun setMargins() {
    ViewCompat.setOnApplyWindowInsetsListener(
        findViewById(R.id.your_parent_view)
    ) { _, insets ->
        val view = findViewById<FrameLayout>(R.id.your_child_view)
        val params = view.layoutParams as ViewGroup.MarginLayoutParams
        params.setMargins(
            0,
            insets.systemWindowInsetTop,
            0,
            0
        )
        view.layoutParams = params
        insets.consumeSystemWindowInsets()
    }
}

最终代码看起来像这样:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.your_layout))
        setStatusBar()
        setMargins()
}

private fun setStatusBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.apply {
        clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        } else {
            decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        }
        statusBarColor = Color.TRANSPARENT
    }
}

private fun setMargins() {
    ViewCompat.setOnApplyWindowInsetsListener(
        findViewById(R.id.your_parent_view)
    ) { _, insets ->
        val view = findViewById<FrameLayout>(R.id.your_child_view)
        val params = view.layoutParams as ViewGroup.MarginLayoutParams
        params.setMargins(
            0,
            insets.systemWindowInsetTop,
            0,
            0
        )
        view.layoutParams = params
        insets.consumeSystemWindowInsets()
    }
}

你可以在下面的文章中找到更详细的解释

我还留下了一个测试项目,这些概念在其中发挥作用。

其他回答

我在调查这个图书馆的时候找到了答案: https://github.com/laobie/StatusBarUtil

因此,您需要将以下代码添加到您的活动

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
    window.statusBarColor = Color.TRANSPARENT
} else {
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
</style>

完全透明的状态栏和导航栏

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    transparentStatusAndNavigation();
}


private void transparentStatusAndNavigation() {
    //make full transparent statusBar
    if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
        setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, true);
    }
    if (Build.VERSION.SDK_INT >= 19) {
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        );
    }
    if (Build.VERSION.SDK_INT >= 21) {
        setWindowFlag(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, false);
        getWindow().setStatusBarColor(Color.TRANSPARENT);
        getWindow().setNavigationBarColor(Color.TRANSPARENT);
    }
}

private void setWindowFlag(final int bits, boolean on) {
    Window win = getWindow();
    WindowManager.LayoutParams winParams = win.getAttributes();
    if (on) {
        winParams.flags |= bits;
    } else {
        winParams.flags &= ~bits;
    }
    win.setAttributes(winParams);
}

我发现摆弄styles.xml和activity太麻烦了,因此创建了一个通用的实用工具方法,它有以下选项集

Java

Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.setStatusBarColor(Color.TRANSPARENT);

Kotlin DSL

activity.window.apply {
    clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
    decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    statusBarColor = Color.TRANSPARENT
}

这就是实现透明状态栏所需要的全部内容。希望这能有所帮助。

对于API > 23日/夜支持,您可以使用下面的扩展。要理解的重要部分是android:fitsSystemWindows="true"使用填充来在嵌入内移动(就像你会用一个工具栏)。因此,将它放在根布局中是没有意义的(除了DrawerLayout, CoordinatorLayout,…它们使用自己的实现)。

<style name="Theme.YourApp.DayNight" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    ...
    <item name="android:windowLightStatusBar">@bool/isDayMode</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>
<androidx.constraintlayout.widget.ConstraintLayout
    ...>

    <com.google.android.material.appbar.MaterialToolbar
        ...
        android:fitsSystemWindows="true">

</androidx.constraintlayout.widget.ConstraintLayout
fun Activity.transparentStatusBar() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
    } else {
        window.setDecorFitsSystemWindows(false)
    }
}

然后像这样称呼它:

class YourActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        transparentStatusBar()
    }
}

看看克里斯·巴内斯的这些幻灯片:成为窗户安装大师

编辑:如果你对导航栏后面的浮动内容有问题,请使用

// using Insetter
binding.yourViewHere.applySystemWindowInsetsToPadding(bottom = true)