A Comprehensive Guide to Flutter Buttons: Choosing the Right One for Your App

10 min read
Share this
Table Of Content

Are you a Flutter developer who’s ever felt puzzled by which button to use in your app’s UI? You’re not alone. Many developers struggle to pick the right button type, often resorting to unnecessary customizations. But fear not! This guide is here to demystify Flutter buttons, helping you make informed choices for your app’s design needs.

TextButton:

The TextButton is your basic, no-frills button. It’s perfect for simple actions like navigating pages or confirming choices. Avoid adding unnecessary customizations to it. Let it blend seamlessly into your UI, or customize it with a style or theme if needed.

Basic TextButton with onPressed function enabled

basic-textbutton-with-onpressed-function-enabled

Copy
TextButton(
  // onPressed function that gets triggered when button is pressed
  onPressed: () {
    // Add your onPressed code here!
  },
  child: const Text(
    'This is a TextButton Demo - Enabled',
  ), // Text displayed on the button
),

Disabled TextButton with onPressed function set to null

disabled-textbutton-with-onpressed-function-set-to-null

Copy
TextButton(
  // Button is disabled
  // as onPressed function is null
  onPressed: null,
  child: Text(
    'This is a TextButton Demo - Disabled',
  ),
),

TextButton with icon and onPressed function enabled

textbutton-with-icon-and-onpressed-function-enabled

Copy
TextButton.icon(
  // onPressed function that gets
  //triggered when button is pressed
  onPressed: () {
    // Add your onPressed code here!
  },
  icon: const Icon(
    Icons.access_alarm,
  ), // Icon displayed before the text
  label: const Text(
    'This is a TextButton Demo - TextButton.icon #1',
  ), // Text displayed on the button
),

TextButton with custom styling and onPressed function enabled

textbutton-with-custom-styling-and-onpressed-function-enabled

Copy
TextButton.icon(
  style: TextButton.styleFrom(
    foregroundColor: Colors.white, // Text color
    backgroundColor: Colors.green, // Background color
  ),
  onPressed: () {}, // onPressed function that gets triggered when button is pressed
  icon: const Icon(
    Icons.access_alarm,
  ), // Icon displayed before the text
  label: const Text(
    'This is a TextButton Demo - TextButton.icon #2',
  ), // Text displayed on the button
),

TextButton with custom shape and onPressed function enabled

textbutton-with-custom-shape-and-onpressed-function-enabled

Copy
TextButton(
  style: TextButton.styleFrom(
    shape: RoundedRectangleBorder(
      borderRadius: const BorderRadius.all(
        Radius.circular(
          20,
        ),
      ), // Border radius of the button
      side: BorderSide(
        color: Colors.lightBlue, // Border color
        width: 3, // Border width
      ),
    ),
  ),
  onPressed: () {}, // onPressed function that gets triggered when button is pressed
  child: const Text(
    'This is a TextButton Demo - TextButton #3',
  ), // Text displayed on the button
),

TextButton with custom overlay color and onPressed function enabled

textbutton-with-custom-overlay-color-and-onpressed-function-enabled

Copy
TextButton(
  style: TextButton.styleFrom(
    overlayColor: Colors.amber, // Color when button is pressed
  ),
  onPressed: () {}, // onPressed function that gets triggered when button is pressed
  child: const Text(
    'This is a TextButton Demo - TextButton #4',
  ), // Text displayed on the button
),

TextButton with custom foreground using ShaderMask and onPressed function enabled

textbutton-with-custom-foreground-using-shadermask-and-onpressed-function-enabled

Copy
TextButton(
  style: TextButton.styleFrom(
    foregroundBuilder: (context, states, child) {
      return ShaderMask(
        shaderCallback: (Rect bounds) {
          return LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [
              Colors.red,
              Colors.green,
            ],
          ).createShader(bounds);
        },
        blendMode: BlendMode.srcATop,
        child: child,
      );
    },
  ),
  onPressed: () {}, // onPressed function that gets triggered when button is pressed
  child: const Text(
    'This is a TextButton Demo - TextButton #5',
  ), // Text displayed on the button
),

TextButton with custom foreground using DecoratedBox and onPressed function enabled

textbutton-with-custom-background-and-onpressed-function-enabled

