CoordinatorLayout即使使用了windowTranslucentStatus和fitsSystemWindows仍无法绘制到状态栏后面

27

我试图像这样在状态栏后面绘制视图:

所期望的结果

我尝试使用推荐的技术来实现这个效果,但我得到了这个:

实际结果

从截图中可以看出,我的应用程序内容没有任何一部分绘制在状态栏的后面。

有趣的是,底部导航栏设法在状态栏的后面绘制:

输入图像说明

我做的事情:

  • 使用支持库小部件 - CoordinatorLayoutAppBarLayoutToolbarDrawerLayout
  • 在我的应用程序主题中将windowTranslucentStatus设置为true
  • 在我的CoordinatorLayout上将fitsSystemWindows设置为true

这是我的应用程序主题:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@android:color/transparent</item>
    <item name="colorAccent">@color/colorAccent</item>

    <item name="android:windowTranslucentStatus">true</item>
</style>

这是我的活动布局:

<android.support.v4.widget.DrawerLayout
    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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <FrameLayout android:id="@+id/page_container"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:fitsSystemWindows="true"/>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

我的活动布局中的FrameLayout被替换为这个片段布局:

<android.support.design.widget.CoordinatorLayout
    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:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <FrameLayout android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:paddingLeft="@dimen/activity_horizontal_margin"
                 android:paddingRight="@dimen/activity_horizontal_margin"
                 android:paddingTop="@dimen/activity_vertical_margin"
                 android:paddingBottom="@dimen/activity_vertical_margin"
                 android:background="@android:color/holo_blue_bright"
                 tools:context=".MainActivity">

        <TextView android:text="@string/lorem_ipsum"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content" />
    </FrameLayout>

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        app:elevation="0dp"
        android:theme="@style/AppTheme.TransparentAppBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@android:color/transparent"
            app:title="@string/hello_blank_fragment"
            app:popupTheme="@style/AppTheme.OverflowMenu" />

    </android.support.design.widget.AppBarLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

尝试在抽屉布局上设置fitsSystemWindows="false"。 - natario
@mvai 我刚试了一下,似乎没有改变任何东西。 - Joshua
我遇到了类似的问题,试试这个链接: https://dev59.com/yuk6XIcBkEYKwwoYDPoQ#37713319 - milechainsaw
请查看此答案:https://dev59.com/yuk6XIcBkEYKwwoYDPoQ#47906087 - MHSaffari
4个回答

31

未来读者请注意:评论区有很多关于这个主题和问题的好信息,请务必仔细阅读。

原始回答: 你的主题是错误的,这就是原因。 不幸的是,在Kitkat或Lollipop中激活方式存在差异。在我的代码中,我是用Java实现的,但如果想要在资源树上玩弄V21文件夹,也可以使用XML。参数的名称与Java参数非常相似。

从你的XML中删除android:windowTranslucentStatus,在Java中像这样使用:

   public static void setTranslucentStatusBar(Window window) {
      if (window == null) return;
      int sdkInt = Build.VERSION.SDK_INT;
      if (sdkInt >= Build.VERSION_CODES.LOLLIPOP) {
         setTranslucentStatusBarLollipop(window);
      } else if (sdkInt >= Build.VERSION_CODES.KITKAT) {
         setTranslucentStatusBarKiKat(window);
      }
   }

  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
   private static void setTranslucentStatusBarLollipop(Window window) {
      window.setStatusBarColor(
             window.getContext()
                   .getResources()
                   .getColor(R.color. / add here your translucent color code /));
   }

   @TargetApi(Build.VERSION_CODES.KITKAT)
   private static void setTranslucentStatusBarKiKat(Window window) {
      window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
   }

然后您可以从活动中调用setTranslucentStatusBar(getWindow());

编辑:

在Android中,使状态栏半透明并在其后绘制(由于某些原因我无法理解)是两个不同的任务。

我在我的代码中仔细查看了更多,我确定我在布局上有比CoordinatorLayout更多的android:fitsSystemWindows="true"

以下是我布局中所有具有android:fitsSystemWindows="true"的视图:

  • CoordinatorLayout
  • AppBarLayout
  • CollapsingToolbarLayout
  • ImageView(带背景图像)
  • FrameLayout(带标题内容)

所以我的建议是只需在XML中尝试填充android:fitsSystemWindows="true"进行测试/尝试。


