37

I'm adding some Lollipop-only styling to an app.

I want to change color of header in overview screeen like Gmail here:
enter image description here

I have figured out I can do

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

    <item name="android:colorPrimary">@color/my_favorite_color</item>

</style>

to achieve it, but I would want to specify only the color for this case, just like I can do:

<item name="android:statusBarColor">@color/my_favorite_color<item>

Is there a specific attribute to set header's color?

Side question: can icon and title be also changed?

Jonik
  • 80,077
  • 70
  • 264
  • 372
MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
  • 3
    This is a duplicate of http://stackoverflow.com/questions/26899820/android-5-0-how-to-change-recent-apps-title-color but cannot be closed due to the bounty. – alanv Nov 24 '14 at 18:24
  • 2
    @alanv Neat, thanks Alan. I would argue about this being a duplicate, because the question you pointed out asks about changing title color, which seems not to be possible. Anyway the answer there perfectly answers my question. If you could answer, I will remove/transfer the bounty, allowing you to vote on closing this question. – MaciejGórski Nov 24 '14 at 18:48
  • @MaciejGórski Just an improvement(in my opinion): if you already know what color you need to supply, you can override `setTaskDescription(TaskDescription)` and pass relevant `TaskDescription` instance to the super call. To trace back from the source, look at [TaskViewHeader](http://androidxref.com/5.0.0_r2/xref/frameworks/base/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java). You should end at `Activity#onApplyThemeResource(....)` - this is where `setTaskDescription(TaskDescription)` is called from. – Vikram Nov 24 '14 at 19:01
  • @Vikram Thanks for pointing out `onApplyThemeResource`. From the code there we can clearly deduct background cannot be changed via app theme just like `statusBarColor` except for using `colorPrimary`. I'm not sure relying on `setTaskDescription` being called by the framework would be a good thing. Not nearly as bad as trying to call `ActivityManagerNative.getDefault().setTaskDescription` via reflection (which I just did to try to make a different size of icon, but it didn't work), but I think I prefer a more straighforward way of having compat helper class with `if (SDK_INT >= LOLLIPOP)`. – MaciejGórski Nov 25 '14 at 13:31
  • @MaciejGórski `...which I just did to try to make a different size of icon, but it didn't work...` That's probably because `TaskViewHeader` uses a `FixedSizeImageView` for application icon: check the xml layout here: [recents_task_view_header.xml](http://androidxref.com/5.0.0_r2/xref/frameworks/base/packages/SystemUI/res/layout/recents_task_view_header.xml). `I'm not sure relying on setTaskDescription being called by the framework would be a good thing.` _Why not?_ To me, it looks like `setTaskDescription()` is called _at least_ once: when the activity is created & its theme is set. – Vikram Nov 26 '14 at 19:39
  • 1
    @Vikram Yes, it's called exactly once before `onCreate`, but this behavior is not part of the lifecycle, is not documented and developers first looking at the code that does that won't be able to understand it without having comments in the overridden method body explaining how it works or digging deep into Android code. Calling it yourself in `onCreate` is a straightforward way to state the intent of the code and even if a developer didn't know this method existed, they could just look at javadoc. I like writing less code, but more than that I like being clear with the code I write. – MaciejGórski Nov 27 '14 at 09:57
  • @MaciejGórski `I like writing less code, but more than that I like being clear with the code I write.` :) I didn't think about that. I agree - an explicit call would be better. – Vikram Nov 28 '14 at 01:02
  • Is it possible to set a constant header color right in the manifest without adding a custom styles.xml to the project? – Viktor Sehr Sep 18 '18 at 13:36

1 Answers1

53

You can change this via ActivityManager.TaskDescription:

https://developer.android.com/reference/android/app/ActivityManager.TaskDescription.html

From an Activity context, call:

TaskDescription taskDescription = new TaskDescription(label, icon, colorPrimary);
((Activity)this).setTaskDescription(taskDescription);
Tim Malseed
  • 6,003
  • 6
  • 48
  • 66
  • 1
    To clarify more: * Label - text on the card header * Icon - left bitmap icon (usually an icon which looks good on the 'colorPrimary' color * colorPrimary - the card header color (usually same as the Toolbar color, but not necessarily) This solution worked for me, +1 :) – milosmns Apr 15 '15 at 15:24
  • 2
    Works nicely. Depending on `minSdkVersion`, may need to be wrapped in `if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ... }` – Jonik Apr 29 '15 at 13:57
  • 3
    Works nicely, once you figure out it won't work in `onCreate()`. Place this code in `onResume()` and you're good. – user149408 Nov 09 '15 at 19:33
  • 4
    Is there a possibility to do this for sdk 19? – cherry-wave May 30 '16 at 09:16
  • 1
    Awesome, in my case i had to put it within the onStart() method to get it work. – Dariush Malek Apr 14 '17 at 21:11