Search code examples
flutterbuttonthemedata

How to apply different style to ElevatedButton with or without icons


In my application I have many ElevatedButtons, which I style in the main theme. I need to style the ones with icon differently than the ones without icon.

Here is the code with only one property, which however applies to all ElevatedButtons, how can I select the ones with the icon and give them a different borderRadius?

@override
Widget build(BuildContext context) {
  return MaterialApp(
    theme: ThemeData(
      elevatedButtonTheme: ElevatedButtonThemeData(
        style: ElevatedButton.styleFrom(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10.0),
          ),
        ),
      ),
    ),
  );
}

Solution

  • To achieve this, I'd suggest creating a custom widget as a wrapper for the elevated button. Example:

    class CustomButton extends StatelessWidget {
      final Icon? icon;
      final VoidCallback? onPressed;
      final Widget child;
    
      const CustomButton({
        super.key,
        required this.child,
        this.icon,
        this.onPressed,
      });
    
      @override
      Widget build(BuildContext context) {
        final style = ButtonStyle(
          shape: MaterialStateProperty.all<RoundedRectangleBorder>(
            RoundedRectangleBorder(
              // Set the different border radius here
              borderRadius: BorderRadius.circular(icon != null ? 50.0 : 10.0),
            ),
          ),
        );
    
        return icon != null
            ? ElevatedButton.icon(
                onPressed: onPressed,
                icon: icon!,
                label: child,
                style: style,
              )
            : ElevatedButton(
                onPressed: onPressed,
                style: style,
                child: child,
              );
      }
    }
    

    The icon parameter is nullable (optional), if it's set, it should build a ElevatedButton.icon with its specified style. Otherwise, it builds a standard one with its style (which should be different from the ElevatedButton.icon's one).

    Output:

    Without icon:

    CustomButton(
        onPressed: () {},
        child: const Text('Elevated Button'),
    ),
    

    enter image description here

    With icon:

    CustomButton(
        icon: const Icon(Icons.add),
        onPressed: () {},
        child: const Text('Icon Elevated Button'),
    ),
    

    enter image description here


    Note that you could get rid of the style of the standard button (without icon) if you want to keep the style in the ThemeData of the main app widget. However, I'd not recommend it since there will be an explicit widget to handle the appearance of the elevated buttons.