[Android] Support custom seed color scheme generation with Material 3
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 297
Description
## Description
Material 3's [Color System](https://m3.material.io/styles/color/system/overview) generates a complete, harmonized color scheme from a single **seed color** (typically the app's brand color). This seed color is used to algorithmically derive all 40+ M3 color tokens (primary, secondary, tertiary, surface variants, containers, on-colors, etc.), ensuring visual harmony and accessibility contrast ratios.
When `UseMaterial3` is enabled in .NET MAUI, developers should be able to specify a brand/seed color to generate a custom M3 color scheme that replaces the default baseline palette — giving their app a unique, branded Material 3 appearance while maintaining M3 design principles.
## Current Behavior
MAUI's M3 support uses the **baseline Material 3 theme** (`Theme.Material3.DayNight`) which provides a fixed purple-neutral palette:
- `colorPrimary`: `#6750A4`
- `colorSecondary`: `#625B71`
- `colorTertiary`: `#7D5260`
- `colorSurface`: `#FFFBFE`
Developers cannot customize the M3 color scheme through a single seed color. To customize, they would need to manually override 40+ individual color attributes, which is error-prone and breaks M3's harmonized color relationships.
## Expected Behavior
When a developer specifies a seed color:
- The M3 color algorithm generates all tonal palettes (primary, secondary, tertiary, neutral, neutral-variant) from the seed
- Both **light and dark** color schemes are generated automatically
- All M3 controls adopt the custom palette without per-control configuration
- Color contrast ratios meet WCAG accessibility standards (guaranteed by the M3 algorithm)
- Works on **all Android versions** (not limited to Android 12+ like dynamic colors)
## Proposed API
### Option 1: MSBuild Property
```xml
true
#1B6B4E
```
### Option 2: MauiAppBuilder API (Runtime)
```csharp
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp()
.UseMaterial3(options =>
{
// Generate full M3 scheme from brand green
options.SeedColor = Color.FromArgb("#1B6B4E");
});
```
### Option 3: Resource-based theme override
```xml
#1B6B4E
```
### Recommendation
**Option 2 (Builder API)** is preferred because:
- Runtime flexibility (can change based on user preference)
- Cross-platform API surface (even though implementation is Android-only initially)
- Familiar pattern for MAUI developers
## Implementation Details
### Available APIs
The `Xamarin.Google.Android.Material` binding (v1.14.0) provides:
```csharp
// Apply seed-color-based custom scheme
var options = new DynamicColorsOptions.Builder()
.SetContentBasedSeedColor(seedColorArgb) // int ARGB value
.Build();
DynamicColors.ApplyToActivityIfAvailable(activity, options);
```
Additional APIs for advanced scenarios:
- **`MaterialColorUtilitiesHelper`** — Low-level access to the HCT (Hue-Chroma-Tone) color space and tonal palette generation
- **`ColorRoles`** — Get accent/on-accent/container/on-container for any color
- **`HarmonizedColors`** — Shift custom colors to harmonize with the M3 scheme (useful for semantic colors like error/warning)
### Integration Points
1. **`MauiAppCompatActivity.OnCreate()`** — Apply `DynamicColorsOptions` with seed color before `SetTheme()`
2. **`MauiApplication.OnCreate()`** — For app-wide application via `ApplyToActivitiesIfAvailable()`
### Color Scheme Generation Flow
```
Seed Color (#1B6B4E)
↓ HCT color space conversion
Tonal Palettes (Primary, Secondary, Tertiary, Neutral, Neutral-Variant, Error)
↓ Tone mapping per M3 spec
Light Scheme:
colorPrimary = Primary[40]
colorOnPrimary = Primary[100]
colorPrimaryContainer = Primary[90]
colorSurface = Neutral[98]
... (40+ tokens)
Dark Scheme:
colorPrimary = Primary[80]
colorOnPrimary = Primary[20]
colorPrimaryContainer = Primary[30]
colorSurface = Neutral[6]
... (40+ tokens)
```
### Key Considerations
1. **Works on all Android versions**: Unlike dynamic wallpaper colors (Android 12+), seed-color schemes use the Material library's built-in color algorithm which runs on any API level
2. **Priority with dynamic colors**: If both seed color and dynamic colors are enabled, seed color should take precedence (app branding > wallpaper)
3. **Color harmonization**: Custom semantic colors (e.g., warning orange, info blue) can be harmonized with the seed-derived scheme using `HarmonizedColors.Applyxxx()` APIs
4. **Cross-platform future**: While implementation is Android-only today, the API surface should be designed so iOS/Windows support can be added later (e.g., generating platform-specific color resources from the seed)
5. **Runtime switching**: Consider supporting runtime seed color changes for apps that allow user theming (e.g., chat apps with per-conversation colors)
## Use Cases
1. **Brand identity**: App uses `#1B6B4E` (brand green) as seed → entire M3 UI is green-themed with harmonized surfaces, containers, and accent colors
2. **User preference**: Settings page lets user pick a theme color → app regenerates M3 scheme at runtime
3. **Content-based**: Music app uses album art dominant color as seed → UI adapts to current content
4. **Multi-tenant**: White-label app uses different seed per tenant/brand
## Visual Reference
| Seed Color | Primary | Surface | Container | Appearance |
|-----------|---------|---------|-----------|------------|
| `#6750A4` (baseline) | Purple | Off-white | Light purple | Default M3 |
| `#1B6B4E` (green) | Green | Off-white | Light green | Nature/eco apps |
| `#0061A4` (blue) | Blue | Off-white | Light blue | Corporate/tech |
| `#BA1A1A` (red) | Red | Off-white | Light red | Bold/media apps |
## References
- [Material 3 Color System Overview](https://m3.material.io/styles/color/system/overview)
- [Material Theme Builder](https://www.figma.com/community/plugin/1034969338659738588) — Interactive seed color tool
- [Material Color Utilities](https://github.com/nickytonline/material-color-utilities) — Open-source algorithm
- [Android Content-Based Dynamic Color](https://developer.android.com/develop/ui/views/theming/dynamic-colors#content-based-colors)
- [Flutter ColorScheme.fromSeed](https://api.flutter.dev/flutter/material/ColorScheme/ColorScheme.fromSeed.html) — Flutter's equivalent API for reference
Contributor guide
Research direction
Start by examining the MauiAppCompatActivity.OnCreate() and MauiApplication.OnCreate() integration points, along with the available DynamicColorsOptions and Material color utility APIs described in the issue. Resolve the builder, MSBuild, or resource-based API scope and how it interacts with dynamic colors and runtime changes. Done means a seed color generates light and dark M3 schemes across supported Android versions with appropriate tests and documentation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, csharp
- Domain
- mobile
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100