Flutter button widgets are interactive components that respond to user taps and trigger specific actions in your application. The Flutter framework provides various button types to suit different UI needs and design requirements. Understanding the properties and behavior of each Flutter button widget is crucial for creating intuitive and responsive user interfaces.
Flutter's Material Design implementation offers several button variants, each with distinct visual styles and behaviors. Additionally, Flutter allows you to create custom button widgets for unique design requirements.
The ElevatedButton
is a Material Design button with elevation that lifts when pressed. It's one of the most commonly used Flutter button widgets, replacing the deprecated RaisedButton
from earlier Flutter versions.
Property | Type | Description |
---|---|---|
onPressed | VoidCallback? | Required. The callback function when the button is tapped. If null, the button appears disabled. |
onLongPress | VoidCallback? | Called when the button is long-pressed. |
onHover | ValueChanged<bool>? | Called when pointer enters or exits the button. |
style | ButtonStyle? | Used to customize the button's appearance. |
child | Widget | The widget displayed inside the button (usually Text or Icon). |
clipBehavior | Clip | How to clip the button's content. |
autofocus | bool | Whether the button should take focus initially. |
ElevatedButton(
onPressed: () {
print('ElevatedButton pressed!');
},
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.blue,
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
),
child: Text('ElevatedButton'),
)
The style
property allows extensive customization of the Flutter button widget appearance:
ElevatedButton(
onPressed: () {},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.pressed))
return Colors.blue.shade700;
return Colors.blue;
},
),
foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
elevation: MaterialStateProperty.all<double>(5),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
),
child: Text('Custom Styled Button'),
)
TextButton
is a flat button without elevation. It's typically used for less prominent actions, often within dialogs or as an alternative to more prominent buttons.
Property | Type | Description |
---|---|---|
onPressed | VoidCallback? | Required. The callback function when button is tapped. |
onLongPress | VoidCallback? | Called when the button is long-pressed. |
style | ButtonStyle? | Used to customize the button's appearance. |
child | Widget | The widget displayed inside the button. |
TextButton(
onPressed: () {
print('TextButton pressed!');
},
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
textStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
child: Text('TextButton'),
)
OutlinedButton
is a button with an outline border and no fill. It's useful for actions that deserve less emphasis than ElevatedButton
but more than TextButton
.
Property | Type | Description |
---|---|---|
onPressed | VoidCallback? | Required. The callback function when button is tapped. |
onLongPress | VoidCallback? | Called when the button is long-pressed. |
style | ButtonStyle? | Used to customize the button's appearance. |
child | Widget | The widget displayed inside the button. |
OutlinedButton(
onPressed: () {
print('OutlinedButton pressed!');
},
style: OutlinedButton.styleFrom(
foregroundColor: Colors.purple,
side: BorderSide(color: Colors.purple, width: 2),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
),
child: Text('OutlinedButton'),
)
IconButton
is a button that displays an icon without a background or border. It's commonly used in app bars, toolbars, and other compact UI elements.
Property | Type | Description |
---|---|---|
onPressed | VoidCallback? | Required. The callback function when button is tapped. |
icon | Widget | Required. The icon to display (usually an Icon widget). |
color | Color? | The color for the icon. |
splashRadius | double? | The radius of the splash effect. |
tooltip | String? | Text shown when the user long-presses the button. |
iconSize | double | Size of the icon, defaults to 24.0. |
padding | EdgeInsetsGeometry | Padding around the icon. |
IconButton(
onPressed: () {
print('IconButton pressed!');
},
icon: Icon(Icons.favorite),
color: Colors.red,
tooltip: 'Favorite',
splashRadius: 25,
iconSize: 30,
)
FloatingActionButton
(FAB) is a circular button that floats above the UI, typically used for the primary action on a screen. It's a prominent Flutter button widget for key actions.
Property | Type | Description |
---|---|---|
onPressed | VoidCallback | Required. The callback function when button is tapped. |
child | Widget | The widget displayed inside the button (usually an Icon). |
tooltip | String? | Text shown when the user long-presses the button. |
foregroundColor | Color? | The color for the icon/child. |
backgroundColor | Color? | The button's background color. |
elevation | double? | The z-coordinate at which to place this button. |
mini | bool | Whether to use a smaller-sized button. |
shape | ShapeBorder? | The shape of the button's material. |
extended | bool | Whether to create an extended FAB with both an icon and a label. |
label | Widget? | Used with extended FABs to show a label next to the icon. |
FloatingActionButton(
onPressed: () {
print('FAB pressed!');
},
backgroundColor: Colors.green,
child: Icon(Icons.add),
tooltip: 'Add Item',
)
FloatingActionButton.extended(
onPressed: () {
print('Extended FAB pressed!');
},
label: Text('Create'),
icon: Icon(Icons.add),
backgroundColor: Colors.green,
)
DropdownButton
is a Flutter button widget that shows a menu when pressed, allowing users to select from a list of items.
Property | Type | Description |
---|---|---|
items | List<DropdownMenuItem<T>>? | The list of items to display in the dropdown. |
value | T? | The currently selected value. |
onChanged | ValueChanged<T?>? | Called when the user selects an item. |
hint | Widget? | Displayed if no item is selected. |
disabledHint | Widget? | Displayed if dropdown is disabled. |
icon | Widget? | The icon to display next to the button. |
style | TextStyle? | The text style to use for the items. |
underline | Widget? | The widget to display as the underline. |
isDense | bool | Whether to reduce the height of the button. |
isExpanded | bool | Whether the button should expand to fill its parent. |
String dropdownValue = 'One';
DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_drop_down),
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['One', 'Two', 'Three', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
PopupMenuButton
displays a menu when pressed, similar to a dropdown but typically used for actions rather than selection.
Property | Type | Description |
---|---|---|
itemBuilder | PopupMenuItemBuilder<T> | Required. Builds the items in the menu. |
onSelected | PopupMenuItemSelected<T>? | Called when a menu item is selected. |
icon | Widget? | The icon to display for the button. |
offset | Offset? | The offset of the popup menu from the button. |
tooltip | String? | Text shown when the user long-presses the button. |
elevation | double? | The z-coordinate at which to place the menu. |
padding | EdgeInsetsGeometry? | Padding inside the button. |
PopupMenuButton<String>(
onSelected: (String result) {
print('Selected: $result');
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
const PopupMenuItem<String>(
value: 'edit',
child: Text('Edit'),
),
const PopupMenuItem<String>(
value: 'delete',
child: Text('Delete'),
),
const PopupMenuItem<String>(
value: 'share',
child: Text('Share'),
),
],
icon: Icon(Icons.more_vert),
tooltip: 'Menu',
)
InkWell
is not technically a button, but it's commonly used to create custom button-like behaviors with Material Design ink splash effects.
Property | Type | Description |
---|---|---|
onTap | GestureTapCallback? | Called when tapped. |
onDoubleTap | GestureTapCallback? | Called when double-tapped. |
onLongPress | GestureLongPressCallback? | Called when long-pressed. |
child | Widget | The widget displayed inside the InkWell. |
splashColor | Color? | The color of the splash effect. |
highlightColor | Color? | The color of the highlight effect. |
radius | double? | The radius of the splash effect. |
InkWell(
onTap: () {
print('InkWell tapped!');
},
splashColor: Colors.blue.withAlpha(30),
highlightColor: Colors.blue.withAlpha(15),
borderRadius: BorderRadius.circular(10),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Custom InkWell Button',
style: TextStyle(color: Colors.blue),
),
),
)
Similar to InkWell
, GestureDetector
can be used to create custom buttons, but without the Material Design splash effects.
Property | Type | Description |
---|---|---|
onTap | GestureTapCallback? | Called when tapped. |
onDoubleTap | GestureTapCallback? | Called when double-tapped. |
onLongPress | GestureLongPressCallback? | Called when long-pressed. |
child | Widget | The widget displayed inside the GestureDetector. |
GestureDetector(
onTap: () {
print('GestureDetector tapped!');
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(10),
),
child: Text(
'Custom GestureDetector Button',
style: TextStyle(color: Colors.white),
),
),
)
Creating custom Flutter button widgets allows for unique designs that match your app's branding. Here's an example of a custom button implementation:
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
final Color color;
const CustomButton({
Key? key,
required this.text,
required this.onPressed,
this.color = Colors.blue,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: onPressed,
borderRadius: BorderRadius.circular(15),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 25, vertical: 12),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: color.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 8,
offset: Offset(0, 3),
),
],
),
child: Text(
text,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
);
}
}
// Usage:
CustomButton(
text: 'Custom Flutter Button',
onPressed: () {
print('Custom button pressed!');
},
color: Colors.deepPurple,
)
Flutter allows you to define consistent button styles across your app using themes. This approach ensures visual consistency while reducing code duplication.
ThemeData(
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.purple,
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
),
),
)
ThemeData(
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Colors.purple,
textStyle: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
)
ThemeData(
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.teal,
side: BorderSide(color: Colors.teal, width: 2),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
)