Reputation: 578
I created an app and It has multiple themes and it changes dynamically. I mean in run-time user can choose different themes. so that UI components color changes in runtime. I got stuck in a strange problem. Problem is status bar color is not changing according to theme. statusBar always stays in initial theme color.
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<item name="android:textColorPrimary">@color/primary_text</item>
<item name="android:icon">@color/icons</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
values-v21/themes.xml is as below
===================================
<resources>
<style name="AppThemeRed" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#F44336</item>
<item name="colorPrimaryDark">#D32F2F</item>
<item name="colorAccent">#FFCDD2</item>
<item name="android:textColorPrimary">#FFFFFF</item>
<item name="android:icon">@color/icons</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppThemeAmber" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#FFC107</item>
<item name="colorPrimaryDark">#FFA000</item>
<item name="colorAccent">#FFEB3B</item>
<item name="android:textColorPrimary">#FFFFFF</item>
<item name="android:icon">@color/icons</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppThemeBlue" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#3F51B5</item>
<item name="colorPrimaryDark">#303F9F</item>
<item name="colorAccent">#448AFF</item>
<item name="android:textColorPrimary">#FFFFFF</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppThemePurple" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#9C27B0</item>
<item name="colorPrimaryDark">#7B1FA2</item>
<item name="colorAccent">#7C4DFF</item>
<item name="android:textColorPrimary">#FFFFFF</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="AppThemeYellow" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#FFEB3B</item>
<item name="colorPrimaryDark">#FBC02D</item>
<item name="colorAccent">#CDDC39</item>
<item name="android:textColorPrimary">#FFFFFF</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
when user selects a theme from theme selection dialog i calling a function and setting theme for that activity, also recreating activity.
public static void onActivityCreateSetTheme(Activity activity)
{
switch (sTheme)
{
case 0:
activity.setTheme(R.style.AppThemeRed);
break;
case 1:
activity.setTheme(R.style.AppThemeAmber);
break;
default:
case 2:
activity.setTheme(R.style.AppTheme);
break;
case 3:
activity.setTheme(R.style.AppThemeBlue);
break;
case 4:
activity.setTheme(R.style.AppThemePurple);
break;
case 5:
activity.setTheme(R.style.AppThemeYellow);
break;
}
}
I am using NavigationView in drawer and drawer is coming below status bar no problem with that. But status bar is not picking up current theme's primaryDark-color. It always takes Default theme(startup theme) color only.
Upvotes: 3
Views: 1357
Reputation: 35264
Setting the theme via setTheme(int resId)
in the onCreate()
method won't have any effect on the StatusBar since it is not part of the Activity itself afaik.
So in order to achieve the desired effect you need to do it programatically. Here's a snippet which resolves the R.attr.colorPrimaryDark
and sets it for the StatusBar if the SDK-Level is above 21:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
setContentView(R.layout.activity_management);
// Further code
}
private void init(){
// Set the Theme
setTheme(R.style.MyAppTheme);
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
getWindow().setStatusBarColor(getAttributeColor(R.attr.colorPrimaryDark));
}
}
// Resolve the given attribute of the current theme
private int getAttributeColor(int resId) {
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(resId, typedValue, true);
int color = 0x000000;
if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT && typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
// resId is a color
color = typedValue.data;
} else {
// resId is not a color
}
return color;
}
This approach obviously overwrites the color which is set via android:statusBarColor
. So if you're using a NavigationDrawer and you want that the Drawer goes "under" the StatusBar you have to set the StatusBar color to transparent manually as soon as the Drawer is opened:
Example
actionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar,
R.string.open_drawer_accessibility_desc,
R.string.close_drawer_accessibility_desc) {
@SuppressLint("NewApi")
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(
getResources().getColor(android.R.color.transparent));
}
}
/** Called when a drawer has settled in a completely open state. */
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
/** Called when a drawer has settled in a completely closed state. */
@Override
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
};
}
Upvotes: 7