透明状态栏(具有可见导航栏)
我知道这个问题已经被问了很多次,但所有的答案要么不起作用,要么使用了过时的代码:
- Android Completely transparent Status Bar?
- Transparent status bar - before Android 4.4 (KitKat)
- Lollipop : draw behind statusBar with its color set to transparent
我想达到与最新谷歌地图应用程序相同的效果:
- 完全透明的状态栏(仅限状态栏。不是导航栏!)
- 非推荐使用的解决方案
WindowCompat.setDecorFitsSystemWindows(window, false)
部分工作,因为它还会隐藏导航栏
解决方案
第一步:要使状态栏透明:将以下内容添加到样式themes.xml
或sytles.xml
:
<item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
第二步:然后在活动中使状态栏与活动重叠:
从API级别30起,已使用的窗口标志已过时,因此它们可以使用到API级别29:
if (Build.VERSION.SDK_INT in 21..29) {
window.statusBarColor = Color.TRANSPARENT
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
} else if (Build.VERSION.SDK_INT >= 30) {
window.statusBarColor = Color.TRANSPARENT
// Making status bar overlaps with the activity
WindowCompat.setDecorFitsSystemWindows(window, false)
}
API-30更新
这实际上并不会使状态栏变得透明,而是使其变得半透明,并且仍会有阴影
这在API-30上是正确的,原因是设置<item name="android:windowTranslucentStatus">true</item>
。
实际上<item name="android:windowTranslucentStatus">true</item>
只在API级别19上是必需的。如果您的应用程序高于该级别,您可以完全取消它。
无论如何,解决这个问题的方法是覆盖API-30中的hemes.xml/style es.xml;即有一个resvalues-v30 hemes.xml
;您只需添加如下所示的应用程序主主题:
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.TransparentStatusBar" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- 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>
</style>
</resources>
API-30更新2
刚刚在API 30上发现了一个错误,即底部导航与隐藏底部的活动重叠,这可能无法被操作员发现,因为他们正在使用地图。
若要解决此问题,请As per documentation:
您可以通过对插页做出反应来处理重叠,插页指定了 屏幕的某些部分与系统用户界面相交,如导航 栏或状态栏。相交可以简单地表示显示 在内容之上,但它还可以通知您的应用程序有关系统的信息 手势也一样。
因此,我们需要处理API级别30+的系统栏插页,以避免您的应用程序与导航栏重叠:
这需要活动布局的顶根ViewGroup
,因此需要适当地滑动LayoutParams
。
这里我使用ConstraintLayout
作为根布局,FrameLayout.LayoutParams
:
/*
* Making the Navigation system bar not overlapping with the activity
*/
if (Build.VERSION.SDK_INT >= 30) {
// Root ViewGroup of my activity
val root = findViewById<ConstraintLayout>(R.id.root)
ViewCompat.setOnApplyWindowInsetsListener(root) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
// Apply the insets as a margin to the view. Here the system is setting
// only the bottom, left, and right dimensions, but apply whichever insets are
// appropriate to your layout. You can also update the view padding
// if that's more appropriate.
view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
leftMargin = insets.left
bottomMargin = insets.bottom
rightMargin = insets.right
}
// Return CONSUMED if you don't want want the window insets to keep being
// passed down to descendant views.
WindowInsetsCompat.CONSUMED
}
}
这在API级别19到API级别30的8个设备/仿真器上进行了测试。
相关文章