Flutter - Using FilledButton Widget Examples

This tutorial shows you how to use the FilledButton widget in Flutter, including how to set custom style for the buttons.

Filled buttons are intended for buttons that should have the most visual impact after the FloatingActionButton. Therefore, it should be used for actions that complete a flow such as 'Submit', 'Save', or 'Confirm'. A filled button usually contains a label text. It can also have an icon. In addition, there is also a variant called filled tonal buttons. A filled tonal button is suitable for a button which needs more emphasis than an OutlinedButton, but less emphasis than a FilledButton. For example, it's suitable for the 'Next' button in an onboarding flow.

Flutter already provides a widget called FilledButton which makes it easier to create a filled button. Below are the usage examples which include how to customize the appearance of the buttons.

Using FilledButton

There are some constructors that you can use including factory and const constructors. Let's start with the main constructor.

  const FilledButton({
    Key? key,
    required VoidCallback? onPressed,
    VoidCallback? onLongPress,
    ValueChanged<bool>? onHover,
    ValueChanged<bool>? onFocusChange,
    ButtonStyle? style,
    FocusNode? focusNode,
    bool autofocus = false,
    Clip clipBehavior = Clip.none,
    MaterialStatesController? statesController,
    required Widget? child,
  })

As you can see, there are some named arguments. First, you have to pass a Widget as the child argument which will be set as the content of the button. The other required argument is onPressed, for which you have to pass a callback function to handle the events when the user presses the button. It's allowed to pass a null value as the onPressed argument which causes the button to be disabled.

Basic Usage

Below is the basic usage that only passes the required arguments.

  FilledButton(
    onPressed: () {
      print('pressed');
    },
    child: const Text('Woolha.com'),
  )

Output:

Flutter - FilledButton

Handle Long Press

In some cases, you may need to handle when the user performs a long press. It can be done by passing a function as the onLongPress argument.

  FilledButton(
    onLongPress: () {
      print('long pressed');
    },
    // other arguments
  )

Handle On Hover

You can also detect when a pointer enters or exits the button by passing a function as the onHover argument. The passed function must have a parameter whose type is bool. When the pointer enters the button area, it will be called with true as the argument value. The argument value will be false when the pointer exits the button area. It doesn't work on mobile platforms, but it works on the web platform.

  FilledButton(
    onHover: (bool isOnHover) {
      print('on hover: $isOnHover');
    },
    // other arguments
  )

Set Button Style

Using the above constructor, Flutter will create a standard filled button (non-tonal). If you do not define any style, the default style depends on the values from the ThemeData. For non-tonal buttons, it will use the primary color for the background and the onPrimary color for the foreground. For text style, it will be obtained from the textTheme.labelLarge. You can read the logic from the defaultStyleOf method of FilledButton class.

Set General ThemeData

There are several ways to change the style. As I have written above, the default style is obtained from the ThemeData. Therefore, modifying the ThemeData also affects the style of filled buttons. Keep in mind that if you customize the ThemeData, it may also affect other widgets, not only filled buttons. In other words, it changes the global style of the Flutter application. For non-tonal buttons, the related ThemeData properties are:

  • textTheme.labelLarge: text style
  • colorScheme.primary: background color
  • colorScheme.onPrimary: color for foreground and overlay
  • colorScheme.onSurface: color when the button is disabled.
  • colorScheme.shadow: shadow color

To do it, you have to pass a custom ThemeData as the theme argument. This should only be done if you want the customization to be applied to all kinds of widgets. For example, if you want to change the primary color used in your Flutter application.

  MaterialApp(
    theme: ThemeData.light().copyWith(
      textTheme: const TextTheme(
        labelLarge: TextStyle(
          fontStyle: FontStyle.italic,
        ),
      ),
      colorScheme: ThemeData.light().colorScheme.copyWith(
        primary: Colors.teal,
        onPrimary: Colors.white,
        // secondaryContainer: const Color.fromARGB(255, 217, 231, 203), // for tonal
        // onSecondaryContainer: const Color.fromARGB(255, 80, 80, 80), // for tonal
      ),
    ),
    // other arguments
  );

Output:

Flutter - FilledButton - ThemeData

Set FilledButtonThemeData

