MaterialColorUtilities.Maui
0.3.0
dotnet add package MaterialColorUtilities.Maui --version 0.3.0
NuGet\Install-Package MaterialColorUtilities.Maui -Version 0.3.0
<PackageReference Include="MaterialColorUtilities.Maui" Version="0.3.0" />
paket add MaterialColorUtilities.Maui --version 0.3.0
#r "nuget: MaterialColorUtilities.Maui, 0.3.0"
// Install MaterialColorUtilities.Maui as a Cake Addin #addin nuget:?package=MaterialColorUtilities.Maui&version=0.3.0 // Install MaterialColorUtilities.Maui as a Cake Tool #tool nuget:?package=MaterialColorUtilities.Maui&version=0.3.0
MaterialColorUtilities.Maui
A library for adding Material You colors to your .NET MAUI app
Features
- Dynamic theming on every platform (except iOS)
- Light/dark theme support
- Automatically storing and reapplying seed color/dark mode/style preferences
All of these can be turned on/off at any time.
Getting started
- Add a reference to the package. For instructions visit the NuGet page.
- Call the
UseMaterialColors
extension method inMauiProgram.cs
. This will add all the services required for theming to the service container.
+using MaterialColorUtilities.Maui;
namespace YourApp;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
MauiAppBuilder builder = MauiApp
.CreateBuilder()
+ .UseMaterialColors()
.UseMauiApp<App>();
return builder.Build();
}
}
You can specify the fallback seed as an argument to the extension method or use a lambda for more options:
.UseMaterialColors(options =>
{
options.FallbackSeed = 0xB000B5;
options.UseDynamicColor = false;
})
- Initialize MaterialColorService with a ResourceDictionary:
<details> <summary> If you use XAML click here </summary>
Copy these lines:
<Color x:Key="Primary" />
<Color x:Key="PrimaryContainer" />
<Color x:Key="Secondary" />
<Color x:Key="SecondaryContainer" />
<Color x:Key="Tertiary" />
<Color x:Key="TertiaryContainer" />
<Color x:Key="Surface" />
<Color x:Key="SurfaceVariant" />
<Color x:Key="Background" />
<Color x:Key="Error" />
<Color x:Key="ErrorContainer" />
<Color x:Key="OnPrimary" />
<Color x:Key="OnPrimaryContainer" />
<Color x:Key="OnSecondary" />
<Color x:Key="OnSecondaryContainer" />
<Color x:Key="OnTertiary" />
<Color x:Key="OnTertiaryContainer" />
<Color x:Key="OnSurface" />
<Color x:Key="OnSurfaceVariant" />
<Color x:Key="OnError" />
<Color x:Key="OnErrorContainer" />
<Color x:Key="OnBackground" />
<Color x:Key="Outline" />
<Color x:Key="Shadow" />
<Color x:Key="InverseSurface" />
<Color x:Key="InverseOnSurface" />
<Color x:Key="InversePrimary" />
<Color x:Key="Surface1" />
<Color x:Key="Surface2" />
<Color x:Key="Surface3" />
<Color x:Key="Surface4" />
<Color x:Key="Surface5" />
<SolidColorBrush x:Key="PrimaryBrush" />
<SolidColorBrush x:Key="PrimaryContainerBrush" />
<SolidColorBrush x:Key="SecondaryBrush" />
<SolidColorBrush x:Key="SecondaryContainerBrush" />
<SolidColorBrush x:Key="TertiaryBrush" />
<SolidColorBrush x:Key="TertiaryContainerBrush" />
<SolidColorBrush x:Key="SurfaceBrush" />
<SolidColorBrush x:Key="SurfaceVariantBrush" />
<SolidColorBrush x:Key="BackgroundBrush" />
<SolidColorBrush x:Key="ErrorBrush" />
<SolidColorBrush x:Key="ErrorContainerBrush" />
<SolidColorBrush x:Key="OnPrimaryBrush" />
<SolidColorBrush x:Key="OnPrimaryContainerBrush" />
<SolidColorBrush x:Key="OnSecondaryBrush" />
<SolidColorBrush x:Key="OnSecondaryContainerBrush" />
<SolidColorBrush x:Key="OnTertiaryBrush" />
<SolidColorBrush x:Key="OnTertiaryContainerBrush" />
<SolidColorBrush x:Key="OnSurfaceBrush" />
<SolidColorBrush x:Key="OnSurfaceVariantBrush" />
<SolidColorBrush x:Key="OnErrorBrush" />
<SolidColorBrush x:Key="OnErrorContainerBrush" />
<SolidColorBrush x:Key="OnBackgroundBrush" />
<SolidColorBrush x:Key="OutlineBrush" />
<SolidColorBrush x:Key="ShadowBrush" />
<SolidColorBrush x:Key="InverseSurfaceBrush" />
<SolidColorBrush x:Key="InverseOnSurfaceBrush" />
<SolidColorBrush x:Key="InversePrimaryBrush" />
<SolidColorBrush x:Key="Surface1Brush" />
<SolidColorBrush x:Key="Surface2Brush" />
<SolidColorBrush x:Key="Surface3Brush" />
<SolidColorBrush x:Key="Surface4Brush" />
<SolidColorBrush x:Key="Surface5Brush" />
and update App.xaml
like this:
<?xml version="1.0" encoding="UTF-8" ?>
<Application
x:Class="Playground.Maui.App"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:mcu="clr-namespace:MaterialColorUtilities.Maui;assembly=MaterialColorUtilities.Maui">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary>
+
+ </ResourceDictionary>
+ <mcu:MaterialColorResourceDictionary />
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Button">
<Setter Property="BackgroundColor" Value="{DynamicResource Primary}" />
<Setter Property="TextColor" Value="{DynamicResource OnPrimary}" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
</details>
<details> <summary>If you don't use XAML click here</summary>
Edit App.xaml.cs
like this:
+using MaterialColorUtilities.Maui;
public class App : Application
{
public App()
{
+ IMaterialColorService.Current.Initialize(this.Resources);
MainPage = new AppShell();
}
}
</details>
Usage
By default the colors are added as global resources. You can access them
- in XAML using DynamicResource:
<Button BackgroundColor="{DynamicResource Primary}" />
- in C# using
Element.SetDynamicResource()
:
Button button = new();
button.SetDynamicResource(Button.BackgroundProperty, "Primary");
The MaterialColorService
can be resolved from the MAUI dependency injection container. It contains the current core palette and schemes. It also has properties for updating the seed color and style.
using MaterialColorUtilites.Maui;
public class MyService
{
public MyService(MaterialColorService materialColorService)
{
Scheme<Color> scheme = materialColorService.SchemeMaui;
materialColorService.Seed = 0x123456;
materialColorService.Style = Style.Spritz;
}
}
Customization
Extending MaterialColorService allows you to use your custom colors or set different outputs for theming.
When you do this, register the new service at startup:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
MauiAppBuilder builder = MauiApp
.CreateBuilder()
+ .UseMaterialColors<MyMaterialColorService>()
.UseMauiApp<App>();
return builder.Build();
}
}
Custom colors
If you want to use custom colors, follow the instructions here on how to create you own palettes/schemes. Then specify them as generic type arguments:
public class MyMaterialColorService : MaterialColorService<MyCorePalette, MyScheme<uint>, MyScheme<Color>, MyLightSchemeMapper, MyDarkSchemeMapper>
{
public MyMaterialColorService(IOptions<MaterialColorOptions> options, IDynamicColorService dynamicColorService, IPreferences preferences)
: base(options, dynamicColorService, preferences)
{
}
}
Custom theming
By overriding the Apply method you can define things that should happen when colors change. For example invoking an event, setting native colors or if you are using .NET MAUI with Blazor, updating CSS.
public class MyMaterialColorService : MaterialColorService
{
private readonly WeakEventManager _weakEventManager = new();
public MyMaterialColorService(IOptions<MaterialColorOptions> options, IDynamicColorService dynamicColorService, IPreferences preferences) : base(options, dynamicColorService, preferences)
{
}
public event EventHandler SeedChanged
{
add => _weakEventManager.AddEventHandler(value);
remove => _weakEventManager.RemoveEventHandler(value);
}
protected override async void Apply()
{
base.Apply();
_weakEventManager.HandleEvent(null!, null!, nameof(SeedChanged));
#if ANDROID
Activity activity = await Platform.WaitForActivityAsync();
// Update status/navigation bar background color
Android.Graphics.Color androidColor = SchemeMaui.Surface2.ToPlatform();
activity.Window!.SetNavigationBarColor(androidColor);
activity.Window!.SetStatusBarColor(androidColor);
// Update status/navigation bar text/icon color
_ = new WindowInsetsControllerCompat(activity.Window, activity.Window.DecorView)
{
AppearanceLightStatusBars = !IsDark,
AppearanceLightNavigationBars = !IsDark
};
#endif
}
}
Implementation details
Light/dark mode handling works everywhere, but the dynamic theming source is different on all of the platforms:
- Android ≥12.0 (API 31): use system colors
- Android ≥8.1 (API 27): use WallpaperColors.Primary as seed color
- Android ≥7.0 (API 24): if the
StorageRead
permission has been granted, extract a color from the wallpaper, otherwise use fallback seed - Android ≥5.0 (API 21): use fallback seed
- iOS: no accent color, use fallback seed
- Mac: use accent color
- Windows: use accent color
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-android31.0 is compatible. net6.0-ios was computed. net6.0-ios16.1 is compatible. net6.0-maccatalyst was computed. net6.0-maccatalyst16.1 is compatible. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net6.0-windows10.0.19041 is compatible. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- MaterialColorUtilities (>= 0.3.0)
-
net6.0-android31.0
- MaterialColorUtilities (>= 0.3.0)
-
net6.0-ios16.1
- MaterialColorUtilities (>= 0.3.0)
- System.Runtime.InteropServices.NFloat.Internal (>= 6.0.1)
-
net6.0-maccatalyst16.1
- MaterialColorUtilities (>= 0.3.0)
- System.Runtime.InteropServices.NFloat.Internal (>= 6.0.1)
-
net6.0-windows10.0.19041
- MaterialColorUtilities (>= 0.3.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on MaterialColorUtilities.Maui:
Package | Downloads |
---|---|
RichMvvm.MAUI
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.