Copy
TextButton(
  style: TextButton.styleFrom(
    foregroundBuilder: (context, states, child) {
      return DecoratedBox(
        decoration: BoxDecoration(
          border: states.contains(MaterialState.hovered)
              ? Border(
                  bottom: BorderSide(
                    color: Colors.lightBlue,
                  ),
                )
              : const Border(), // Border displayed when button is hovered
        ),
        child: child,
      );
    },
  ),
  onPressed: () {}, // onPressed function that gets triggered when button is pressed
  child: const Text(
    'This is a TextButton Demo - TextButton #6',
  ), // Text displayed on the button
),

TextButton with custom background and onPressed function enabled

textbutton-with-custom-background-and-onpressed-function-enabled

Copy
TextButton(
  onPressed: () {}, // onPressed function that gets triggered when button is pressed
  style: TextButton.styleFrom(
    overlayColor: Colors.orange.withOpacity(
      1.0,
    ), // Color when button is pressed
    backgroundBuilder: (context, states, child) {
      return AnimatedContainer(
        duration: const Duration(
          milliseconds: 500,
        ), // Duration of the animation
        decoration: (states.contains(MaterialState.pressed))
            ? BoxDecoration(
                gradient: LinearGradient(
                  colors: [
                    Colors.orange.withOpacity(
                      1.0,
                    ),
                    Colors.orange.withOpacity(
                      1.0,
                    ),
                  ],
                ), // Gradient when button is pressed
              )
            : BoxDecoration(
                gradient: LinearGradient(
                  colors: switch (
                      states.contains(MaterialState.hovered)) {
                    true => [
                        Colors.blue.withOpacity(
                          1.0,
                        ),
                        Colors.orange.withOpacity(
                          1.0,
                        )
                      ],
                    false => [
                        Colors.orange.withOpacity(
                          1.0,
                        ),
                        Colors.blue.withOpacity(
                          1.0,
                        ),
                      ],
                  },
                ), // Gradient when button is not pressed
              ),
        child: child,
      );
    },
  ).copyWith(
    side: MaterialStateProperty.resolveWith<BorderSide?>((states) {
      if (states.contains(MaterialState.hovered)) {
        return BorderSide(
          width: 3,
          color: Colors.yellow.withOpacity(
            1.0,
          ), // Border color when button is hovered
        );
      }
      return null; // Border color when button is not hovered
    }),
  ),
  child: const Text(
    'TextButton #7',
    style: TextStyle(
      color: Colors.white,
    ),
  ), // Text displayed on the button
),

FilledButton:

Consider FilledButton as a TextButton with a bit more flair. It’s great for important actions that demand attention, like saving or confirming. While it offers tonal variations, remember, it’s essentially a styled TextButton.

A filled button with a solid background color

a-filled-button-with-a-solid-background-color

Copy
FilledButton(
  onPressed: () {
    // Define the action that should be taken when the button is pressed.
    // Currently, this is an empty function.
  },
  child: const Text(
    "This is a filled button - Mihir Pipermitwala",
  ),
),

A tonal filled button with background color

a-tonal-filled-button-with-a-softer-less-prominent-background-color

Copy
FilledButton.tonal(
  onPressed: () {
    // Define the action that should be taken when the button is pressed.
    // Currently, this is an empty function.
  },
  child: const Text(
    "This is a filled button (tonal)",
  ),
)

ElevatedButton:

ElevatedButton adds depth to your UI with its elevation and native Android-like appearance. Use it when you want your button to stand out or convey hierarchy. But avoid using it in popups or dialogues where default animations might clash.

A Disabled ElevatedButton with custom text style

an-elevatedbutton

Copy
ElevatedButton(
  onPressed: null,
  child: const Text(
    'Disabled',
  ),
),
ElevatedButton(
  onPressed: () {
    // Add your onPressed code here!
  },
  child: const Text(
    'Enabled',
  ),
),

OutlinedButton:

If you need a button with a subtle outline, OutlinedButton is your friend. It’s ideal for medium-emphasis actions. Its clean design ensures it doesn’t overpower your UI elements.

OutlinedButton with a custom onPressed callback

outlinedbutton-with-a-custom-onpressed-callback

Copy
OutlinedButton(
  onPressed: () {
    debugPrint(
      'Received click',
    );
  },
  child: const Text(
    'Click Me',
  ),
),

IconButton:

Need a button with just an icon? IconButton is the way to go. It offers click animations and various button styles, making it versatile for different UI needs.

Basic IconButton with an icon and onPressed function

basic-icon-button-with-an-icon-and-onpressed-function

Copy
IconButton(
  icon: const Icon(Icons.filter_drama),
  onPressed: () {
    // Add your onPressed code here!
  },
),

Filled IconButton with an icon and onPressed function

filled-icon-button-with-an-icon-and-onpressed-function

Copy
IconButton.filled(
  onPressed: () {
    // Add your onPressed code here!
  },
  icon: const Icon(
    Icons.filter_drama,
  ),
),

Filled tonal IconButton with an icon and onPressed function

filled-tonal-icon-button-with-an-icon-and-onpressed-function

Copy
IconButton.filledTonal(
  onPressed: () {
    // Add your onPressed code here!
  },
  icon: const Icon(
    Icons.filter_drama,
  ),
),

Outlined IconButton with an icon and onPressed function

outlined-icon-button-with-an-icon-and-onpressed-function

Copy
IconButton.outlined(
  onPressed: () {
    // Add your onPressed code here!
  },
  icon: const Icon(
    Icons.filter_drama,
  ),
),

FloatingActionButton:

The FloatingActionButton (FAB) widget is a circular button that floats above the content in a Flutter application. It is typically used for a primary action in an application.

Small FloatingActionButton with an add icon

small-floating-action-button-with-an-add-icon

Copy
FloatingActionButton.small(
  onPressed: () {
    // Add your onPressed code here!
  },
  child: const Icon(Icons.add),
),

Default size FloatingActionButton with an add icon

default-size-floating-action-button-with-an-add-icon

Copy
FloatingActionButton(
  onPressed: () {
    // Add your onPressed code here!
  },
  child: const Icon(Icons.add),
),

Large FloatingActionButton with an add icon

large-floating-action-button-with-an-add-icon

Copy
FloatingActionButton.large(
  onPressed: () {
    // Add your onPressed code here!
  },
  child: const Icon(Icons.add),
),

Extended FloatingActionButton with a label and an add icon

extended-floating-action-button-with-a-label-and-an-add-icon

Copy
FloatingActionButton.extended(
  onPressed: () {
    // Add your onPressed code here!
  },
  label: const Text('Add'),
  icon: const Icon(Icons.add),
),

CupertinoButton:

CupertinoButton brings an iOS-native button design to your Flutter app. Use it for a seamless iOS experience, complete with default iOS animations and padding.

A disabled Cupertino button with a standard transparent background

a-disabled-cupertino-button-with-a-standard-transparent-background

Copy
const CupertinoButton(
  onPressed: null,
  child: Text('Disabled'),
),

A disabled filled Cupertino button with a solid background color

a-disabled-filled-cupertino-button-with-a-solid-background-color

Copy
const CupertinoButton.filled(
  onPressed: null,
  child: Text('Disabled'),
),

An enabled Cupertino button with a standard transparent background

an-enabled-cupertino-button-with-a-standard-transparent-background

Copy
CupertinoButton(
  onPressed: () {
    // Define the action that should be taken when the button is pressed.
  },
  child: const Text('Enabled'),
),

An enabled filled Cupertino button with a solid background color

an-enabled-filled-cupertino-button-with-a-solid-background-color

Copy
CupertinoButton.filled(
  onPressed: () {
    // Define the action that should be taken when the button is pressed.
  },
  child: const Text('Enabled'),
),

Summary

Each Flutter button serves a specific purpose in your UI arsenal. Choose wisely based on your app’s needs, and remember, simplicity is often key. Have questions or suggestions? Drop them in the comments below. And if you found this guide helpful, don’t forget to show some love by hitting that clap button!

Related Blogs
Adjusting MinSdkVersion in Flutter for Android: 2 Simple Approaches [2023]

Adjusting MinSdkVersion in Flutter for Android: 2 Simple Approaches [2023]

Enhance your Flutter app's compatibility by tweaking the Android minSdkVersion. This comprehensive guide covers easy techniques for projects pre and post Flutter 2.8, guaranteeing optimal functionality.

AndroidFlutterFlutter DevelopmentMin Sdk Version

July 20, 2023

Unlocking Flutter's Potential: Best Practices for Writing Clean Code

