在状态和导航栏后面显示内容
Posted
技术标签:
【中文标题】在状态和导航栏后面显示内容【英文标题】:Showing content behind status and navigation bar 【发布时间】:2018-01-13 14:21:16 【问题描述】:这看起来像是一个重复的问题,但我做不到。我想要完全透明(不是半透明)的状态栏以及导航栏,并希望内容出现在它们后面。
activity_details.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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_
android:layout_
android:background="@color/colorPrimary"
tools:context="com.bitspilanidvm.bosm2017.DetailsActivity">
<ImageView
android:layout_
android:layout_
android:src="@drawable/q"
android:scaleType="centerCrop"/>
</LinearLayout>
v21 样式.xml
<resources>
<!-- Theme for API level > 21 -->
<style name="AppTheme" parent="AppBaseTheme">
<!--Customize your theme here. -->
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
在活动java文件中
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
这就是我得到的。
如何获取导航栏后面的内容?
如果我添加
<item name="android:windowTranslucentNavigation">true</item>
到我的styles.xml
这是我得到的
如您所见,内容位于导航栏后面,但导航栏必须是半透明的。
有什么解决办法吗?
【问题讨论】:
这个设备没有硬后退按钮吗? 【参考方案1】:在窗口中添加FLAG_LAYOUT_NO_LIMITS
标志。这适用于 Android KitKat 及更高版本的 API。示例如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
FLAG_FULLSCREEN
不起作用的原因仅仅是因为 FULLSCREEN 标志用于删除状态栏等屏幕装饰(适用于您)。但是导航栏不是屏幕装饰。 LAYOUT_NO_LIMIT
标志允许窗口超出屏幕限制,因此导航栏也被此标志覆盖。
您还可以通过将应用设置为沉浸式模式来简单地隐藏导航和状态栏。
编辑
API ViewCompat.setOnApplyWindowInsetListener
解决了 android:fitsSystemWindows=”true”
无法解决的问题,并且窗口插图可以应用于特定视图。一个例子。
ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) ->
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
params.topMargin = insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
);
FrameLayout
、LinearLayout
或 RelativeLayout
等标准布局不会将窗口插图传递给其子级,而材质布局则可以(例如 DrawerLayout
、CoordinatorLayout
)。所以我们可以将我们的布局更改为任何材质,或者我们可以子类化一个标准布局并自己将 insets 传递给布局的子级。我们只需要覆盖onApplyWindowInsets
方法。
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets)
int childCount = getChildCount();
for (int index = 0; index < childCount; ++index)
getChildAt(index).dispatchApplyWindowInsets(insets);
// let children know about WindowInsets
return insets;
参考文档:OnApplyWindowInsetsListener、WindowInsets
【讨论】:
谢谢!它工作得很好。你能简要解释一下为什么会这样吗?为什么将装饰视图系统 ui 可见性标志设置为 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 不起作用? FLAG_FULLSCREEN 不起作用的原因仅仅是因为 FULLSCREEN 标志用于删除状态栏等屏幕装饰(对您有用)。但是导航栏不是屏幕装饰。 LAYOUT_NO_LIMIT 标志允许窗口超出屏幕限制,因此导航栏也被此标志覆盖。 这行得通!但现在的问题是窗口从不应用插图,所以我无法知道状态栏和导航栏在哪里(不使用一些 hacky 解决方法)。关于我们如何在onApplyWindowInsets()
中接收插图的任何线索?
@Bryan 我不明白你的问题。应用上述代码后,状态和导航栏是透明的。您可以将插图应用于任何特定视图。 FrameLayout
、LinearLayout
等布局不会将窗口插图传递给它们的子级,而材质布局(DrawerLayout
、CoordinatorLayout
)可以。我已经编辑了答案并添加了关于插图的内容。但我对你的问题还是含糊其辞。【参考方案2】:
我想评论接受的答案,但我还不能。
只是为了警告所有会采取这种方法的人
FLAG_LAYOUT_NO_LIMITS 让您将根视图扩展到屏幕边界之外,从而为您的布局设计带来其他问题。例如,此标志通过强制系统忽略“adjustPan”和“adjustResize”标志来简单地破坏表单的可读性
所以,即使我仍然认为 Ahbi 的答案是正确的,但请确保没有任何内容超出此标志的范围
更好的解决方案:
实际上,我刚刚找到了一种更好的方法来实现相同的结果,而不会破坏任何东西
这是我的样式文件
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
这些是我以编程方式设置的标志
w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
设置标志 LAYOUT_HIDE_NAVIGATION(与样式项结合)起到了作用,我的表单仍然对 adjustPan 标志作出反应
【讨论】:
在回答这个问题时,我没有考虑过像adjustPan
这样的其他标志。谢谢指正。【参考方案3】:
如果您希望图像显示在状态栏后面
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
但是这样做,fitsSystemWindows="true"
不起作用
工具栏与状态栏重叠。
【讨论】:
以上是关于在状态和导航栏后面显示内容的主要内容,如果未能解决你的问题,请参考以下文章