CoordinatorLayout не рисует за строкой состояния даже с windowTranslucentStatus и fitsSystemWindows

Я пытаюсь нарисовать представления за строкой состояния следующим образом: Желаемый результат

Я пытался создать этот эффект с помощью рекомендованных техник, но у меня получилось следующее:

Фактический результат

На снимке экрана видно, что содержимое моего приложения не отображается за строкой состояния.

Интересно то, что каким-то образом Nav Drawer удается рисовать за строкой состояния:

введите здесь описание изображения

Что я сделал:

  • Используйте виджеты библиотеки поддержки - CoordinatorLayout, AppBarLayout, Toolbar, DrawerLayout
  • windowTranslucentStatus установлен на true в моей теме приложения
  • fitsSystemWindows установлен на true на моем CoordinatorLayout

Это моя тема приложения:

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

comment
Попробуйте установить fitsSystemWindows=false в макете ящика.   -  person natario    schedule 12.11.2015
comment
@mvai Я только что попробовал, и, похоже, ничего не изменилось   -  person Joshua    schedule 12.11.2015
comment
У меня была аналогичная проблема, попробуйте следующее: фрагмент панели инструментов координатора панели"> stackoverflow.com/questions/34761671/   -  person milechainsaw    schedule 09.06.2016
comment
см. этот ответ: stackoverflow.com/a/47906087/2201814   -  person MHSFisher    schedule 20.12.2017


Ответы (4)


изменить для будущих читателей: есть много полезной информации по этому вопросу, а также о проблеме в комментариях, обязательно прочитайте их.

исходный ответ: ваша тема неверна, вот почему. К сожалению, есть различия в том, как активировать в Kitkat или Lollipop. В моем коде я сделал это на Java, но вы также можете добиться этого в XML, если хотите поиграть с папками V21 в дереве ресурсов. Имена параметров будут очень похожи на их аналоги в Java.

Удалите android:windowTranslucentStatus из вашего XML и в 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.

Я посмотрел больше на свой код, и я уверен, что в моем макете НАМНОГО больше android:fitsSystemWindows="true", чем просто CoordinatorLayout.

ниже приведены все виды на моем макете с android:fitsSystemWindows="true" на них:

  • КоординаторМакет
  • AppBarLayout
  • СвернутьToolbarLayout
  • ImageView (с фоновым изображением)
  • FrameLayout (с содержимым шапки)

поэтому я предлагаю просто протестировать/попробовать заполнить android:fitsSystemWindows="true" в вашем XML.

person Budius    schedule 12.11.2015
comment
Ваш метод удаляет темный оттенок фона строки состояния, но он по-прежнему не позволяет моему CoordinatorLayout заполнить область за строкой состояния. Теперь это выглядит так: i.imgur.com/koMgcm0.png?1 - person Joshua; 12.11.2015
comment
К сожалению, применение fitsSystemWindows ко всему не сработало. Я даже пытался добавить CollapsingToolbarLayout с ImageView в свой макет фрагмента с помощью fitsSystemWindows, но это тоже не сработало. А если серьезно, спасибо за помощь. Я думаю, что мне придется попробовать некоторые неортодоксальные решения. - person Joshua; 12.11.2015
comment
Я почти уверен, что это работает только с моей Java и некоторыми fitSystemWindows. Я смотрю ваши макеты, я думаю, вам придется удалить из макета вашей деятельности. Я имею в виду, удалить из DrawerLayout, NavigationView и FrameLayout. Я думаю, вы добавляете true только к тому, что не должно быть за ним (например, у вас есть заголовок), но то, что должно быть за ним, не должно иметь fitSystemWindows - person Budius; 12.11.2015
comment
DrawerLayout и NavigationView нужны fitsSystemWindows, потому что они также должны отображаться за строкой состояния (согласно спецификации Material Design). FrameLayout на самом деле содержит мой контент (он заменен макетом фрагмента), поэтому ему тоже нужен fitsSystemWindows. Я начинаю думать, что это не работает, потому что я использую фрагменты... - person Joshua; 13.11.2015
comment
Мой проект тоже с фрагментами, причина не в этом. Я предполагаю, что вы неправильно интерпретируете fitSystemWindows developer.android.com /ссылка/android/view/ . Попробуйте. - person Budius; 13.11.2015
comment
Я заставил его работать! Вы были правы, я неправильно понял fitsSystemWindows. Он не расширяет представление, чтобы оно соответствовало системному окну, а фактически требует, чтобы представление избегало декораций окна, таких как строка состояния. Я решил проблему, удалив fitsSystemWindows из всего. Установка windowsTranslucentStatus на true в моей теме приложения достаточна для достижения желаемого эффекта; fitsSystemWindows на самом деле мешает этому. - person Joshua; 13.11.2015
comment
Я собираюсь принять ваш ответ как принятый ответ. Я думаю, что было бы полезно, если бы вы отредактировали свой ответ, включив в него краткое изложение моего объяснения или попросив читателей просмотреть комментарии. - person Joshua; 13.11.2015
comment
Можете ли вы добавить соответствующие свойства, которые вам нужно поместить в xml, чтобы добиться этого через xml вместо java? - person Bhargav; 13.01.2016
comment
Я не собираюсь проверять документацию вместо вас. Ссылка находится здесь: developer.android.com/reference/android/view/Window .html вы можете проверить. Это будет что-то вроде window:statusBarColor и window:flags - person Budius; 13.01.2016
comment
Спасибо ! кстати, если вы укажете fitsystemwindows = true для макета координатора и заставите панель инструментов прокручиваться вверх, указав свой viewpager appbar_scrolling_view_behavior, тогда, если цвет строки состояния прозрачен, панель инструментов будет находиться за строкой состояния, но поскольку строка состояния прозрачна, панель инструментов будет видна под строкой состояния , поэтому вам нужно передать свойство fitssystemwindows=true родителю макета координатора - person Bhargav; 13.01.2016
comment
@Bhargav, не могли бы вы рассказать, как справиться с этим сценарием DrawerLayout --> Cordinator -> AppBar -> ToolBar, LP и MM, он работает нормально, но с включенным свойством Translucent для KK, тогда панель инструментов помещается под него, а панель инструментов с добавлением результатов заполнения идет под панелью приложений. и панель приложений исправлена, я пробовал fsw для нескольких комбинаций, но они не работали, я должен использовать окна fitsystems в главном ящике, чтобы он не отображал тонированный SB при открытии ящика, предложите, пожалуйста.. - person mfaisalhyder; 18.06.2016

  1. Если я хочу рисовать за StatusBar, я использую CoordinatorLayout в качестве самого родительского представления Activity (android:fitsSystemWindows=" ЛОЖЬ")

стили.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>

Затем, если вы хотите изменить цвет statubar, вам нужно удалить 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. Если я хочу, чтобы StatusBar был полупрозрачным и одновременно удерживал вид от сокрытия за StatusBar, я использую в качестве основного родительского представления 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>

И 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>

Возможно, ключевым моментом здесь является уверенность в том, что вы используете AppCompactActivity, а также используете Theme.AppCompact в качестве корня для своих стилей.

person murt    schedule 25.11.2016

Это было действительно запутанным для меня, но в конце концов я понял это для моей комбинации представлений, которая выглядит так:

<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 в моем приложении, чтобы заставить работать прозрачную строку состояния:

Удалите android:windowTranslucentStatus из вашего XML и используйте 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);
   }
person Simon    schedule 23.10.2016

Добавь это

android:fitsSystemWindows="true"

во внутренних представлениях AppBarLayout это решило проблему для меня

person Mohammad Elsayed    schedule 01.08.2020