8

Background

I'm trying to prepare dark theme for an app, and one of the requirements is to have a specific color for cards and dialogs : #ff3c454c

The problem

Whether I set it by force ( app:cardBackgroundColor="#3c454c") , by reference ( app:cardBackgroundColor="@color/...) or just in the theme - in all cases I don't get the color I've set. Instead I get the color of #525A61.

I've tested just a red color (#f00) just to be sure it affects the card, and it does, and for this color it indeed gets to be fine. But for the color I've set, it doesn't.

What I've tried

As I wrote, I tried multiple ways to set the color. In the beginning I wanted to use just the theme itself, so I've set it as such:

styles.xml

    <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        ...
        <item name="colorBackgroundFloating">@color/colorBackgroundFloating</item>
        <item name="colorSurface">@color/colorBackgroundFloating</item>
    </style>

res/values-night/colors.xml

    <color name="colorBackgroundFloating">#ff3c454c</color>

Later I tried to use the color directly and even set it as hard coded. Still got the incorrect color when it gets shown.

Seeing this could be a bug on the library itself, I've reported about this here (include a sample project, if you wish to check it out).

I've noticed the exact same issue occurs for BottomNavigationView and probably other similar cases.

The question

Why does it occur? Is there any workaround for this? Something that will fix it globally for all views that use these attributes ?

android developer
  • 114,585
  • 152
  • 739
  • 1,270

1 Answers1

13

What you are seeing is the elevation overlay that they introduced to make elevation more noticeable while in Dark Theme, where shadows are not so visible. You can read about it here : https://material.io/develop/android/theming/dark/ in the section "Elevation Overlays"

The simple solution if you don't want this behavior is to add this to your theme.

<item name="elevationOverlayEnabled">false</item>

And you can also adjust it to another color or even a more subtle version of the overlay by changing the alpha:

<item name="elevationOverlayColor">#80FFFFFF</item>

EDIT with more info from https://github.com/material-components/material-components-android/issues/1133

If you want to disable it for only one component or widget, you can define a style for it with a theme overlay and use it in a specific layout:

<style name="ThemeOverlay.MyApp.ElevationOverlayDisabled" parent="">
    <item name="elevationOverlayEnabled">false</item>
</style>

<style name="Widget.MyApp.CardView" parent="Widget.MaterialComponents.CardView">
    <item name="materialThemeOverlay">@style/ThemeOverlay.MyApp.ElevationOverlayDisabled</item>
</style>

And if you want to disable it for all cards in your app but keep it in other components you can set that style as the default style for material card views:

# Set in your app theme
<item name="materialCardViewStyle">@style/Widget.MyApp.CardView</item>
GSala
  • 946
  • 7
  • 15
  • And why would some colors change it, and some won't? And how can I set it so that the color as normal would be what I chose, together with this enabled? It doesn't make sense after all that I will have to disable it everywhere, or set a style for it on every possible to be disabled... Why set it on top of the color I choose? It modifies the color I chose this way. What's the purpose of it? I choose a color, and I expect to see this color. Why change its default state color that I chose? – android developer Mar 22 '20 at 19:50
  • Every component with elevation as far as I know will have the overlay. You can see the whole list in the link I posted. So all the colors applied to elevated components will be modified in dark theme. I'm sure to disable it in some components only, you could use a theme overlay in some component' style, but I don't know the specifics of this. – GSala Mar 22 '20 at 19:56
  • Why do you want to keep it enabled? If I may ask. From your line "I choose a color, and I expect to see this color" I understand you just want to disable it. It doesn't disable elevation, just the overlay. – GSala Mar 22 '20 at 19:58
  • If it makes sense to have it, let it stay, but let me choose the color and make it stay this way. As I wrote, if color should change, it should not be for the default state. Anyway, I've noticed that by adding this to the theme, it gets fixed. I still don't get why in some colors it changes the color (red for example) and in some it doesn't – android developer Mar 22 '20 at 20:00
  • What is the default "elevationOverlayColor" value? Does it also affect the foreground color and anything that's inside the card? – android developer Mar 22 '20 at 20:03
  • The default value is `?attr/colorOnSurface` so on dark theme, that would be white (0xFFFFFFFF). I think the red color might also get the overlay, but it might not be noticeable in the way the colors are merged, but I'm not sure. – GSala Mar 22 '20 at 20:06
  • Also, I think it doesn't effect the content of the card, just the background. – GSala Mar 22 '20 at 20:10
  • I see. So the default behavior is to make things become brighter, the more elevated they are, right? What if I disable it, and change elevation? Would it be noticeable ? Also, what is the default change of the color? How can I choose the color of a MaterialCardView to be seen as the default one, without disabling this attribute? Is there maybe a video of it by Google? I think I missed/forgot about it. – android developer Mar 23 '20 at 08:46
  • If you disable the attribute, the shadow of the card will still be there (more elevation, more shadow) even in dark theme. Obviously, in dark theme the shadows are not as noticeable, but they are still there. – GSala Mar 23 '20 at 11:17
  • You can see the default values of this overlay in a table and picture here https://material.io/design/color/dark-theme.html#properties – GSala Mar 23 '20 at 11:17
  • If you want to have only one specific CardView that ignores this attribute, while the rest of your UI uses it as default, you can declare a theme overlay that disables the attrbiute, and apply that theme only to your CardView – GSala Mar 23 '20 at 11:18
  • I see. Do you prefer this way of handling dark theme, or you do disable this attribute? Also, I can't see it mentioned about the default value on the link you've provided. Maybe you didn't understand me: I want to know the default "elevationOverlayColor" , and how it works exactly : Is it just adding to the color that I've provided? Meaning that the output color would be thge sum : colorSurface+elevationOverlayColor ? But hen how does the elevation gets into this ? I want to know how to reach the color that I was required, if it's even possible. Meaning app:cardBackgroundColor=? to get #3c454c – android developer Mar 23 '20 at 21:03
  • In my own side project, I just have the attribute enabled and let it overlay the colors. I think I tuned down how bright it was by making the `elevationOverlayColor` more subtle. In my work projects, I get a design with some specific colors, so I disable the attribute and set every surface to whatever the design spec says. – GSala Mar 24 '20 at 08:49
  • The default value for `elevationOverlayColor` is `?attr/colorOnSurface` which is by default `0xFFFFFFFF` (full white). The link I posted above has a table that shows how opaque this white layer will be. So at 1dp elevation, the overlay is white with 5% alpha. At 2 dp elevation, the overlay is white with 7% alpha. At 3dp it's 8% alpha, At 4dp it's 9% alpha and so on. – GSala Mar 24 '20 at 08:54
  • I would NOT try to get to the color you were required by trying to mix the right color with the overlay. Because that's a terrible solution, that will stop working if you change the elevation of the card one day, Or if Google decides to adjust the default values for the elevation overlays. – GSala Mar 24 '20 at 08:56
  • Seems the calculation is not linear or easy to guess how it works. Anyway thank you. Here, get +1 for all the effort. – android developer Mar 24 '20 at 09:39