Another alternative is to set a global style for all filled buttons. When creating or copying a ThemeData, you can pass a ButtonStyle as the filledButtonTheme argument. The ButtonStyle can be constructed using FilledButton.styleFrom static method. With this way, the styles of other kinds of widgets are not affected. In addition, it allows more customization since you can also change the shape, size, and alignment in a more convenient way. The style defined as FilledButtonThemeData will override the general ThemeData style.

  MaterialApp(
    filledButtonTheme: FilledButtonThemeData(
      style: FilledButton.styleFrom(
          // ButtonStyle arguments
      ),
    ),
    // other arguments
  );

The ButtonStyle itself has a lot of properties to define a custom style. Common customizations such as how to change the color, text, and shape are going to be explained in the next section which explains how to change the individual button style, since it also uses the ButtonStyle class.

Set Individual ButtonStyle

If you want to apply a custom ButtonStyle to particular buttons, you can pass a ButtonStyle as the style argument to the constructor of FilledButton. You can utilize the FilledButton.styleFrom static method to build the . The style set on a specific button will override the style from FilledButtonThemeData or ThemeData.

  FilledButton(
    style: FilledButton.styleFrom(
      // ButtonStyle arguments
    ),
    // other arguments
  )

Below are common customizations that you might want to apply

Set Colors

To set the background color, you pass a Color value as the backgroundColor argument of the ButtonStyle. For the color of the text and the icon, you can set it using the foregroundColor argument. When the button is disabled, you can set different background and foreground colors using disabledBackgroundColor and disabledForegroundColor arguments respectively.

  FilledButton(
    style: FilledButton.styleFrom(
      backgroundColor: Colors.teal,
      foregroundColor: Colors.yellow,
      disabledBackgroundColor: Colors.grey,
      disabledForegroundColor: Colors.black,
    // other arguments
  )

Output when enabled:

Flutter - FilledButton - Colors

Output when disabled:

Flutter - FilledButton - Colors Disabled

Set Text Style

To change the text style, you can pass a TextStyle instance as the textStyle argument.

  FilledButton(
    style: FilledButton.styleFrom(
      textStyle: const TextStyle(
        fontStyle: FontStyle.italic,
      ),
    ),
    // other arguments
  )

Output:

Flutter - FilledButton - Text Style

Set Shape

By default, Flutter uses StadiumBorder for the shape, you can change it by passing an OutlinedBorder instance as the shape argument.

  FilledButton(
    style: FilledButton.styleFrom(
      shape: const ContinuousRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(20))
      ),
    ),
    // other arguments
  )

Output:

Flutter - FilledButton - Shape

Below is the list of named parameters you can pass to FilledButton.styleFrom static method.

  • Color? foregroundColor: Foreground color when enabled.
  • Color? backgroundColor: Background color when enabled.
  • Color? disabledForegroundColor: Foreground color when disabled.
  • Color? disabledBackgroundColor: Background color when disabled.
  • Color? shadowColor: The shadow color of the button.
  • Color? surfaceTintColor: The color of the surface tint.
  • double? elevation: The elevation of the button.
  • TextStyle? textStyle: The style for Text widget.
  • EdgeInsetsGeometry? padding: The padding between the button's boundary and its child.
  • Size? minimumSize: The minimum size of the button.
  • Size? fixedSize: The size of the button.
  • Size? maximumSize: The maximum size of the button.
  • BorderSide? side: The outline of the button.
  • OutlinedBorder? shape: The shape of the button.
  • MouseCursor? enabledMouseCursor: The mouse cursor when enabled.
  • MouseCursor? disabledMouseCursor: The mouse cursor when disabled.
  • VisualDensity? visualDensity: How compact is the button's layout.
  • MaterialTapTargetSize? tapTargetSize: yyy.
  • Duration? animationDuration: The minimum size of the area within which the button can be pressed.
  • bool? enableFeedback: Whether to enable acoustic and/or haptic feedback.
  • AlignmentGeometry? alignment: The alignment of the child.
  • InteractiveInkFeatureFactory? splashFactory: InkWell splash factory for showing ink splashes when tapped.

Using FilledButton.icon

It's also possible to create a filled button by passing the icon and label as separate arguments by using the following constructor.

  factory FilledButton.icon({
    Key? key,
    required VoidCallback? onPressed,
    VoidCallback? onLongPress,
    ValueChanged<bool>? onHover,
    ValueChanged<bool>? onFocusChange,
    ButtonStyle? style,
    FocusNode? focusNode,
    bool? autofocus,
    Clip? clipBehavior,
    MaterialStatesController? statesController,
    required Widget icon,
    required Widget label,
  })
  FilledButton.icon(
    onPressed: () {
      print('pressed');
    },
    icon: const Icon(Icons.web),
    label: const Text('Woolha.com'),
  )