Unlocking Flutter's Potential: Best Practices for Writing Clean Code

Unlock Flutter's potential with clean code! Learn best practices for writing maintainable Dart code in Flutter. Explore examples and essential principles for code quality.

Clean CodeCode Best PracticesCode MaintainabilityCode OrganizationCode Readability

June 02, 2023

All about SOLID Principles in Flutter: Examples and Tips

All about SOLID Principles in Flutter: Examples and Tips

Check out this guide on SOLID principles in Flutter by Mihir Pipermitwala, a software engineer from Surat. Learn with real-world examples!

DartFlutterSolid Principles

April 11, 2023

Top 9 Local Databases for Flutter in 2023: A Comprehensive Comparison

Top 9 Local Databases for Flutter in 2023: A Comprehensive Comparison

Looking for the best local database for your Flutter app? Check out our comprehensive comparison of the top 9 local databases for Flutter in 2023.

CodingFlutterFlutter Local DatabasesLearn To CodeNosql

April 06, 2023

Related Tutorials
A Comprehensive Guide to Flutter Buttons: Choosing the Right One for Your App

A Comprehensive Guide to Flutter Buttons: Choosing the Right One for Your App

A quick guide for you to understand and choose which Button widget suits your needs

FlutterFlutter ButtonFlutter DevelopmentText Button

April 17, 2024

How to Show Automatic Internet Connection Offline Message in Flutter

How to Show Automatic Internet Connection Offline Message in Flutter

You have to use the 'Connectivity Flutter Package' to achieve this feature on your App. This package helps to know whether your device is online or offline.

Connectivity PlusDependenciesFlutterFlutter DevelopmentFlutter Packages

April 09, 2024

Mastering TabBar and TabBarView Implementation in Flutter: A Comprehensive Guide for 2023

Mastering TabBar and TabBarView Implementation in Flutter: A Comprehensive Guide for 2023

Discover the art of implementing TabBar and TabBarView widgets in Flutter with our comprehensive guide for 2023. Learn step by step how to create captivating user interfaces, customize tab indicators, enable scrollable tabs, change tabs programmatically, and more. Elevate your Flutter app's navigation and user experience with expert insights and practical examples.

CodingDefault Tab ControllerFlutterLearn To CodeTab Controller

July 26, 2023

Enhancing File Manipulation in Flutter: Best Practices and Examples

Enhancing File Manipulation in Flutter: Best Practices and Examples

Master Flutter file manipulation like a pro. Our comprehensive blog provides insights on permission management, directory handling, and practical read-write scenarios. Elevate your app's file management.

CodingFlutterFlutter DevelopmentFlutter File OperationFlutter Path Provider

June 30, 2023

Related Recommended Services
Visual Studio Code for the Web

Visual Studio Code for the Web

Build with Visual Studio Code, anywhere, anytime, in your browser.

idevisual-studiovisual-studio-codevscodeweb
Renovate | Automated Dependency Updates

Renovate | Automated Dependency Updates

Renovate Bot keeps source code dependencies up-to-date using automated Pull Requests.

automated-dependency-updatesbundlercomposergithubgo-modules
Kubecost | Kubernetes cost monitoring and management

Kubecost | Kubernetes cost monitoring and management

Kubecost started in early 2019 as an open-source tool to give developers visibility into Kubernetes spend. We maintain a deep commitment to building and supporting dedicated solutions for the open source community.

cloudkubecostkubernetesopen-sourceself-hosted
Related Recommended Stories
Awesome Python

Awesome Python

An opinionated list of awesome Python frameworks, libraries, software and resources

awesomecollectionsgithubpythonpython-framework
Found means fixed - Introducing code scanning autofix, powered by GitHub Copilot and CodeQL

Found means fixed - Introducing code scanning autofix, powered by GitHub Copilot and CodeQL

Now in public beta for GitHub Advanced Security customers, code scanning autofix helps developers remediate more than two-thirds of supported alerts with little or no editing.

code-scanningcodeqlcodinggithubgithub-advanced-security
Awesome Java

Awesome Java

A curated list of awesome frameworks, libraries and software for the Java programming language

awesomebuildcachingclicode-analysis
Awesome iOS

Awesome iOS

A curated list of awesome iOS ecosystem, including Objective-C and Swift Projects

analyticsapp-routingapp-storeapple-swiftapple-tv