【问题标题】:Collapsing toolbar - toolbar under statusbar折叠工具栏 - 状态栏下的工具栏
【发布时间】:2016-09-14 14:05:38
【问题描述】:

我最近遇到了协调器布局的问题。当我尝试像this 示例那样创建简单的折叠工具栏布局时,工具栏似乎位于状态栏下方,如下面的屏幕截图所示(在 preLolipop 设备上一切正常,因为应用程序不会在状态栏下方绘制)。

我的 Activity 布局的代码 sn-p:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/imageCalculationDetail"
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:background="@drawable/ic_dummy_calculation"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@color/transparent"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

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

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="fill_vertical"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <include layout="@layout/container"/>

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

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

我的样式(仅限 v21),其中 BaseAppTheme 父级是 Theme.AppCompat.Light.NoActionBar:

<style name="AppTheme" parent="BaseAppTheme">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="android:colorAccent">@color/colorPrimary</item>
        <item name="android:colorButtonNormal">@color/button_state_list</item>
        <item name="android:statusBarColor">@color/transparent</item>
    </style>

【问题讨论】:

  • 发布您的 styles.xml 文件。
  • 我已将样式添加到问题中
  • 你的清单文件呢?您在那里指定了正确的样式吗?也发一个。因为我在棒棒糖模拟器上尝试了相同的布局并且一切正常。
  • @color/transparent 的值是多少?如果不是,请将其更改为 #00000000
  • 透明的值为@android:color/transparent,即#00000000

标签: android android-coordinatorlayout android-collapsingtoolbarlayout


【解决方案1】:

我明白了,问题是我有

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

在我的 BaseAppTheme 的工具栏样式中(对于其他活动,一切正常,对于带有半透明状态栏的折叠工具栏不是)。设置后

android:fitsSystemWindows="false"

到我的工具栏,一切正常。

【讨论】:

    【解决方案2】:

    对我来说

    在 XML 中向工具栏添加属性 fitSystemWindows="false" 有效。

    <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:fitsSystemWindows="false"
                    app:popupTheme="@style/AppTheme.PopupOverlay"
                    app:layout_collapseMode="pin"/>
    

    【讨论】:

      【解决方案3】:
      <item name="android:windowDrawsSystemBarBackgrounds">true</item>
      

      通过将其放入您的样式中,您就是在告诉 Android 您的应用负责绘制系统栏后面的内容。这就是为什么如果设置了这个标志,另一个答案中的“肮脏黑客”在技术上是正确的。

      除非您有明确的理由让该标志为真(我怀疑不是),否则请将其设置为假,以便操作系统为您正确偏移您的内容。您的状态栏应该仍然是半透明的。

      【讨论】:

      • 不将此值设置为 false 没有任何区别
      【解决方案4】:

      尝试从 ImageView 中删除 android:fitsSystemWindows="true"..

      <ImageView
                  android:id="@+id/imageCalculationDetail"
                  android:layout_width="match_parent"
                  android:layout_height="200dp"
                  android:background="@drawable/ic_dummy_calculation"
                  android:scaleType="centerCrop"
                  app:layout_collapseMode="parallax"/>
      

      【讨论】:

      • 去掉此标志后,工具栏在状态栏下方,但状态栏不再透明,整个折叠的工具栏被扭曲,这不是我们想要的效果
      • 请发截图好吗?
      【解决方案5】:

      以编程方式,您可以通过 Android 的 Window 类方法清除和添加相关标志来更改此行为。在相关的 Activity 中编写一个自定义函数并将您选择的颜色资源 ID 传递给它:

      Kotlin

      fun setStatusBar(color: Int) {
          val window = this.window
          window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
          window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
          window.statusBarColor = ContextCompat.getColor(this, color)
      }
      

      Java

      public void setStatusBar(int color) {
          Window window = this.getWindow();
          window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
          window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
          window.setStatusBarColor(ContextCompat.getColor(this, color));
      }
      

      然后,在 setContentView(R.layout.your_layout) 行之后从 Activity 的重写 onCreate 方法调用该函数。例如:

      Kotlin

      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.your_layout)
          setStatusBar(R.color.colorPrimaryDark)
          ...
      }
      

      Java

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.your_layout);
          setStatusBar(R.color.colorPrimaryDark);
          ...
      }
      

      【讨论】:

        【解决方案6】:

        对棒棒糖设备或更高版本的工具栏应用断点以包含 marginTop。

        值/dimens.xml

        <dimen name="toolbar_margin_top">0dp</dimen>
        

        values-v21/dimens.xml

        <dimen name="toolbar_margin_top">24dp</dimen>
        

        然后在你的布局中:

        <android.support.v7.widget.Toolbar
          .....
          android:layout_marginTop="@dimen/toolbar_margin_top"
        

        【讨论】:

        • 这似乎更像是一种解决方法,我想要一些干净的解决方案,example 中没有上边距
        • 如果你想拥有一个透明的状态栏,这是唯一的解决方法。否则,您需要在您的样式中禁用 android:windowDrawsSystemBarBackgrounds 属性:false
        【解决方案7】:

        注意对我有用。

        对我来说解决方案很简单:

        Top CoordinatorLayout 视图中添加android:fitsSystemWindows="false"

        【讨论】: