In Flutter, MaterialColor
is a class that defines a color palette to be used within a Material Design app. It creates a set of shades for a given primary color, which can be used in various components of the UI, such as buttons, text fields, and navigation bars. MaterialColor
objects can be created from a single color value and then generate shades based on a specified brightness factor. This allows for a consistent and harmonious color scheme throughout the app.
To create a MaterialColor from a Color, you can use the MaterialColor
class in Dart. The MaterialColor
constructor takes two arguments:
- The value of the color in RGB.
- A map of shades of the color with keys representing the shade level and values representing the
Color
of that shade.
Let’s say we want to create a MaterialColor
from the RGB color 176 / 255 / 38:

To use an implementation, let’s create a static method in a MaterialColorGenerator
class and call:
Color color = Color.fromARGB(255, 176, 255, 38);
MaterialColor material = MaterialColorGenerator.from(color);
MaterialColor from opacity only
Now there are different ways to define the shades. Most tutorials propose to change the opacity for each shade, which will result in such a code:
import 'package:flutter/material.dart';
class MaterialColorGenerator{
static MaterialColor from(Color color) {
return MaterialColor(color.value, <int, Color>{
50: color.withOpacity(0.1),
100: color.withOpacity(0.2),
200: color.withOpacity(0.3),
300: color.withOpacity(0.4),
400: color.withOpacity(0.5),
500: color.withOpacity(0.6),
600: color.withOpacity(0.7),
700: color.withOpacity(0.8),
800: color.withOpacity(0.9),
900: color.withOpacity(1.0),
});
}
}
Let’s take our color example and look at the result:

This is a good result for lighter colors, but results in very similar colors for the “darker” shades.
MaterialColor from color variations only
To create some real color variations, it’s better to adjust the color values itself by using:
import 'package:flutter/material.dart';
class MaterialColorGenerator{
static MaterialColor from(Color color) {
List strengths = <double>[.05];
final swatch = <int, Color>{};
final int r = color.red, g = color.green, b = color.blue;
for (int i = 1; i < 10; i++) {
strengths.add(0.1 * i);
}
for (var strength in strengths) {
final double ds = 0.5 - strength;
swatch[(strength * 1000).round()] = Color.fromRGBO(
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
1,
);
}
return MaterialColor(color.value, swatch);
}
}
Let’s take our color example and look at the result:

Now the result is good for “darker” shades (> 500), but there is less variation for the “lighter” colors.
A better MaterialColor from opacity and color variations
Let’s find a version that combines both of the advantages:
import 'dart:math';
import 'package:flutter/material.dart';
class MaterialColorGenerator{
static MaterialColor from(Color color) {
return MaterialColor(color.value, {
50: tintColor(color, 0.9),
100: tintColor(color, 0.8),
200: tintColor(color, 0.6),
300: tintColor(color, 0.4),
400: tintColor(color, 0.2),
500: color,
600: shadeColor(color, 0.1),
700: shadeColor(color, 0.2),
800: shadeColor(color, 0.3),
900: shadeColor(color, 0.4),
});
}
static int tintValue(int value, double factor) =>
max(0, min((value + ((255 - value) * factor)).round(), 255));
static Color tintColor(Color color, double factor) => Color.fromRGBO(
tintValue(color.red, factor),
tintValue(color.green, factor),
tintValue(color.blue, factor),
1);
static int shadeValue(int value, double factor) =>
max(0, min(value - (value * factor).round(), 255));
static Color shadeColor(Color color, double factor) => Color.fromRGBO(
shadeValue(color.red, factor),
shadeValue(color.green, factor),
shadeValue(color.blue, factor),
1);
}
Let’s take our color example and look at the result:

This is a much better result, which corelates with the color palettes of the Material Design. This implementation is also used by the material_color_generator package.
Photo by guy stevens on Unsplash
Leave a Reply