Skip to content

Commit a81a658

Browse files
Material Design Teamhunterstich
authored andcommitted
[M3][Color] Updated Color dev doc and added new section for Apply dynamic colors using DynamicColorsOptions and Resource Harmonization.
PiperOrigin-RevId: 431448591
1 parent f3d7ca4 commit a81a658

File tree

1 file changed

+114
-2
lines changed

1 file changed

+114
-2
lines changed

docs/theming/Color.md

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,26 @@ If the app is running on Android S+, dynamic colors will be applied to the
228228
activity. You can also apply a custom theme overlay or a precondition as
229229
depicted in the application section above.
230230

231+
##### Apply dynamic colors using `DynamicColorsOptions`
232+
233+
You also have the option to apply dynamic colors by passing in a
234+
`DynamicColorsOptions` object. When constructing `DynamicColorsOptions`, an
235+
Application or Activity is required as to where dynamic colors will be applied.
236+
You may optionally specify a customized theme overlay, likely inheriting from the
237+
`Material3` theme overlays above and/or a precondition, to have finer control over
238+
theme overlay deployment. You may also optionally specify a `OnAppliedCallback`
239+
function, which will be called after dynamic colors have been applied:
240+
241+
```
242+
DynamicColorsOptions dynamicColorOptions =
243+
new DynamicColorsOptions.Builder(application)
244+
.setThemeOverlay(themeOverlay)
245+
.setPrecondition(precondition)
246+
.setOnAppliedCallback(onAppliedCallback)
247+
.build()
248+
DynamicColors.applyIfAvailable(dynamicColorOptions);
249+
```
250+
231251
##### Apply dynamic colors to a specific fragment/view
232252

233253
Applying dynamic colors to a few of the views in an activity is more complex.
@@ -351,13 +371,13 @@ Color harmonization solves the problem of "How do we ensure any particular
351371
Reserved color (eg. those used for semantic or brand) looks good next to a
352372
user's dynamically-generated color?"
353373

374+
##### Harmonize a color with `colorPrimary`
375+
354376
To make it easier to implement color harmonization to ensure visual cohesion in
355377
any M3 themes with dynamic colors enabled, MDC-Android provides the following
356378
`MaterialColors` helper method in the `com.google.android.material.color`
357379
package:
358380

359-
##### Harmonize a color with `colorPrimary`
360-
361381
In your application class or activity/fragment/view, call:
362382

363383
```
@@ -372,6 +392,98 @@ towards `colorPrimary`.
372392
**Note:** If the input color `colorToHarmonize` is the same as `colorPrimary`,
373393
harmonization won't happen and `colorToHarmonize` will be returned.
374394

395+
##### Color Resources Harmonization
396+
397+
If you need to harmonize color resources at runtime and use the harmonized color
398+
resources in xml, call:
399+
400+
```
401+
HarmonizedColors.applyIfAvailable(harmonizedColorsOptions);
402+
```
403+
To construct a `HarmonizedColorsOptions`, a `Context` is required to specify
404+
where the harmonized color resources will be applied. You can optionally pass in
405+
an array of resource ids for the color resources you'd like to harmonize, a
406+
`HarmonizedColorAttributes` object and/or the color attribute to harmonize with:
407+
408+
```
409+
HarmonizedColorsOptions options =
410+
new HarmonizedColorsOptions.Builder(activity)
411+
.setColorResourcesIds(colorResources)
412+
.setColorAttributes(new HarmonizedColorAttributes.create(attributes))
413+
.setColorAttributeToHarmonizeWith(colorAttributeResId)
414+
.build();
415+
```
416+
417+
To return a new `Context` with color resources being harmonized, call:
418+
419+
```
420+
HarmonizedColors.wrapContextIfAvailable(harmonizedColorsOptions);
421+
```
422+
423+
##### `HarmonizedColorAttributes`
424+
425+
Static Factory Methods | Description
426+
------------------------------------------------------------------------ | -----------
427+
**HarmonizedColorAttributes.create(int[] attributes)** | Provides an int array of attributes for harmonization
428+
**HarmonizedColorAttributes.create(int[] attributes, int themeOverlay)** | Provides a themeOverlay, along with the int array of attributes from the theme overlay for harmonization.
429+
**HarmonizedColorAttributes.createMaterialDefaults()** | Provides a default implementation of `HarmonizedColorAttributes`, with Error colors being harmonized.
430+
431+
If the first static factory method is used, the color resource's id and value of
432+
the attribute will be resolved at runtime and the color resources will be
433+
harmonized. If you're concerned about accidentally overwriting color resources,
434+
the second method should be used. In this method, instead of the color resource
435+
that the attributes are pointing to being harmonized directly, resources value
436+
in the theme overlay will be replaced instead.
437+
438+
If you would like to harmonize additional color attributes along with the
439+
attributes in `HarmonizedColorAttributes.createMaterialDefaults()`,
440+
the `HarmonizedColorAttributes` would look like:
441+
442+
```
443+
HarmonizedColorAttributes.create(
444+
ArrayUtils.addAll(createMaterialDefaults().getAttributes(), myAppAttributes),
445+
R.style.ThemeOverlay_MyApp_HarmonizedColors);
446+
```
447+
448+
**Note:** For your custom theme overlay
449+
`R.style.ThemeOverlay_MyApp_HarmonizedColors`, we recommend you to extend from
450+
our theme overlay at `R.style.ThemeOverlay_Material3_HarmonizedColors`.
451+
452+
You can also use color resources harmonization separate from dynamic colors if
453+
needed, but the general use case for color resources harmonization is after
454+
dynamic colors have been applied. Here's an example use case to harmonize M3
455+
Error colors by default in the Dynamic Colors callback:
456+
457+
```
458+
DynamicColorsOptions dynamicColorOptions =
459+
new DynamicColorsOptions.Builder(activity)
460+
...
461+
.setOnAppliedCallback(
462+
activity ->
463+
HarmonizedColors.applyIfAvailable(
464+
HarmonizedColorsOptions.createMaterialDefaults(activity)))
465+
.build()
466+
DynamicColors.applyIfAvailable(dynamicColorOptions);
467+
```
468+
469+
For color ressources harmonization in a fragment/view, you would use the context
470+
generated from applying dynamic colors when constructing
471+
`HarmonizedColorsOptions` and call
472+
`wrapContextIfAvailable(harmonizedColorsOptions)` to apply resources
473+
harmonization:
474+
475+
```
476+
Context newContext = DynamicColors.wrapContextIfAvailable(getContext());
477+
478+
HarmonizedColorsOptions options =
479+
new HarmonizedColorsOptions.Builder(newContext)
480+
.setColorResources(colorResources)
481+
.build();
482+
HarmonizedColors.wrapContextIfAvailable(options);
483+
```
484+
485+
**Note:** This is only supported for API 30 and above.
486+
375487
## Color role mapping utilities
376488

377489
M3 schemes also include roles for much of the semantic meaning and other

0 commit comments

Comments
 (0)