I'm writing a function in flutter like this
Expanded playButton({Color colorName, int buttonNumber, int soundNumber}) {
return Expanded(
child: FlatButton(
color: colorName,
onPressed: () {
final player = AudioCache();
player.play('note$soundNumber.wav');
},
child: Text(
'> PLAY $buttonNumber',
style: TextStyle(
fontSize: 35.0,
color: Colors.white,
),
),
),
);
}
Why the argument should be Color colorName instead of Colors colorName.
As we use color: Colors.teal for defining color.
I think the class Colors is a programmer friendly wrapper of the Color class.
As you can see in the source code of the Colors class:
class Colors {
// This class is not meant to be instatiated or extended; this constructor
// prevents instantiation and extension.
// ignore: unused_element
Colors._();
/// Completely invisible.
static const Color transparent = Color(0x00000000);
...
}
Here the 'Colors' class defines a variable transparent which we could easily use like
...
Container(
color: Colors.transparent,
)
...
So you always use a Color instance for a 'color' and therefore you have to define the variable as a Color instance, even if you use the Colors class wrapper.
Colors are predefined instances of the class Color.
It's like this...
Colors is to Color as Mercedes is to Car. Not every Car is a Mercedes. And not every Color object is a Colors object.
Btw, you can use Color to get the exact color you want, like...
const color = const Color(0xffb74093);
So it's much more versatile than Colors
Related
I have a picture on the page and below it a color pallette of 9 colors. When user clicks a color from the pallette, the image is to show that color on it. For that I want to use an array and I am changing a variable on tap
selectedIndex = 0 -> 8;
And I want to pass the color in ColorFilter
child: ColorFiltered(
colorFilter: ColorFilter.mode(
Color(filters[selectedIndex]),
BlendMode.color),
child: Image('')),
I am getting an error. String is not subtype of Color. How can I do this?
This is my filters array
"Colors.black",
"Colors.blue",
"Colors.yellow",
"Colors.orange",
"Colors.pink",
"Colors.green",
"Colors.white",
"Colors.indigo",
"Colors.grey",
"Colors.red",
];
It expects a Color type, not a String. Remove the quotes
[
Colors.black,
Colors.blue,
Colors.yellow,
etc..
];
Your filters array is a List<String>, but you are not providing any information about the expected color.
You have two ways to solve this problem:
1 - Convert your List<String> to a List<Color>
2 - Change the values of your List<String> to hexadecimal codes. (I would recommend you to change your List<String> to a List<int>)
Example:
In the first way, your filters array should looks something like:
final List<Color> filters = [
Colors.black,
Colors.blue,
Colors.yellow,
Colors.orange,
Colors.pink,
Colors.green,
Colors.white,
Colors.indigo,
Colors.grey,
Colors.red,
];
// ColorFilter
ColorFilter.mode(filters[selectedIndex], BlendMode.color);
If you want to keep your array as a List<Int> then you will need to provide the hexadecimal code of the expected color, like:
final List<Int> filters = [
0xFF000000,
0xFF0000FF,
0xFFFF0000,
];
// ColorFilter
ColorFilter.mode(Color(filters[selectedIndex]), BlendMode.color);
I want to create a bunch of const colored boxes. The following code works:
class MyBox extends SizedBox {
const MyBox(Color color, {Key? key}) // [*1] color parameter
: super(key: key,
width: 20,
height: 40,
child: const DecoratedBox(
decoration: BoxDecoration(
backgroundBlendMode: BlendMode.multiply,
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Colors.green, // [*2] all boxes are green
// color: color, // [*3] this is what I want
),
),
);
}
[...]
static const mbRed = MyBox(Colors.red);
static const mbYellow = MyBox(Colors.yellow);
static const mbBlue = MyBox(Colors.blue);
But notice that the color parameter at line [*1] is not actually used. If I replace line [*2] with line [*3], I am told this is an Invalid constant value. (Note that the Color class are immutable 32-bit values.)
Somehow there must be a way to pass a color parameter to a const constructor. What am I doing wrong?
And if this is the wrong way to go about it, what is a succinct means of creating a bunch of boxes, identical except for color? Thanks!
You can't. When you declare MyBox's constructor as const, that means that the constructor can be used to create a compile-time constant, not that it must be. Meanwhile, when that constructor itself invokes const DecoratedBox, you're stating that DecoratedBox is guaranteed to be a compile-time constant, but you cannot guarantee that. For example, MyBox could have been constructed with a Color determined at runtime.
Unfortunately Dart has no way to recursively say "try to invoke this constructor as const if possible". You will have to declare the MyBox constructor as a non-const constructor.
What is MaterialStateProperty in ButtonStyle?
ThemeData(
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
backgroundColor: , //?
),
),
),
The purpose of MaterialStateProperty is to make it possible to specify different styles for different states.
For example, if we want a button that's usually blue, but turns green when it's pressed, and enlarges its texts at the same time, we can use MaterialStateProperty.resolveWith to do exactly that.
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith((states) {
// If the button is pressed, return green, otherwise blue
if (states.contains(MaterialState.pressed)) {
return Colors.green;
}
return Colors.blue;
}),
textStyle: MaterialStateProperty.resolveWith((states) {
// If the button is pressed, return size 40, otherwise 20
if (states.contains(MaterialState.pressed)) {
return TextStyle(fontSize: 40);
}
return TextStyle(fontSize: 20);
}),
),
child: Text("Changing Button"),
onPressed: () {},
)
In addition to checking whether the button is being "pressed", MaterialStateProperty also supports: disabled, dragged, error, focused, hovered, pressed, scrolledUnder, selected. Note that it's possible to have multiple states at once. For example, a button can be both "disabled" & "hovered" at the same time. With MaterialStateProperty you can customize its appearance when that happens.
"Is there a clean way to resolve multiple states at once?"
The Flutter API documentation provides a nice clean pattern for resolving any of multiple states at one time. For example, if you want to respond the same way to all interactive states you could define a method like this:
Color getColor(Set<MaterialState> states) {
const Set<MaterialState> interactiveStates = <MaterialState>{
MaterialState.pressed, // Any states you want to affect here
MaterialState.hovered,
MaterialState.focused,
};
if (states.any(interactiveStates.contains)) {
// if any of the input states are found in our list
return Colors.blue;
}
return Colors.red; // default color
}
Then later in the button widget, simply assign that method as the resolver for the backgroundColor:
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(getColor),
),
onPressed: () {},
child: const Text('Changing Button'),
);
Play with the full example in Dart Pad.
"Okay, but I just want a red button."
Sure, it seems like you can use: MaterialStateProperty.all(Colors.red) to make it red in all cases. But that's probably NOT what you want. For example, when the button is disabled, do you still want it to be red?
See, "all" means "all". This is not good.
So what, are we stuck dealing with MaterialStateProperty and checking for disabled states all day?
Thankfully, no. There's a better way:
If you are using ElevatedButton, you can use ElevatedButton.styleFrom as a base style. Similarly, if you are using TextButton, you can use TextButton.styleFrom. From there, you can easily modify some of the styles.
Code:
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
child: Text("Red Button"),
onPressed: () {},
)
That's it, you just pass in a Color class. Super easy, no MaterialStateProperty involved. And it automatically handles edge cases for you.
I am assuming that you want to know how to assign a color to the backgroundColor parameter of the ButtonStyle widget. If that is the case then just type something like this:
backgroundColor: MaterialStateProperty.all(Colors.green),
OR
backgroundColor: MaterialStateProperty.all(Color(0xFF5D5F6E)),
Interface for classes that resolve to a value of type T based on a widget's interactive "state", which is defined as a set of MaterialStates.
Material state properties represent values that depend on a widget's material "state". The state is encoded as a set of MaterialState values, like MaterialState.focused, MaterialState.hovered, MaterialState.pressed. For example, the InkWell.overlayColor defines the color that fills the ink well when it's pressed (the "splash color"), focused, or hovered. The InkWell uses the overlay color's resolve method to compute the color for the ink well's current state.
ButtonStyle, which is used to configure the appearance of buttons like TextButton, ElevatedButton, and OutlinedButton, has many material state properties. The button widgets keep track of their current material state and resolve the button style's material state properties when their value is needed.
Code Example:
Widget build(BuildContext context) {
Color getColor(Set<MaterialState> states) {
const Set<MaterialState> interactiveStates = <MaterialState>{
MaterialState.pressed,
MaterialState.hovered,
MaterialState.focused,
};
if (states.any(interactiveStates.contains)) {
return Colors.blue;
}
return Colors.red;
}
return TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith(getColor),
),
onPressed: () {},
child: Text('TextButton'),
);
}
A simple way to use it:
MaterialStateProperty.all(Colors.green) // Whatever value you want
To get more you can check official documentation of Material state properties made by the flutter team.
It is used to calculate the value depending on the current interactive state of the button, which can be hovered, pressed, focused,... (full list here).
If you want a fixed value, you can use MaterialStateProperty.all(YOUR_VALUE), this value will be applied to all button states.
You can find more information here: https://api.flutter.dev/flutter/material/MaterialStateProperty-class.html
I add this package to my project.
This works but I want to change the color of a container, for example, depending on which theme is selected. How can I do that?
Create a helper method getThemeColor as follows:
Color getThemeColor({#required Color darkThemeColor,#required Color lightThemeColor}) {
return Theme.of(context).brightness == Brightness.dark ? darkThemeColor : lightThemeColor;
}
And then use this wherever you want to set your color:
Container(
color: getThemeColor(darkThemeColor: Colors.red, lightThemeColor: Colors.green),
),
I have declared a custom icon font in pubspec.yaml (icomoon.ttf).
Flutter's documentation says to invoke an icon, use...
const IconData(
this.codePoint, {
this.fontFamily,
});
I have an element with padding that should contain the icon.
new Padding(
padding: new EdgeInsets.only(top: 2.0),
how to invoke the glyph here? Need to be able to specify font size and
color too.
),
What is an example of how I should invoke "icomoon.ttf" glyph "e901" at size 25px with tint "myColor"?
You need to use that IconData in an Icon widget to display it, something like:
new Icon(const IconData(0x41, fontFamily: 'Roboto'), size: 48.0, color: Colors.red);
So in your case it would be something like:
new Icon(const IconData(0xe901, fontFamily: 'icomoon'), size: 25.0, color: myColor);
I wound up copying the Google icons definitions sheet into a "theme" file for my app ("lib/themes/my_icons.dart") So in this sheet, the icons are defined like so:
class MyIcons {
MyIcons._();
static const IconData superCheckMark = const IconData(0xe900, fontFamily: 'icomoon');
}
In the top of the component where I wanted to use the icon, I included the file. Then the icons were invoked like so:
new Icon(MyIcons.superCheckMark, size: 30.0, color: Colors.white,),
There is also a way to create a color theme file, for example "lib/theme/my_colors.dart". In this file the color "myBlue" is defined. So then this file can also be included at the top of any panel where a custom color palette will be invoked, and it is invoked for the icons like so:
new Icon(MyIcons.superCheckMark, size: 16.0, color: MyColors.colors.myBlue,),
Hope this helps someone else.