Output:

Flutter - FilledButton - Icon

Using FilledButton.tonal

There is a named const constructor for creating filled tonal buttons. The list of arguments are the same as the main constructor. The difference is the default style. It uses colorScheme.secondaryContainer and colorScheme.onSecondaryContainer as the default background and foreground/overlay color respectively. However, if you define the colors with a ButtonStyle using either FilledButtonThemeData or set it directly to the button, the result can be the same as using the main constructor. In other words, the only difference between tonal and non-tonal is the default colors.

  const FilledButton.tonal({
    Key? key,
    required VoidCallback? onPressed,
    VoidCallback? onLongPress,
    ValueChanged<bool>? onHover,
    ValueChanged<bool>? onFocusChange,
    ButtonStyle? style,
    FocusNode? focusNode,
    bool autofocus = false,
    Clip clipBehavior = Clip.none,
    MaterialStatesController? statesController,
    required Widget? child,
  })
  FilledButton.tonal(
    onPressed: () {
      print('pressed');
    },
    child: const Text('Woolha.com'),
  )

Output:

Flutter - FilledButton - Tonal

Using FilledButton.tonalIcon

If you prefer to create a tonal button by passing the icon and label widgets, you can use the constructor below.

  factory FilledButton.tonalIcon({
    Key? key,
    required VoidCallback? onPressed,
    VoidCallback? onLongPress,
    ValueChanged<bool>? onHover,
    ValueChanged<bool>? onFocusChange,
    ButtonStyle? style,
    FocusNode? focusNode,
    bool? autofocus,
    Clip? clipBehavior,
    MaterialStatesController? statesController,
    required Widget icon,
    required Widget label,
  })
  FilledButton.tonalIcon(
    onPressed: () {
      print('pressed');
    },
    icon: const Icon(Icons.web),
    label: const Text('Woolha.com'),
  )

Output:

Flutter - FilledButton - Tonal Icon

FilledButton Parameters

Below is the list of parameters of the FilledButton or FilledButton.tonal constructor.

  • Key? key: The widget's key, used to control how a widget is replaced with another.
  • required VoidCallback? onPressed: Function to be called when the button is pressed.
  • VoidCallback? onLongPress: Function to be called when the button is long-pressed.
  • ValueChanged<bool>? onHover: Function to be called when a pointer enters or exits the button area.
  • ValueChanged<bool>? onFocusChange: Function to be called when the focus changes.
  • ButtonStyle? style: Style to be applied to the button.
  • FocusNode? focusNode: Focus node for the widget.
  • bool autofocus: Whether the widget will be selected as the initial focus when there is no other focused node in the scope.
  • MaterialStatesController? statesController: Represents the MaterialState of the widget.
  • Clip clipBehavior: How to clip the widget. Defaults to Clip.none.
  • Widget? child: The button content.

Below is the list of parameters of the FilledButton.icon or FilledButton.tonalIcon constructor.

  • Key? key: The widget's key, used to control how a widget is replaced with another.
  • required VoidCallback? onPressed: Function to be called when the button is pressed.
  • VoidCallback? onLongPress: Function to be called when the button is long-pressed.
  • ValueChanged<bool>? onHover: Function to be called when a pointer enters or exits the button area.
  • ValueChanged<bool>? onFocusChange: Function to be called when the focus changes.
  • ButtonStyle? style: Style to be applied to the button.
  • FocusNode? focusNode: Focus node for the widget.
  • bool autofocus: Whether the widget will be selected as the initial focus when there is no other focused node in the scope.
  • MaterialStatesController? statesController: Represents the MaterialState of the widget.
  • Clip clipBehavior: How to clip the widget. Defaults to Clip.none.
  • required Widget icon: Widget to be set as the icon.
  • required Widget label: Widget to be set as the label.

Summary

In Flutter, you can use the FilledButton widget for creating filled buttons. The constructors have some arguments you can use for customizations. There is also a variant called filled tonal button which is suitable for buttons whose priority is higher than an OutlinedButton but less than a FilledButton.

You can also read about:

  • ElevatedButton, a button whose elevation increases when being pressed by the user.
  • OutlinedButton, a button with an outlined border.
  • TextButton, a standard button without outlined border and elevation change.