Reputation: 476
I'd like to create a layout displaying a music album's tracks, with the text and background colors being taken from the album cover's color palette. I know how to retrieve the color palette, but I am unsure how to easily apply it programmatically to an entire layout, without manually finding each individual view and changing the colors appropriately. I have only found solutions where themes are changed before creating the views, but those themes are already predefined in the resources, not dynamically generated on the album cover.
Is there some way for me to write a layout in XML referencing colors like "color1" and "color2", and then at runtime assigning an actual value to these colors, such that I don't need to painstakingly modify every view programmatically myself?
Upvotes: 2
Views: 209
Reputation: 19524
I'm not sure it's possible to do that through XML normally, since you're referring to resource IDs and those resources are fixed at runtime. The Theme
class also links attributes to resources, so you can't just inject the values you want (as far as I know) into a Theme and then apply that to the Activity
. (I don't know a lot about the styling/theming system though so it's possible you can do some wild stuff with it!)
There's a couple of things you could look into though. If you're happy to use the new Material 3 system, that has dynamic colour baked into it, including theming parts of the app with colours derived from content like album art.
But from that outline, it looks like it pulls a single colour from the image, and derives a couple of complementary, neutral colours from it - so it's not pulling multiple colours from the image like the Palette
library does. The Material 3 stuff has a particular tone to it (limited colour variation, not too much contrast, consistent look) and if that works for you, great! But if you want a more vibrant palette, you might need to use Palette
instead (that link up there shows how you're meant to use it, the examples are basically "apply colour to each view/component in code")
The other thing you could try is using data binding, and instead of using resource IDs and attributes in your XML, you could reference properties on a ViewModel
. So you could create LiveData
s for things like primaryColour
, secondaryColour
etc, and bind to those when setting the colour attributes in your XML. And then by updating a value in the ViewModel
, any views bound to that property will see the change. And that binding is defined in the XML, you don't need to know which View
is using which colour in your code.
I've never actually used data binding, never mind for colour updates, so I'm not sure how well it would work or if you need to give things a kick to get them to refresh visually - I'd imagine it just works like setting a new value through code, but I'm not sure so I just want to be clear about that!
But if you want smooth colour transitions (e.g. switching albums fades the colours) then I'm not sure there's anything that does that out of the box - maybe the Material 3 stuff does it. You could probably do it with the ViewModel
approach though - when you set a new colour, kick off a coroutine that interpolates between the current value and the new one over 1 second or whatever, updating the LiveData
every tick.
Upvotes: 1