0 purchases
themed
themed #
The Themed package:
Lets you define a theme with const values, but change them dynamically anyway.
ChangeColors widget to change the brightness, saturation and hue of widgets or images.
Color extension methods: Colors.blue.decolorize() and more.
TextStyle extension methods: var myStyle = TextStyle(fontSize: 15) + Colors.blue and more.
Const values that you can change #
As we all know, using const variables is the easiest way to create and use themes:
static const myColor = Colors.white;
static const myStyle = TextStyle(fontSize: 16);
Container(
color: myColor,
child: const Text('Hi', style: myStyle)))
copied to clipboard
However, if you do it like that you can't later change the theme dynamically. By using the
Themed package you can:
static const myColor = ColorRef(Colors.white);
static const myStyle = TextStyleRef(TextStyle(fontSize: 16));
Container(
color: myColor,
child: const Text('Hello', style: myStyle)))
// Later, change the theme dynamically.
Themed.currentTheme = {
myColor: Colors.blue,
myStyle: TextStyle(fontSize: 20);
}
copied to clipboard
There is no need to use Theme.of(context) anymore:
// So old-fashioned.
Container(
color: Theme.of(context).primary,
child: Text('Hello', style: TextStyle(color: Theme.of(context).secondary)))
copied to clipboard
Also, since Theme.of needs the context and is not constant, you can't use it in constructors.
However, the Themed package has no such limitations:
// The const color is the default value of an optional parameter.
MyWidget({
this.color = myColor,
});
copied to clipboard
Setup #
Wrap your widget tree with the Themed widget, above the MaterialApp:
@override
Widget build(BuildContext context) {
return Themed(
child: MaterialApp(
...
copied to clipboard
Compatibility #
The Themed package is a competitor to writing Theme.of(context).xxx in your build methods, but
it’s NOT a competitor to Flutter’s native theme system and the Theme widget. It’s there to solve
a different problem, and it’s usually used together with the Theme widget. For example, if you
want to set a global default color for all buttons, you’ll use the Theme widget. You may use it
together with the Themed package however, meaning that Themed colors and styles may be used
inside a ThemeData widget:
static const myColor1 = ColorRef(Colors.red);
static const myColor2 = ColorRef(Colors.blue);
...
child: MaterialApp(
theme: ThemeData(
primaryColor: MyTheme.color2,
elevatedButtonTheme:
ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(primary: MyTheme.color2),
),
),
copied to clipboard
How to define a theme map #
Each theme should be a Map<ThemeRef, Object>, where the keys are your ColorRef
and TextStyleRef const values, and the values are the colors and styles you want to use on
that theme. For example:
Map<ThemeRef, Object> theme1 = {
MyTheme.color1: Colors.yellow,
MyTheme.color2: Colors.pink,
MyTheme.color3: Colors.purple,
MyTheme.mainStyle: const TextStyle(fontSize: 22, fontWeight: FontWeight.w900, color: MyTheme.color1),
};
copied to clipboard
At any point in your app you can just change the current theme by doing:
// Setting a theme:
Themed.currentTheme = theme1;
// Setting another theme:
Themed.currentTheme = theme2;
// Removing the current theme (and falling back to the default theme):
Themed.clearCurrentTheme();
// This would also remove the current theme:
Themed.currentTheme = null;
copied to clipboard
Organization #
You can also organize your theme in a class:
class MyTheme {
static const myColor = ColorRef(Colors.white);
static const myStyle = TextStyleRef(TextStyle(fontSize: 16, color: Colors.red));
}
Container(
color: MyTheme.myColor,
child: const Text('Hello', style: MyTheme.myStyle)))
copied to clipboard
Color transform #
Instead of changing the current theme you can create a color transformation. For example, this
will turn your theme into shades of grey:
static Color shadesOfGreyTransform(Color color) {
int average = (color.red + color.green + color.blue) ~/ 3;
return Color.fromARGB(color.alpha, average, average, average);
}
copied to clipboard
Note you can create your own function to process colors, but shadesOfGreyTransform is already
provided:
// Turn it on:
Themed.transformColor = ColorRef.shadesOfGreyTransform;
// Then, later, turn it off:
Themed.clearTransformColor();
copied to clipboard
Changing brightness, saturation and hue of widgets or images. #
Use the provided ChangeColors widget to change the brightness, saturation and hue of any widget,
including images. Example:
ChangeColors(
hue: 0.55,
brightness: 0.2,
saturation: 0.1,
child: Image.asset('myImage.png'),
);
copied to clipboard
To achieve a greyscale effect, you may also use the ChangeColors.greyscale constructor.
Note: This widget is based upon
this code (from
BananaNeil's), which is in turn based upon
this code (by Richard
Lalancette).
Color extension #
The lighter method makes the color lighter (more white). Example:
// 20% more white.
Colors.blue.lighter(0.2);
copied to clipboard
The darker method makes the color darker (more black). Example:
// 20% more black.
Colors.blue.darker(0.2);
copied to clipboard
The average method makes the current color more similar to the given color. Example:
// 50% blue and 50% red.
Colors.blue.average(Colors.red);
// 20% blue and 80% red.
Colors.blue.average(Colors.red, 0.8);
copied to clipboard
The decolorize method makes the current color more grey. Example:
// Grey, with luminance similar to the original blue.
Colors.blue.decolorize();
// Blue with 20% less color.
Colors.blue.decolorize(0.2);
copied to clipboard
The addOpacity method makes the current color more transparent than it already is, by the given
amount. This is different from the withOpacity method, as you can see below.
// 50% transparent blue.
Colors.blue.addOpacity(0.5);
// Also 50% transparent blue.
Colors.withOpacity(0.5);
// 75% transparent blue, because we add 50% and then more 50%.
Colors.blue.addOpacity(0.5).addOpacity(0.5);
// This is 50% transparent blue, because the opacity is replaced, not added.
Colors.withOpacity(0.5).withOpacity(0.5);
copied to clipboard
There are also two methods for advanced color representation conversion: The rgbaToArgb method
converts the RGBA color representation to ARGB. The abgrToArgb method converts the ABGR color
representation to ARGB.
TextStyle transform #
You can also create a style transformation. For example, this will make your fonts larger:
static TextStyle largerText(TextStyle textStyle) =>
textStyle.copyWith(fontSize: textStyle.fontSize! * 1.5);
// Turn it on:
Themed.transformTextStyle = largerText;
// Then, later, turn it off:
Themed.clearTransformTextStyle();
copied to clipboard
TextStyle extension #
With the provided extension, you can make your code more clean-code by creating new text styles by
adding colors and other values to a TextStyle. For example:
const myStyle = TextStyle(...);
// Using some style:
Text('Hello', style: myStyle);
// Making text black:
Text('Hello', style: myStyle + Colors.black);
// Changing some other stuff:
Text('Hello', style: myStyle + FontWeight.w900 + FontSize(20.0) + TextHeight(1.2));
copied to clipboard
Beware not to define the same constant #
Please remember Dart constants point to the same memory space. In this example, colorA, colorB
and colorC represent the same variable:
class MyTheme {
static const colorA = ColorRef(Colors.white);
static const colorB = ColorRef(Colors.white);
static const colorC = colorA;
}
copied to clipboard
If you later change the color of colorA, you are also automatically changing the color of colorB
and colorB.
If you want to create 3 independent colors, and be able to change them independently, you have to
create different constants. You can provide an id string, just to differentiate them. For example:
class MyTheme {
static const colorA = ColorRef(Colors.white, id:'A');
static const colorB = ColorRef(Colors.white, id:'B');
static const colorB = ColorRef(colorA, id:'C');
}
copied to clipboard
Avoid circular dependencies #
The following will lead to a StackOverflowError error:
Map<ThemeRef, Object> anotherTheme = {
MyTheme.color1: MyTheme.color2,
MyTheme.color2: MyTheme.color1,
};
copied to clipboard
You can have references which depend on other references, no problem. But both direct and indirect
circular references must be avoided.
Other ways to use it #
If you want, you may also define a default theme, and a current theme for your app:
@override
Widget build(BuildContext context) {
return Themed(
defaultTheme: { ... },
currentTheme: { ... },
child: MaterialApp(
...
copied to clipboard
The defaultTheme and currentTheme are both optional. They are simply theme maps, as explained
below.
When a color/style is used, it will first search it inside the currentTheme.
If it's not found there, it searches inside of defaultTheme.
If it's still not found there, it uses the default color/style which was defined in the constructor.
For example, here the default color is white: ColorRef(Colors.white).
Please note: If you define all your colors in the defaultTheme, then you don't need to provide
default values in the constructor. You can then use the fromId constructor:
class MyTheme {
static const color1 = ColorRef.fromId('c1');
static const color2 = ColorRef.fromId('c2');
static const color3 = ColorRef.fromId('c3');
static const mainStyle = TextStyleRef.fromId('mainStyle');
}
copied to clipboard
Saving and setting Themes by key #
You can save themes with keys, and then later use the keys to set the theme. The keys can be
anything (Strings, enums etc.):
// Save some themes using keys.
enum Keys {light, dark};
Themed.save(key: Keys.light, theme: { ... })
Themed.save(key: Keys.dark, theme: { ... })
// Then set the theme.
Themed.setThemeByKey(Keys.light);
copied to clipboard
It also works the other way around:
If you use the key first, and only save a theme with that key later:
// Set the theme with a key, even before saving the theme.
Themed.setThemeByKey(Keys.light);
// The theme will change as soon as you save a theme with that key.
Themed.save(key: Keys.light, theme: { ... })
copied to clipboard
Note: You can also use the methods saveAll to save many themes by key at the same time,
and clearSavedThemeByKey to remove saved themes.
Important: When I say "save" above, I mean it's saved in memory, not in the device disk.
Copyright #
This package is copyrighted and brought to you by
Parkside Technologies, a company which is simplifying global access to US stocks.
This package is published here with permission.
Please, see the license page for more information.
The Flutter packages I've authored:
async_redux
provider_for_redux
i18n_extension
align_positioned
network_to_file_image
image_pixels
matrix4_transform
back_button_interceptor
indexed_list_view
animated_size_and_fade
assorted_layout_widgets
weak_map
themed
bdd_framework
My Medium Articles:
Async Redux: Flutter’s non-boilerplate version of Redux
(versions:
Português)
i18n_extension
(versions:
Português)
Flutter: The Advanced Layout Rule Even Beginners Must Know
(versions: русский)
The New Way to create Themes in your Flutter App
My article in the official Flutter documentation:
Understanding constraints
Marcelo Glasberg:
github.com/marcglasberg
linkedin.com/in/marcglasberg/
twitter.com/glasbergmarcelo
stackoverflow.com/users/3411681/marcg
medium.com/@marcglasberg
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.