2
你的技巧去除了状态栏的深色背景,但仍然无法让我的CoordinatorLayout填充在状态栏后面的区域。现在它看起来像这样:http://i.imgur.com/koMgcm0.png?1 - Joshua
1
很抱歉要说,将fitsSystemWindows应用于所有东西并没有起作用。我甚至尝试在我的片段布局中添加一个带有ImageView的CollapsingToolbarLayout,并使用fitsSystemWindows,但这也没有起作用。非常感谢您的帮助。不过我想我必须尝试一些非正统的解决方案。 - Joshua
2
我的项目也使用了碎片,但这不是原因。我猜你误解了 fitSystemWindows https://developer.android.com/reference/android/view/View.html#setFitsSystemWindows(boolean) 。试一下吧。 - Budius
7
我搞定了!你说得对,我误解了 fitsSystemWindows。它并不是将视图扩展到“适应系统窗口”,而是请求视图避免窗口装饰,例如状态栏。我通过从所有内容中移除 fitsSystemWindows 来解决问题。在我的应用主题中设置 windowsTranslucentStatustrue 就足以实现我想要的效果;而 fitsSystemWindows 实际上会干扰这一效果。 - Joshua
1
@Bhargav,你能告诉我如何处理这种情况吗? DrawerLayout --> Cordinator ->AppBar ->ToolBar,LP 和 MM 没问题,但是在 KK 上启用半透明属性后,工具栏会被覆盖,添加填充会导致工具栏被固定在应用栏下面。我尝试了几种组合的 fsw,但都没有成功。我必须在主抽屉上使用 fitsystems 窗口,以便在打开抽屉时不显示着色的 SB,请给予建议。 - mfaisalhyder
显示剩余6条评论

1
这对我来说非常困惑,但最终我为我的视图组合找到了解决方法,它看起来像这样:

<android.support.v4.widget.SwipeRefreshLayout - **no fitsSystemWindow set**

<android.support.design.widget.CoordinatorLayout- android:fitsSystemWindows="true"

<android.support.design.widget.AppBarLayout - android:fitsSystemWindows="true"

<android.support.design.widget.CollapsingToolbarLayout - android:fitsSystemWindows="true"

<RelativeLayout - android:fitsSystemWindows="true"

<ImageView - android:fitsSystemWindows="true"

我也在我的应用中使用了Budius发布的方法来实现透明状态栏:
删除XML中的android:windowTranslucentStatus,并在Java中按照以下方式使用:
   public static void setTranslucentStatusBar(Window window) {
      if (window == null) return;
      int sdkInt = Build.VERSION.SDK_INT;
      if (sdkInt >= Build.VERSION_CODES.LOLLIPOP) {
         setTranslucentStatusBarLollipop(window);
      } else if (sdkInt >= Build.VERSION_CODES.KITKAT) {
         setTranslucentStatusBarKiKat(window);
      }
   }

  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
   private static void setTranslucentStatusBarLollipop(Window window) {
      window.setStatusBarColor(
             window.getContext()
                   .getResources()
                   .getColor(R.color. / add here your translucent color code /));
   }

   @TargetApi(Build.VERSION_CODES.KITKAT)
   private static void setTranslucentStatusBarKiKat(Window window) {
      window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
   }

你在我的问题上给了我一点帮助,因此+1。 - Ümañg ßürmån

1
  1. 如果我想在状态栏后面绘制,我会将CoordinatorLayout作为Activity的最顶层父视图(android:fitsSystemWindows="false")

styles.xml(v21)

<style name="MyTheme.NoActionBar.TransparentStatusBar">
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentStatus">true</item>
    </style>

如果你想改变状态栏颜色,你需要像这样移除TRANSLUENT_FLAG。
Window window = activity().getWindow();
        if(showTransluent){
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(Color.TRANSPARENT);
        }else {
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(ContextCompat.getColor(activity(), R.color.colorPrimaryDark));
        }
  1. 如果我想使状态栏透明,并同步确保视图不会被状态栏遮挡,我会使用最上层的父视图 FrameLayout,并添加参数

我的 styles.xml(v21) 如下所示:

<resources>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    </style>

    <style name="AppTheme.NoStatusBar" parent="AppTheme.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
    </style>
</resources>

And styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

也许这里的关键点是确保您在样式中使用AppCompactActivityTheme.AppCompact作为根。

1
添加这个
android:fitsSystemWindows="true"

在AppBarLayout的内部视图中,它为我解决了这个问题。

谢谢。我也一样。 - Ümañg ßürmån

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