Android:具有动态actionBar颜色和DrawerLayout的透明状态栏

时间:2016-07-05 09:34:38

标签: android xml android-coordinatorlayout drawerlayout android-statusbar

我有DrawerLayout的活动。我们的客户要求我们根据从DrawerLayout中选择的项目动态更改操作栏颜色和此活动的相应状态栏颜色。这很容易做到。但是,我的问题是,当我动态更改状态栏颜色时,我无法保持状态栏透明。当我打开抽屉时,彩色状态栏覆盖DrawerLayout的顶部,如下所示:

wrong layout

但是,我希望我的DrawerLayout看起来像这样:

correct layout

我可以使用以下行:

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

但是,我的问题不在于我无法设置状态栏的透明度。我的问题是动态更改状态栏和操作栏颜色不适用于windowTranslucentStatus。即使在我拨打colorPrimaryDark之后,我的状态栏颜色仍为getWindow().setStatusBarColor()(上图中状态栏上显示的芥末黄色)。

现在,我跟踪了this教程以及thisthis stackoverflow等问题,但无法解决问题。所有这些文章都说,ActionBar设置为windowTranslucentStatus后,true将移至状态栏下方的顶部(以便状态栏与操作栏重叠)。之后,我应该能够在操作栏中添加一些填充,只需更改操作栏颜色也会导致颜色相同的深色状态栏,因为状态栏实际上是半透明的并且与我的操作栏重叠。但是,出于某种原因,在我的情况下不会发生这种情况。无论我将fitsSystemWindows设置为true还是false还是完全删除该属性,操作栏都会保留在原位。操作栏总是在下面状态栏,当然,如果我设置透明度,它总是黄色。

我还尝试以编程方式更改状态栏颜色时设置alpha。这确实使状态栏有点透明,但它看起来很奇怪,因为它不再是 dark 了。删除CoordinatorLayout也无济于事。我花了几个小时试图解决这个问题,现在非常沮丧。任何帮助是极大的赞赏。

我的activity_main

<?xml version="1.0" encoding="utf-8"?>
<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">

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

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

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/nav_menu_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="@dimen/nav_header_height"
        android:clipToPadding="false"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/size_14dp"
        app:layoutManager="LinearLayoutManager" />
</android.support.design.widget.NavigationView>

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

这是我的app_bar_main的XML:

<?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"
xmlns:tools="http://schemas.android.com/tools"
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:theme="@style/AppTheme.AppBarOverlay"
    app:elevation="0dp">


    <FrameLayout
        android:id="@+id/toolbar_container"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary" />

        <com.quintype.sakshipost.Widgets.CustomMaterialSearchView
            android:id="@+id/search_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </FrameLayout>

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

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

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

3 个答案:

答案 0 :(得分:7)

导致您的问题是因为getWindow().setStatusBarColor()DrawerLayout不兼容。为了使您的状态栏保持半透明以及能够更改其颜色,您必须按照以下过程进行操作:

v21/styles.xml 文件中添加/修改以下主题,如下所示:

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

这是标准DrawerLayout使用的主题(当然,假设您在具有DrawerLayout的活动中使用此主题)。如您所知,这将使您的状态栏保持半透明状态。

接下来,从android:fitsSystemWindows="true"中的CoordinatorLayout移除app_bar_main

接下来,无论您在何处更改工具栏/状态栏的颜色,请使用与工具栏相同的颜色使用drawerLayout.setStatusBarBackground(colorDrawable)(当然,假设您对DrawerLayout的引用是叫drawerLayout)。请注意,drawerLayout.setStatusBarBackground()方法采用Drawable对象,与采用window.setStatusBarColor()颜色的int方法不同,因此您可能需要使用某些内容将颜色转换为可绘制颜色像这样:

new ColorDrawable(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary))

这将确保您的状态栏是半透明的,并使其能够更改颜色。希望你能够让它发挥作用。

答案 1 :(得分:0)

正如文档所说here,不得设置FLAG_TRANSLUCENT_STATUS。

  

要使此操作生效,窗口必须使用FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS绘制系统栏背景,并且不得设置FLAG_TRANSLUCENT_STATUS。

答案 2 :(得分:-2)

我在我的应用中这样做。

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

colorPrimary将设置状态栏颜色,但仅限于重新启动活动。

将其设置为透明的黑色,然后在代码中重新启动活动。您可以使用不同的colorPrimary值在样式中创建多个样式,然后在您的活动中执行此操作。

//onClick or condition statement here
setTheme(R.style.AppThemeLight);
setContentView(R.layout.activity_link_manager_light);
restart();


public void restart(){
Intent i = getBaseContext().getPackageManager()
            .getLaunchIntentForPackage( getBaseContext().getPackageName() );
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(i);
}

我认为您不需要重置内容视图,除非您也要切换布局,如果没有它,则不确定您是否可以尝试将其重置为相同的布局。

这绝对适用于我,但我从未尝试使用透明值。

您可以使用此方法重置整个应用主题并切换到具有硬编码的不同颜色的新布局,只需在布局上保留所有ID相同,在代码中您将获得正确的ID,只要你将setContentView引用到具有你在其中调用的ID的正确布局之后引用findViewByID。每个布局的ID都不同,但在调用findViewByID时,您将始终获得当前使用setContentView设置的布局ID。

您还可以将当前主题保存到sharedpref文件,并在调用setContentView之前使用开关在applaunch上设置主题(否则状态栏颜色不会更改)

考虑这段代码。这是接近onCreate的开始

String Theme;
    SaveData = getSharedPreferences(SaveFileName,0);
    Theme = SaveData.getString("Theme","Default Theme");
switch(Theme){
        case "Light Theme":
            setTheme(R.style.AppThemeLight);
            setContentView(R.layout.activity_link_manager_light);
            ListTextViewID = R.id.AppListTextViewLight;
            ListRowID = R.layout.app_list_item_light;
            break;

我在设置内容视图之前设置apptheme的方式是状态栏颜色更改的原因。