【问题标题】:Make navigation drawer draw behind status bar使导航抽屉在状态栏后面绘制
【发布时间】:2015-01-10 21:17:15
【问题描述】:

我正在尝试创建一个导航抽屉,类似于 Material 规范中的导航抽屉(比如新 gmail 应用中的导航抽屉)。注意导航抽屉的内容是如何绘制在状态栏后面的:

使用this question 的 Chris Banes 的回答,我能够成功地将应用程序中的导航抽屉绘制在状态栏后面;这工作正常。不起作用的是在状态栏后面绘制导航抽屉的内容。我希望抽屉中的蓝色图像显示在状态栏的后面,但该区域是用状态栏的颜色绘制的,如此屏幕截图所示。

那么,我怎样才能让我的导航抽屉在状态栏后面的区域中绘制呢?我已经在下面发布了我项目的相关部分。

包含导航抽屉的基本布局:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:fitsSystemWindows="true">

    <!-- Framelayout to display Fragments -->
    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/warning_container" />

    <FrameLayout
        android:id="@+id/navigation_drawer_fragment_container"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:layout_gravity="start">

        <fragment
            android:id="@+id/navigation_drawer_fragment"
            android:name="com.thebluealliance.androidclient.fragments.NavigationDrawerFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:layout="@layout/fragment_navigation_drawer" />

    </FrameLayout>

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

我的活动主题

<style name="AppThemeNoActionBar" parent="AppTheme">
    <item name="windowActionBar">false</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

在我的活动onCreate() 中,我执行以下操作:

mDrawerLayout.setStatusBarBackground(R.color.primary_dark);

【问题讨论】:

  • 您查看过 Chris Banes 的问答吗? stackoverflow.com/q/26440879/82788
  • 您阅读我的问题了吗?我特别提到我看了他的回答并按照他的指示进行操作。
  • 对不起,我显然没有像我想象的那样彻底阅读它。 :)

标签: android android-layout android-navigation


【解决方案1】:

适用于 API 21+

<style name="AppTheme" parent="android:Theme.Holo.NoActionBar.TranslucentDecor">
    ...
</style>

适用于 API 19+

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowTranslucentStatus">true</item>
</style>

您的布局应该有android:fitsSystemWindows="false"(这是默认设置)。


现在,既然您想切换半透明,您可以通过编程方式进行:

Window window = getWindow();

// Enable status bar translucency (requires API 19)
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
        WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

// Disable status bar translucency (requires API 19)
window.getAttributes().flags &= (~WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

// Set a color (requires API 21)
window.setStatusBarColor(Color.RED);

我把所有的 sdk 版本检查留给你 :)


【讨论】:

  • AppCompat 好像没有对应的主题。
  • @NathanWalters 是什么让您认为 Gmail 使用 AppCompat?
  • 他们在 5.0 以外的 Android 版本上提供材料设计的事实。当他们已经投入大量时间来创建 AppCompat 的所有功能时,复制它的所有功能将毫无意义。
  • @NathanWalters 好吧,因为我无法获得您在我的 gmail 应用程序上显示的屏幕,所以我在 api 21 和 api 17 上尝试了Billy。一个有一个透明的状态栏,另一个有一个坚实的一个。你有没有在较低的 api 上看到一个透明的状态栏或者你在猜?
  • @NathanWalters 我的回答有什么问题吗?我确实回答了你的问题。
【解决方案2】:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:fitsSystemWindows="true">

        <include layout="@layout/toolbar" />
        <!-- Main layout -->
        <FrameLayout
            android:id="@+id/main_fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    <!-- Nav drawer -->
    <fragment
        android:id="@+id/fragment_drawer"
        android:name="com.example.DrawerFragment"
        android:layout_width="@dimen/drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="left|start"
        android:fitsSystemWindows="true" />

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

values/themes.xml

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@color/primary</item>
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:textColorPrimary">@color/textColorPrimary</item>
</style>

<style name="AppTheme" parent="AppTheme.Base">
</style>

values-v19/themes.xml

<style name="AppTheme" parent="AppTheme.Base">
    <!--This makes the status bar transparent in KK and Lollipop-->
    <!--You do not need values-v21 and if you create them make sure you extend from this one-->
    <item name="android:windowTranslucentStatus">true</item>
</style>

如果你想改变状态栏的颜色(不同于透明黑色),你需要在自定义视图中选择the other approach,因为 mDrawerLayout.setStatusBarBackgroundColor(int)只有在这个DrawerLayout适合SystemWindows时才会被激活(@ 987654327@),如果你这样做,它不会被绘制在状态栏后面,而是在它下面。

【讨论】:

  • 这个问题和官方答案是它不会给状态栏着色。使用第一个孩子的背景(LinearLayout)而不是提供的颜色。
  • 经过更多测试后我修改了答案
  • ScrimInsetFrameLayout 对于三星设备是必需的,因为默认情况下它们不会用透明黑色绘制状态栏。因此,要保持跨设备的一致性,您需要 ScrimInsetFrameLayout。
【解决方案3】:

我找到了在 Android 5.0 上执行此操作的最佳方法。关键是使用ScrimInsetFrameLayout 作为导航抽屉的根元素(DrawerLayout 中的第二个视图)。这将使内容扩展以填充状态栏后面的空间。要正确着色插图,您可以在ScrimInsetFrameLayout 上设置以下属性:

app:insetForeground="#4000"

另外,请确保您在稀松布布局上有 android:fitsSystemWindows="true"

ScrimInsetFrameLayout 的源代码可以在这里找到:https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/ScrimInsetsFrameLayout.java

【讨论】:

  • ScrimInsetFrameLayout 不是必需的。我不知道为什么这个答案被接受了。
  • @jpardogo 那么最好的方法是什么?我认为 Google 自己设计应用程序的方式是最正确的方式
  • Lollipop 未在此应用发布时发布。他们用 chris banes(Android 开发者关系团队中的 DPE)解释的方式是正确的。我知道它不起作用,但我通过修改来回答这个问题以使其起作用。您不需要为此自定义视图。它可以在本地运行。
  • 不,Lollipop 没有发布,但 Material Design 也没有发布。此行为伴随着 I/O 的更新而来。不管怎样,我刚试过你的方法,得到的结果和以前完全一样。
  • 你的解决方案给了我原来的东西:导航抽屉延伸到状态栏后面,但导航抽屉的内容没有。我逐字使用了您的解决方案。
【解决方案4】:

对于每个在半透明状态栏与导航栏组合中苦苦挣扎但不愿将&lt;style name="yourAppTheme" parent= 更改为"android:Theme.Holo.NoActionBar.TranslucentDecor" 的人,只需在您的 style.xml 中添加这些行:

    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item> 
    <item name="android:windowContentOverlay">@null</item>

【讨论】:

    【解决方案5】:

    在您的目录“values-v21”中,添加以下行:

    <style name="AppTheme" parent="BaseTheme">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowSharedElementsUseOverlay">false</item>
    </style>
    

    【讨论】:

      【解决方案6】:

      只需将这两个值添加到 values-v21 中的主题样式中

      <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        ..
        <item name="android:statusBarColor">@android:color/transparent</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
      </style>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-27
        • 1970-01-01
        相关资源
        最近更新 更多