David Martin
David Martin

Reputation: 169

Flutter ThemeData: colorScheme is prioritized for button text color instead of ElevatedButtonTheme textStyle

I am currently trying to define the ThemeData for my material app and I need the ButtonStyle in ElevatedButtonThemeData to control the appearance of all the buttons in my app. So far, everything works fine but for some reason the "color" field for my buttons' TextStyle is overridden by the "onPrimary" field in my theme's ColorScheme.

Everything else works fine in textStyle, for instance, if I change the fontSize in TextStyle, then the font size is updated across my entire app but changing the color does nothing. Also, the backgroundColor works fine for the ButtonStyle.

I know that I can just wrap all of my buttons in a theme widget, but I want to avoid that if possible.

This is the color that ends up being used

      theme: ThemeData(
        brightness: Brightness.light,
        colorScheme: const ColorScheme(
          brightness: Brightness.light,
          primary: Colors.white,

          ///////////////////////////////////////
          onPrimary: Colors.red,
          //this is the color that is used
       ),

this is the color I want to use

elevatedButtonTheme: ElevatedButtonThemeData(
          //this themedata controls themedata for elevated buttons
          style: ButtonStyle(
            //for some reason the MarterialStateProperty must be called to explicitly define types for buttons
            //ie: "MaterialStateProperty.all<Color>(const Color(0xFF50D2C2))" just allows "const Color(0xFF50D2C2)" to be used
            backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF50D2C2)), //this is the color of the button background
            textStyle: MaterialStateProperty.all<TextStyle>(const TextStyle(
              //this determines the text style of the text displayed on buttons
              fontSize: 14,
              fontFamily: 'Lato',

              ///////////////////////////////////
              color: Colors.white,
              //this is the color I want

            ),),
            enableFeedback: true,
          ),
        ),

and this is my recreation of the issue using flutter's default demo to recreate it.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        brightness: Brightness.light,
        colorScheme: const ColorScheme(
          brightness: Brightness.light,
          primary: Colors.white,

          ///////////////////////////////////////
          onPrimary: Colors.red,
          //this is the color that is used

          secondary: Color(0xFFe8f3f2),
          onSecondary: Color(0xFF7a7a7a),
          error: Color(0xFFff3366),
          onError: Colors.white,
          background: Colors.white,
          onBackground: Color(0xFF7a7a7a),
          surface: Color(0xFF50D2C2),
          onSurface: Colors.white,
        ),

        elevatedButtonTheme: ElevatedButtonThemeData(
          //this themedata controls themedata for elevated buttons
          style: ButtonStyle(
            //for some reason the MarterialStateProperty must be called to explicitly define types for buttons
            //ie: "MaterialStateProperty.all<Color>(const Color(0xFF50D2C2))" just allows "const Color(0xFF50D2C2)" to be used
            backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF50D2C2)), //this is the color of the button background
            textStyle: MaterialStateProperty.all<TextStyle>(const TextStyle(
              //this determines the text style of the text displayed on buttons
              fontSize: 14,
              fontFamily: 'Lato',

              ///////////////////////////////////
              color: Colors.white,
              //this is the color I want

            ),),
            enableFeedback: true,
          ),
        ),
      ),
      home: const MyHomePage(title: 'Flutter Button Theme'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              child: const Text("This is a button"),
              onPressed: () { },
            )
          ],
        ),
      ),
    );
  }
}

Upvotes: 2

Views: 3203

Answers (2)

mikyll98
mikyll98

Reputation: 2283

MaterialStateProperty was deprecated after v3.19.0-0.3.pre.

As noted in the breaking changes — see Breaking Changes | Rename MaterialState to WidgetState) — it has been renamed to WidgetStateProperty and will be removed in future releases. Code using MaterialStateProperty should be migrated to use WidgetStateProperty instead.

Migration

The code provided in David Martin's answer would become:

elevatedButtonTheme: ElevatedButtonThemeData(
  //style: ElevatedButton.styleFrom(onPrimary: Colors.white)
  //this themedata controls the 
  style: ButtonStyle(
    //for some reason the MarterialStateProperty must be called to explicitly define types for buttons
    //ie: "MaterialStateProperty.all<Color>(const Color(0xFF50D2C2))" just allows "const Color(0xFF50D2C2)" to be used
    backgroundColor: WidgetStatePropertyAll(const Color(0xFF50D2C2)),
    foregroundColor: WidgetStatePropertyAll(Colors.white), //actual text color
    textStyle: WidgetStatePropertyAll(const TextStyle(
      //this determines the text style of the text displayed on buttons
      fontSize: 14,
      fontFamily: 'Lato',
      color: Colors.red, //color not used
    ),),
    enableFeedback: true,
    //minimumSize: ,
  ),
),

Upvotes: 0

David Martin
David Martin

Reputation: 169

Welp, I just spent 6 hours trying to find the answer to this issue and then figured it out 5 minutes after posting the question.

Button text color is controlled by the foregroundColor parameter, not textStyle.

elevatedButtonTheme: ElevatedButtonThemeData(
      //style: ElevatedButton.styleFrom(onPrimary: Colors.white)
      //this themedata controls the 
      style: ButtonStyle(
        //for some reason the MarterialStateProperty must be called to explicitly define types for buttons
        //ie: "MaterialStateProperty.all<Color>(const Color(0xFF50D2C2))" just allows "const Color(0xFF50D2C2)" to be used
        backgroundColor: MaterialStateProperty.all<Color>(const Color(0xFF50D2C2)),
        foregroundColor: MaterialStateProperty.all<Color>(Colors.white), //actual text color
        textStyle: MaterialStateProperty.all<TextStyle>(const TextStyle(
          //this determines the text style of the text displayed on buttons
          fontSize: 14,
          fontFamily: 'Lato',
          color: Colors.red, //color not used
        ),),
        enableFeedback: true,
        //minimumSize: ,
      ),
    ),

Upvotes: 14

Related Questions