Home > Enterprise >  Flutter - elegant way to define buttons
Flutter - elegant way to define buttons

Time:12-31

I want to create a design system for my new app.

Standard elevated button

      child: ElevatedButton.icon(               
            icon: Icon(Icons.power_settings_new),
            onPressed: () => context.go('/login'),
            label: const Text('Log out'),
          ),

It's ok but in this scenario it should have a red color accent. This goal is easily achievable by use of foregroundColor property. By use of this technique there is no need to worry about icon's color, text's color, ripple effect color.

enter image description here

      child: ElevatedButton.icon(
            style: ElevatedButton.styleFrom(
              foregroundColor: Colors.red,
            ),
            icon: Icon(Icons.power_settings_new),
            onPressed: () => context.go('/login'),
            label: const Text('Log out'),
          ),

However I don't want to specify this color every time. I'd prefer to make something like this and I'd like to avoid writing anny wrappers for buttons.

      child: ElevatedButton.error( // Color accent is red
                    icon: Icon(Icons.power_settings_new),
                    onPressed: () => context.go('/login'),
                    label: const Text('Log out'),
                  ),

Question 1: Is it event possible?

Question 2: How icon, text and ripple effects know that they need use a foreground color to render themselves?

CodePudding user response:

I would look into Extensions (https://dart.dev/guides/language/extension-methods)

@override
Widget build(BuildContext context) {
  return ElevatedButton.icon(
    icon: const Icon(Icons.power_settings_new),
    label: const Text('Log out'),
    onPressed: () {},
  ).error();
}

extension ExtendedElevatedButton on ElevatedButton {
  ElevatedButton error() {
    return ElevatedButton(
      style: ElevatedButton.styleFrom(
        foregroundColor: Colors.red,
      ),
      onPressed: onPressed,
      child: child,
    );
  }
}

CodePudding user response:

Wrap a widget with Theme:

extension ThemeModifiers on Widget {
  Widget theme(ThemeData data) {
    return Theme(data: data, child: this);
  }
}

ElevatedButton.icon(
  icon: const Icon(Icons.power_settings_new),
  onPressed: () {},
  label: const Text('Log out'),
).theme(
  Theme.of(context).copyWith(
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
          foregroundColor: Colors.red,
      ),
    ),
  ),
)

Then go for a more specific style as needed:

extension ElevatedButtoneModifier on ElevatedButton {
  Widget error(BuildContext context) {
    return theme(
      Theme.of(context).copyWith(
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            foregroundColor: Colors.red,
          ),
        ),
      ),
    );
  }
}

ElevatedButton.icon(
  icon: const Icon(Icons.power_settings_new),
  onPressed: () {},
  label: const Text('Log out'),
).error(context)

  • Related