rozerro
rozerro

Reputation: 7166

What is MaterialStateProperty<Color>?

What is MaterialStateProperty in ButtonStyle?

ThemeData(
  textButtonTheme: TextButtonThemeData(
    style: ButtonStyle(
      backgroundColor: , //?
    ),
  ),
),

Upvotes: 89

Views: 113279

Answers (5)

Satria Suria
Satria Suria

Reputation: 1146

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: WidgetStateProperty.all(Colors.green),

OR

backgroundColor: WidgetStateProperty.all(Color(0xFF5D5F6E)),

Upvotes: 97

Anna Muzykina
Anna Muzykina

Reputation: 310

'MaterialStateProperty' is deprecated and shouldn't be used, use 'WidgetStateProperty' instead

See an issue https://github.com/flutter/flutter/issues/148218

enter image description here

Upvotes: 2

WSBT
WSBT

Reputation: 36333

The purpose of MaterialStateProperty is to make it possible to specify different styles for different states.

a button with 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.

"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?

a red button that's always red, even when disabled

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.

a red button that can be properly disabled

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.

Upvotes: 184

theiskaa
theiskaa

Reputation: 2443

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.

Upvotes: 36

Ali Hussein Al-Issa
Ali Hussein Al-Issa

Reputation: 685

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

Upvotes: 7

Related Questions