Skip to content

Changing Elevated Button Background Color in Flutter ​

Learn how to properly customize the background color of ElevatedButton widgets in Flutter using modern approaches and best practices.

Problem Statement ​

When working with Flutter's ElevatedButton, developers often encounter errors when trying to customize the button's background color. The common error occurs:

type '_MaterialStatePropertyAll' is not a subtype of type 'MaterialStateProperty<Color?>?

This typically happens when:

  1. Using the wrong approach to set button colors
  2. Passing incorrect parameter types to styling properties
  3. Not accounting for Flutter version changes in the API

Solution Overview ​

Flutter provides several methods to customize ElevatedButton colors. The two primary approaches are:

  1. Using ElevatedButton.styleFrom() - Simplified approach for basic customization
  2. Using ButtonStyle with MaterialStateProperty - More control over different button states

The simplest and most straightforward approach for most use cases:

dart
ElevatedButton(
  onPressed: () {},
  child: Text('Click Me'),
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,    // Background color
    foregroundColor: Colors.white,    // Text/icon color
    padding: EdgeInsets.all(16.0),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(8.0),
    ),
  ),
)

Method 2: Using ButtonStyle with MaterialStateProperty ​

For more advanced control over different button states (pressed, disabled, hovered, etc.):

dart
ElevatedButton(
  onPressed: () {},
  child: Text('Click Me'),
  style: ButtonStyle(
    backgroundColor: MaterialStateProperty.resolveWith<Color>(
      (Set<MaterialState> states) {
        if (states.contains(MaterialState.pressed)) {
          return Colors.blue.shade700; // Color when pressed
        } else if (states.contains(MaterialState.disabled)) {
          return Colors.grey; // Color when disabled
        }
        return Colors.blue; // Default color
      },
    ),
    foregroundColor: MaterialStateProperty.all(Colors.white),
  ),
)

Method 3: Dynamic Color Changes Based on State ​

For buttons that need to change color based on application state:

dart
bool _isActive = false;

ElevatedButton(
  onPressed: () {
    setState(() {
      _isActive = !_isActive;
    });
  },
  child: Text(_isActive ? 'Active' : 'Inactive'),
  style: ElevatedButton.styleFrom(
    backgroundColor: _isActive ? Colors.green : Colors.red,
    foregroundColor: Colors.white,
  ),
)

Common Pitfalls and Solutions ​

WARNING

Important Version Note: As of Flutter v3.1.0, the primary parameter in ElevatedButton.styleFrom() is deprecated. Use backgroundColor instead.

Incorrect approach (deprecated):

dart
// ❌ Don't use - deprecated after Flutter v3.1.0
ElevatedButton.styleFrom(primary: Colors.red)

Correct approach:

dart
// ✅ Use this instead
ElevatedButton.styleFrom(backgroundColor: Colors.red)

TIP

Always ensure your onPressed callback is properly defined. Buttons without an onPressed handler will appear disabled with gray colors regardless of your custom styling.

Complete Example: Xylophone App Buttons ​

Here's the corrected implementation for the xylophone application mentioned in the question:

dart
void playSound(int soundNumber) {
  final player = AudioCache();
  player.play('note$soundNumber.wav');
}

Expanded buildPlayButton({required Color color, required int soundNumber}) {
  return Expanded(
    child: ElevatedButton(
      onPressed: () {
        playSound(soundNumber);
      },
      style: ElevatedButton.styleFrom(
        backgroundColor: color,
        foregroundColor: Colors.white,
      ),
    ),
  );
}

// Usage in build method
Widget build(BuildContext context) {
  return Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[
      buildPlayButton(color: Colors.red, soundNumber: 1),
      buildPlayButton(color: Colors.orange, soundNumber: 2),
      buildPlayButton(color: Colors.yellow, soundNumber: 3),
      buildPlayButton(color: Colors.green, soundNumber: 4),
      buildPlayButton(color: Colors.blue, soundNumber: 5),
      buildPlayButton(color: Colors.indigo, soundNumber: 6),
      buildPlayButton(color: Colors.purple, soundNumber: 7),
    ],
  );
}

Additional Styling Options ​

Beyond background color, you can customize various aspects of ElevatedButton:

dart
ElevatedButton(
  onPressed: () {},
  child: Text('Styled Button'),
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.deepPurple,
    foregroundColor: Colors.white,
    elevation: 5,
    shadowColor: Colors.deepPurple.shade300,
    padding: EdgeInsets.symmetric(horizontal: 32, vertical: 16),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20),
    ),
    textStyle: TextStyle(
      fontSize: 18,
      fontWeight: FontWeight.bold,
    ),
  ),
)

Best Practices ​

  1. Use styleFrom() for simple customizations - It's more concise and readable
  2. Use ButtonStyle for state-dependent styling - When you need different colors for pressed, hovered, or disabled states
  3. Ensure contrast between background and text colors - For accessibility
  4. Test your buttons in different states - Especially disabled and pressed states
  5. Consider using theme colors - For consistency across your app
dart
// Using theme colors
ElevatedButton(
  onPressed: () {},
  child: Text('Themed Button'),
  style: ElevatedButton.styleFrom(
    backgroundColor: Theme.of(context).primaryColor,
    foregroundColor: Theme.of(context).colorScheme.onPrimary,
  ),
)

By following these approaches, you can effectively customize ElevatedButton colors in your Flutter applications while avoiding common pitfalls and ensuring your code remains maintainable across Flutter version updates.