Flutter Buttons – Detailed Notes
Buttons are one of the most important interactive elements in a Flutter application. They allow users to perform actions such as submitting forms, opening screens, saving information, downloading files, adding products to a cart, deleting records, and navigating through an application.
Flutter provides several Material button widgets, including ElevatedButton, FilledButton, OutlinedButton, TextButton, IconButton, and FloatingActionButton. Modern Flutter uses these button widgets instead of the older FlatButton, RaisedButton, and OutlineButton widgets. :contentReference[oaicite:0]{index=0}
1. What Is a Button in Flutter?
A button is an interactive widget that responds to user actions such as tapping, clicking, hovering, focusing, or long-pressing.
Common Button Actions
- Submit a form
- Open another screen
- Save data
- Delete data
- Download content
- Add an item to a cart
- Open a menu
- Search for information
- Like or favorite an item
- Start or stop an operation
Basic Button Structure
ElevatedButton(
onPressed: () {
print('Button clicked');
},
child: const Text('Click Me'),
)
Most standard Flutter buttons use an onPressed callback and a widget representing their content. :contentReference[oaicite:1]{index=1}
2. Main Types of Flutter Buttons
| Button | Purpose | Common Use |
ElevatedButton | Prominent filled button with elevation | Primary actions |
FilledButton | Prominent filled button without elevation emphasis | Primary actions |
FilledButton.tonal | Tonal filled button | Secondary actions |
OutlinedButton | Button with an outline and no filled background by default | Secondary actions |
TextButton | Simple button without an outline or filled background by default | Low-emphasis actions |
IconButton | Button represented primarily by an icon | Toolbar and compact actions |
FloatingActionButton | Floating prominent action button | Main screen action |
Material 3 defines five common button types: Elevated, Filled, Filled Tonal, Outlined, and Text. Flutter provides corresponding button implementations. :contentReference[oaicite:2]{index=2}
3. ElevatedButton
ElevatedButton is a filled button that provides visual elevation and is useful for prominent actions.
Basic Syntax
ElevatedButton(
onPressed: () {
print('Clicked');
},
child: const Text('Submit'),
)
Complete Example
import 'package:flutter/material.dart';
class ElevatedButtonExample extends StatelessWidget {
const ElevatedButtonExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Elevated Button'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
print('Button pressed');
},
child: const Text('Submit'),
),
),
);
}
}
Flutter's ElevatedButton is intended to add visual prominence and elevation to an action. :contentReference[oaicite:3]{index=3}
4. Changing ElevatedButton Colors
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
onPressed: () {},
child: const Text('Login'),
)
backgroundColor controls the button background.
foregroundColor controls text and icon color.
5. Changing Button Size
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(200, 50),
),
onPressed: () {},
child: const Text('Continue'),
)
Full Width Button
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: const Text('Continue'),
),
)
6. Button Padding
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 30,
vertical: 15,
),
),
onPressed: () {},
child: const Text('Submit'),
)
7. Button Border Radius
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
onPressed: () {},
child: const Text('Rounded Button'),
)
Pill-Shaped Button
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
),
onPressed: () {},
child: const Text('Get Started'),
)
8. OutlinedButton
OutlinedButton displays an outlined button and is commonly used for secondary actions.
Basic Example
OutlinedButton(
onPressed: () {
print('Edit clicked');
},
child: const Text('Edit'),
)
Styled OutlinedButton
OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.blue,
side: const BorderSide(
color: Colors.blue,
width: 2,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: () {},
child: const Text('Learn More'),
)
9. TextButton
TextButton is a low-emphasis button without a visible border or filled background by default. It is useful for actions such as Cancel, Skip, Learn More, or Edit.
Basic Example
TextButton(
onPressed: () {
print('Cancel clicked');
},
child: const Text('Cancel'),
)
Styled TextButton
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
),
onPressed: () {},
child: const Text('Forgot Password?'),
)
Flutter documentation describes TextButton as appropriate for toolbars, dialogs, and inline actions where its placement provides enough context. :contentReference[oaicite:4]{index=4}
10. FilledButton
FilledButton is a filled Material button that does not use elevation as its primary visual distinction.
FilledButton(
onPressed: () {},
child: const Text('Save'),
)
Styled FilledButton
FilledButton(
style: FilledButton.styleFrom(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
),
onPressed: () {},
child: const Text('Save Changes'),
)
11. FilledButton.tonal
FilledButton.tonal provides a tonal filled appearance and can be useful for actions that need emphasis without looking as strong as a primary filled button.
FilledButton.tonal(
onPressed: () {},
child: const Text('View Details'),
)
12. TextButton vs ElevatedButton vs OutlinedButton
| Feature | TextButton | ElevatedButton | OutlinedButton |
| Background | Transparent by default | Filled | Transparent by default |
| Border | No visible border by default | No visible border by default | Visible outline |
| Elevation | No elevation | Uses elevation | No elevation |
| Typical Use | Low-emphasis actions | Prominent actions | Secondary actions |
| Example | Cancel | Submit | Learn More |
13. IconButton
IconButton is used when an icon itself represents an interactive action.
IconButton(
icon: const Icon(Icons.favorite),
onPressed: () {
print('Favorite clicked');
},
)
Styled IconButton
IconButton(
icon: const Icon(Icons.favorite),
iconSize: 35,
color: Colors.red,
onPressed: () {},
)
IconButton supports standard, filled, tonal, and outlined variants and can also be configured using an IconButtonTheme or its style. :contentReference[oaicite:5]{index=5}
14. IconButton with Tooltip
A tooltip can make an icon-only action easier to understand, especially when its purpose is not obvious.
IconButton(
tooltip: 'Delete',
icon: const Icon(Icons.delete),
onPressed: () {
print('Delete clicked');
},
)
15. IconButton Toggle
An icon button can be used as a toggle to represent states such as favorite/unfavorite or selected/unselected.
bool isFavorite = false;
For a stateful implementation:
class FavoriteButton extends StatefulWidget {
const FavoriteButton({super.key});
@override
State createState() =>
_FavoriteButtonState();
}
class _FavoriteButtonState extends State {
bool isFavorite = false;
@override
Widget build(BuildContext context) {
return IconButton(
isSelected: isFavorite,
selectedIcon: const Icon(Icons.favorite),
icon: const Icon(Icons.favorite_border),
onPressed: () {
setState(() {
isFavorite = !isFavorite;
});
},
);
}
}
16. Buttons with Icons
Flutter provides convenient constructors such as ElevatedButton.icon(), FilledButton.icon(), OutlinedButton.icon(), and TextButton.icon().
ElevatedButton.icon
ElevatedButton.icon(
onPressed: () {},
icon: const Icon(Icons.download),
label: const Text('Download'),
)
FilledButton.icon
FilledButton.icon(
onPressed: () {},
icon: const Icon(Icons.save),
label: const Text('Save'),
)
OutlinedButton.icon
OutlinedButton.icon(
onPressed: () {},
icon: const Icon(Icons.edit),
label: const Text('Edit'),
)
TextButton.icon
TextButton.icon(
onPressed: () {},
icon: const Icon(Icons.share),
label: const Text('Share'),
)
17. FloatingActionButton
FloatingActionButton is commonly used for a primary action that should remain easily accessible on a screen.
Scaffold(
body: const Center(
child: Text('Home Screen'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
print('Add clicked');
},
child: const Icon(Icons.add),
),
)
FloatingActionButton with Tooltip
FloatingActionButton(
tooltip: 'Add Item',
onPressed: () {},
child: const Icon(Icons.add),
)
18. FloatingActionButton.extended
The extended version can display both an icon and a text label.
FloatingActionButton.extended(
onPressed: () {},
icon: const Icon(Icons.add),
label: const Text('Add Item'),
)
19. Button onPressed Callback
The onPressed callback defines what should happen when the button is activated.
ElevatedButton(
onPressed: () {
print('Hello Flutter');
},
child: const Text('Click'),
)
Calling a Function
void showMessage() {
print('Button pressed');
}
ElevatedButton(
onPressed: showMessage,
child: const Text('Click'),
)
20. Passing Parameters to a Function
void showUser(String name) {
print('Hello $name');
}
ElevatedButton(
onPressed: () {
showUser('Rahul');
},
child: const Text('Welcome'),
)
21. Disabling a Button
A button can be disabled by setting onPressed to null.
ElevatedButton(
onPressed: null,
child: const Text('Disabled'),
)
For standard Material buttons, a null onPressed and onLongPress causes the button to be disabled. :contentReference[oaicite:6]{index=6}
22. Conditional Button State
bool isEnabled = true;
ElevatedButton(
onPressed: isEnabled
? () {
print('Button clicked');
}
: null,
child: const Text('Submit'),
)
Practical Example
class SubmitButton extends StatefulWidget {
const SubmitButton({super.key});
@override
State createState() => _SubmitButtonState();
}
class _SubmitButtonState extends State {
bool isLoading = false;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: isLoading
? null
: () async {
setState(() {
isLoading = true;
});
await Future.delayed(
const Duration(seconds: 2),
);
setState(() {
isLoading = false;
});
},
child: isLoading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: const Text('Submit'),
);
}
}
23. ButtonStyle
ButtonStyle is used to control the appearance and behavior-related visual properties of Material buttons. It can define properties such as colors, padding, shape, minimum size, borders, and state-dependent visual behavior. :contentReference[oaicite:7]{index=7}
Example
ElevatedButton(
style: ButtonStyle(
backgroundColor: WidgetStatePropertyAll(
Colors.blue,
),
foregroundColor: WidgetStatePropertyAll(
Colors.white,
),
padding: WidgetStatePropertyAll(
EdgeInsets.symmetric(
horizontal: 25,
vertical: 15,
),
),
),
onPressed: () {},
child: const Text('Submit'),
)
24. Using styleFrom()
The styleFrom() methods provide a convenient way to create button styles using straightforward property values.
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 30,
vertical: 15,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: () {},
child: const Text('Register'),
)
Flutter provides styleFrom() methods for common Material button classes, including ElevatedButton, FilledButton, OutlinedButton, and TextButton. :contentReference[oaicite:8]{index=8}
25. Button Shape
Rounded Rectangle
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
onPressed: () {},
child: const Text('Rounded'),
)
Stadium Shape
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
),
onPressed: () {},
child: const Text('Pill Button'),
)
26. Button Border
Outlined buttons are especially useful when you want to emphasize a border.
OutlinedButton(
style: OutlinedButton.styleFrom(
side: const BorderSide(
color: Colors.blue,
width: 2,
),
),
onPressed: () {},
child: const Text('Outlined'),
)
27. Button Text Styling
ElevatedButton(
style: ElevatedButton.styleFrom(
textStyle: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
onPressed: () {},
child: const Text('Submit'),
)
28. Button Elevation
ElevatedButton can be customized with an elevation value.
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 8,
),
onPressed: () {},
child: const Text('Elevated'),
)
29. Button Minimum Size
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(180, 50),
),
onPressed: () {},
child: const Text('Continue'),
)
30. Button Maximum Size
ElevatedButton(
style: ElevatedButton.styleFrom(
maximumSize: const Size(300, 60),
),
onPressed: () {},
child: const Text('Continue'),
)
31. Full Width Login Button
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
print('Login');
},
child: const Text('Login'),
),
),
)
32. Login Screen Buttons Example
Column(
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
print('Login');
},
child: const Text('Login'),
),
),
const SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: () {
print('Create account');
},
child: const Text('Create Account'),
),
),
const SizedBox(height: 10),
TextButton(
onPressed: () {
print('Forgot password');
},
child: const Text('Forgot Password?'),
),
],
)
33. Save, Edit, and Delete Buttons
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
onPressed: () {},
icon: const Icon(Icons.save),
label: const Text('Save'),
),
OutlinedButton.icon(
onPressed: () {},
icon: const Icon(Icons.edit),
label: const Text('Edit'),
),
IconButton(
tooltip: 'Delete',
icon: const Icon(Icons.delete),
color: Colors.red,
onPressed: () {},
),
],
)
34. Button with Loading Indicator
A loading state is useful when a button starts an asynchronous operation.
ElevatedButton(
onPressed: () async {
print('Processing...');
},
child: const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
)
Dynamic Loading Button
class LoadingButton extends StatefulWidget {
const LoadingButton({super.key});
@override
State createState() => _LoadingButtonState();
}
class _LoadingButtonState extends State {
bool loading = false;
Future submit() async {
setState(() {
loading = true;
});
await Future.delayed(
const Duration(seconds: 2),
);
if (mounted) {
setState(() {
loading = false;
});
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: loading ? null : submit,
child: loading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: const Text('Submit'),
);
}
}
35. Buttons Inside Cards
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Flutter Course',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
const Text(
'Learn Flutter application development.',
),
const SizedBox(height: 15),
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: () {},
child: const Text('Enroll'),
),
),
const SizedBox(width: 10),
Expanded(
child: OutlinedButton(
onPressed: () {},
child: const Text('Details'),
),
),
],
),
],
),
),
)
36. Buttons Inside a Dialog
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Delete Item'),
content: const Text(
'Are you sure you want to delete this item?',
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Delete'),
),
],
);
},
);
37. Buttons and Navigation
Buttons are frequently used to navigate from one screen to another.
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SecondScreen(),
),
);
},
child: const Text('Open Next Screen'),
)
Complete Example
class SecondScreen extends StatelessWidget {
const SecondScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Screen'),
),
body: const Center(
child: Text('Welcome to Second Screen'),
),
);
}
}
38. Buttons with Form Validation
Buttons are commonly used to submit a Form.
final formKey = GlobalKey();
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
return null;
},
decoration: const InputDecoration(
labelText: 'Name',
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
print('Form is valid');
}
},
child: const Text('Submit'),
),
],
),
)
39. Creating a Custom Reusable Button
When the same button design is used throughout an application, creating a reusable custom widget can reduce duplicate code.
class PrimaryButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
const PrimaryButton({
super.key,
required this.text,
required this.onPressed,
});
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: onPressed,
child: Text(text),
),
);
}
}
Using the Custom Button
PrimaryButton(
text: 'Login',
onPressed: () {
print('Login clicked');
},
)
40. Creating a Reusable Icon Button
class ActionIconButton extends StatelessWidget {
final IconData icon;
final String tooltip;
final VoidCallback onPressed;
const ActionIconButton({
super.key,
required this.icon,
required this.tooltip,
required this.onPressed,
});
@override
Widget build(BuildContext context) {
return IconButton(
tooltip: tooltip,
icon: Icon(icon),
onPressed: onPressed,
);
}
}
Using the Widget
ActionIconButton(
icon: Icons.delete,
tooltip: 'Delete',
onPressed: () {
print('Delete');
},
)
41. Theming Buttons Globally
Instead of styling every button separately, button themes can be configured in ThemeData. Flutter provides separate themes for button types such as ElevatedButtonTheme, OutlinedButtonTheme, and TextButtonTheme. :contentReference[oaicite:9]{index=9}
MaterialApp(
theme: ThemeData(
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
),
home: const HomeScreen(),
)
Now ElevatedButtons throughout the relevant application theme can use the configured styling unless a local style overrides it.
42. Button States
Buttons can have different visual states depending on user interaction.
| State | Description |
| Enabled | Button can be activated. |
| Disabled | Button cannot be activated. |
| Pressed | User is currently pressing the button. |
| Hovered | Pointer is positioned over the button, especially relevant on desktop/web. |
| Focused | Button has keyboard or accessibility focus. |
| Selected | Used by supported controls to represent a selected state. |
Flutter's button styling system supports state-dependent values through state properties. :contentReference[oaicite:10]{index=10}
43. State-Dependent Button Styling
For advanced designs, a button's style can respond differently to pressed, hovered, focused, or other widget states.
ElevatedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.resolveWith(
(states) {
if (states.contains(WidgetState.pressed)) {
return Colors.blue.shade900;
}
if (states.contains(WidgetState.hovered)) {
return Colors.blue.shade700;
}
return Colors.blue;
},
),
),
onPressed: () {},
child: const Text('Interactive Button'),
)
44. Button Alignment
Buttons can be aligned using layout widgets.
Center Button
Center(
child: ElevatedButton(
onPressed: () {},
child: const Text('Center'),
),
)
Right-Aligned Button
Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
onPressed: () {},
child: const Text('Continue'),
),
)
45. Multiple Buttons in a Row
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {},
child: const Text('Save'),
),
const SizedBox(width: 10),
OutlinedButton(
onPressed: () {},
child: const Text('Cancel'),
),
],
)
46. Multiple Buttons in a Column
Column(
children: [
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: const Text('Login'),
),
),
const SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: () {},
child: const Text('Register'),
),
),
TextButton(
onPressed: () {},
child: const Text('Forgot Password?'),
),
],
)
47. Complete Buttons Example
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Buttons',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
),
useMaterial3: true,
),
home: const ButtonsScreen(),
);
}
}
class ButtonsScreen extends StatelessWidget {
const ButtonsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Buttons'),
actions: [
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: () {},
),
],
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ElevatedButton(
onPressed: () {
print('Elevated button');
},
child: const Text('Elevated Button'),
),
const SizedBox(height: 15),
FilledButton(
onPressed: () {
print('Filled button');
},
child: const Text('Filled Button'),
),
const SizedBox(height: 15),
FilledButton.tonal(
onPressed: () {
print('Tonal button');
},
child: const Text('Tonal Button'),
),
const SizedBox(height: 15),
OutlinedButton(
onPressed: () {
print('Outlined button');
},
child: const Text('Outlined Button'),
),
const SizedBox(height: 15),
TextButton(
onPressed: () {
print('Text button');
},
child: const Text('Text Button'),
),
const SizedBox(height: 15),
ElevatedButton.icon(
onPressed: () {
print('Download');
},
icon: const Icon(Icons.download),
label: const Text('Download'),
),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
tooltip: 'Favorite',
icon: const Icon(Icons.favorite_border),
onPressed: () {},
),
IconButton(
tooltip: 'Share',
icon: const Icon(Icons.share),
onPressed: () {},
),
IconButton(
tooltip: 'Delete',
icon: const Icon(Icons.delete),
color: Colors.red,
onPressed: () {},
),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add',
onPressed: () {},
child: const Icon(Icons.add),
),
);
}
}
48. Button Selection Guide
| Requirement | Recommended Widget |
| Main important action | ElevatedButton or FilledButton |
| Secondary action | OutlinedButton |
| Low-emphasis action | TextButton |
| Action represented by an icon | IconButton |
| Main floating screen action | FloatingActionButton |
| Action with icon and text | ElevatedButton.icon, FilledButton.icon, OutlinedButton.icon, or TextButton.icon |
| Tonal filled action | FilledButton.tonal |
49. Old Flutter Buttons vs Modern Buttons
| Old Widget | Modern Replacement |
FlatButton | TextButton |
RaisedButton | ElevatedButton |
OutlineButton | OutlinedButton |
The older Material button widgets were deprecated and replaced by the newer button classes. New Flutter applications should use the current button APIs. :contentReference[oaicite:11]{index=11}
50. Button Accessibility Best Practices
- Use clear and meaningful button labels.
- Use tooltips for icon-only actions where appropriate.
- Do not make important actions depend only on color.
- Maintain sufficient contrast between button content and its background.
- Provide an adequate interactive area for touch controls.
- Use disabled states only when the action genuinely cannot be performed.
- Make button behavior predictable.
- Use semantic labels when the visual content alone does not communicate the action clearly.
Example
IconButton(
tooltip: 'Delete account',
icon: const Icon(Icons.delete),
onPressed: () {},
)
51. Button Design Best Practices
- Use one visually prominent primary action where appropriate.
- Use consistent button shapes throughout the application.
- Keep button labels short and action-oriented.
- Use icons when they improve recognition of the action.
- Avoid placing too many competing primary buttons together.
- Use loading indicators when an action takes noticeable time.
- Disable buttons when an action cannot currently be performed.
- Use reusable custom button widgets for repeated designs.
- Use application-level button themes for consistent styling.
- Prefer current Flutter button widgets instead of deprecated button APIs.
52. Common Mistakes
Mistake 1: Forgetting onPressed
ElevatedButton(
child: const Text('Submit'),
)
The standard constructor requires an onPressed callback.
Correct Version
ElevatedButton(
onPressed: () {},
child: const Text('Submit'),
)
Mistake 2: Using Deprecated Button Widgets
Avoid starting new projects with FlatButton, RaisedButton, or OutlineButton. Use their modern replacements.
Mistake 3: Using Too Many Colors
Using a different button color for every action can make the interface inconsistent. Use a clear visual hierarchy.
Mistake 4: Ignoring Disabled State
If an action cannot currently be performed, provide an appropriate disabled state instead of allowing the user to trigger an invalid operation.
Mistake 5: Using IconButton Without Context
An unfamiliar icon may not clearly communicate its purpose. Add a tooltip or supporting context when appropriate.
53. Practice Exercises
- Create a screen containing ElevatedButton, FilledButton, OutlinedButton, and TextButton.
- Create a login screen with Login and Register buttons.
- Create a registration form with a Submit button.
- Create a product card with Add to Cart and Favorite buttons.
- Create an AppBar with Search, Notifications, and Settings IconButtons.
- Create a delete confirmation dialog containing Cancel and Delete buttons.
- Create a loading Submit button using
setState().
- Create a custom reusable primary button.
- Create a FloatingActionButton for adding a new item.
- Create a button that navigates from one screen to another.
- Create a favorite button that changes between favorite and favorite-border icons.
- Create a global button theme using
ThemeData.
54. Interview Questions
- What is a button in Flutter?
- What are the main button widgets in Flutter?
- What is the difference between ElevatedButton and FilledButton?
- What is the difference between ElevatedButton and OutlinedButton?
- When should you use TextButton?
- What is IconButton?
- What is FloatingActionButton?
- How do you disable a Flutter button?
- What is the purpose of the
onPressed property?
- How do you add an icon to an ElevatedButton?
- What is ButtonStyle?
- What is the purpose of
styleFrom()?
- How do you change a button's background color?
- How do you change a button's border?
- How do you create a rounded button?
- How do you create a full-width button?
- How do you create a reusable custom button?
- How can button styles respond to pressed or hovered states?
- How can you show a loading indicator inside a button?
- Which old Flutter button widgets have been replaced by modern button widgets?
55. Key Takeaways
- Buttons provide interaction between the user and the application.
ElevatedButton is useful for prominent actions.
FilledButton provides a prominent filled Material 3 button.
FilledButton.tonal provides a tonal filled button.
OutlinedButton is useful for secondary actions.
TextButton is useful for low-emphasis actions.
IconButton is useful for compact icon-based actions.
FloatingActionButton is useful for a prominent floating action.
ButtonStyle provides advanced button customization.
styleFrom() provides a convenient way to create common button styles.
- Buttons can contain both text and icons.
- Buttons can be enabled, disabled, pressed, hovered, focused, or selected depending on the widget and configuration.
- Button themes help maintain consistent application-wide styling.
- Use current Flutter button APIs instead of deprecated button widgets.
56. Learning Resources
JustAcademy Flutter Training: Flutter Training
Register for Course Demo: Register for Course Demo
Official Flutter Button Styling Documentation: ButtonStyle API
Official ElevatedButton Documentation: ElevatedButton API
Official TextButton Documentation: TextButton API
Official IconButton Documentation: IconButton API
Official Flutter Interactivity Guide: Adding Interactivity to Your Flutter App