在状态和导航栏后面显示内容

Showing content behind status and navigation bar

这看起来像是一个重复的问题,但我做不到。我想要完全透明(非半透明)的状态栏和导航栏,并希望内容显示在它们后面。

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_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context="com.bitspilanidvm.bosm2017.DetailsActivity">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/q"
    android:scaleType="centerCrop"/>

</LinearLayout>

v21styles.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>

在 activity java 文件中

getWindow().getDecorView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
               View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        );

这就是我得到的。

如何获取导航栏后面的内容?

如果我加

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

我的styles.xml

这是我得到的

如您所见,内容位于导航栏后面,但为此导航栏必须是半透明的。

有解决办法吗?

在 Window 中添加 FLAG_LAYOUT_NO_LIMITS 标志。这将适用于 Android KitKat 和 APIs 以上。这方面的例子是这样的:

 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 标志允许 window 超出屏幕限制,因此导航栏也包含在该标志内。

您也可以通过将应用程序设置为沉浸模式来简单地隐藏导航栏和状态栏。

编辑 API ViewCompat.setOnApplyWindowInsetListener 解决了 android:fitsSystemWindows=”true” 没有解决的问题,并且 window 插图可以应用于特定视图。举个例子。

ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
    params.topMargin = insets.getSystemWindowInsetTop();
    return insets.consumeSystemWindowInsets();
});

FrameLayoutLinearLayoutRelativeLayout 等标准布局不会将 window 插入传递给它们的 children,而 material 布局会做(例如 DrawerLayoutCoordinatorLayout )。所以我们可以将我们的布局更改为任何 material 布局,或者我们可以继承标准布局并将插图传递给我们自己的 children 布局。我们只需要覆盖 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

我想对已接受的答案发表评论,但我现在还不能。

只是警告所有将采用这种方法的人

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 标志做出反应

如果你想让图片显示在状态栏后面

getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

但是通过这样做,fitsSystemWindows="true" 不起作用 工具栏与状态栏重叠。