flutter Icon button with text description below it
Use a Column
to display widgets in vertical order:
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(...),
Text(...),
],
)
You can use a RaisedButton
and have a Row/Column having an Icon and Text as its child.
RaisedButton(
color: Colors.redAccent,
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.camera,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Capture from Camera",
style: TextStyle(
color: Colors.yellow,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: () {
},
);
You can replace Row
with Column
if you want icon and text to be side-by-side.
Heres a widget I wrote for a project which should do the job.
I provided examples of a "Icon Button with Text Below It" and also a "Image Button with Text Below It"
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconTextButton(
image: Image.network(
'https://robohash.org/YOUR-TEXT.png',
height: 50,
),
label: 'image button',
onTap: () {
/// your on pressed function here
},
toolTip: 'button with image',
highlightColor: Colors.deepOrangeAccent,
),
IconTextButton(
icon: Icon(Icons.edit),
label: 'icon button',
onTap: () {
/// your on pressed function here
},
toolTip: 'button with icon',
highlightColor: Colors.deepOrangeAccent,
),
],
)
],
),
),
);
}
}
class IconTextButton extends StatelessWidget {
/// Icon to display in button. Leave null to hide icon.
final Icon? icon;
/// Image to display between icon and label. Leave null to hide image.
final Image? image;
/// Text to display under icon. Leave null to hide text.
final String? label;
/// function to execute when user taps button. Leave null to disable button.
final VoidCallback? onTap;
/// optional tooltip to display.
final String? toolTip;
/// cursor to display when user mouses over button
///
/// Defaults to [SystemMouseCursors.click]
final MouseCursor mouseCursor;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
final bool enableFeedback;
/// text style to apply to label
final TextStyle? labelStyle;
/// The color of the icon when no onTap function is provided
///
/// Defaults to [ThemeData.disabledColor]
final Color? disabledIconColor;
/// The color of the label text when no onTap function is provided
///
/// Defaults to [ThemeData.disabledColor]
final Color? disabledTextColor;
/// The overlay color of the image when no onTap function is provided
///
/// Defaults to greyscale color filter
final ColorFilter? disabledImageColorFilter;
/// The color for the button's icon when a pointer is hovering over it.
///
/// Defaults to [ThemeData.hoverColor] of the ambient theme.
final Color? hoverColor;
/// The color of the button when in the down (pressed) state.
///
/// Defaults to the Theme's highlight color, [ThemeData.highlightColor].
final Color? highlightColor;
/// The radius of the ink Splash
///
/// Defaults to the [InkResponse] radius
final double? radius;
const IconTextButton({
this.icon,
this.image,
this.label,
this.onTap,
this.toolTip,
this.mouseCursor = SystemMouseCursors.click,
this.enableFeedback = true,
this.labelStyle,
this.disabledIconColor,
this.disabledTextColor,
this.disabledImageColorFilter = const ColorFilter.matrix(<double>[
0.2126,
0.7152,
0.0722,
0,
0,
0.2126,
0.7152,
0.0722,
0,
0,
0.2126,
0.7152,
0.0722,
0,
0,
0,
0,
0,
1,
0,
]),
this.hoverColor,
this.highlightColor,
this.radius,
});
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
Color? _disabledIconColor;
Color? _disabledTextColor;
ColorFilter? _disabledImageColorFilter;
/// determine disabled status
if (onTap == null) {
_disabledIconColor = disabledIconColor ?? theme.disabledColor;
_disabledTextColor = disabledTextColor ?? theme.disabledColor;
_disabledImageColorFilter = disabledImageColorFilter;
}
/// generate icon
Widget _icon = Container();
if (icon != null) {
Widget _iconChild = icon!;
if (_disabledIconColor != null) {
_iconChild = IconTheme.merge(
data: IconThemeData(
color: _disabledIconColor,
),
child: icon!,
);
}
_icon = Align(
alignment: Alignment.topCenter,
heightFactor: 1.0,
child: _iconChild,
);
}
/// generate icon label
Widget _label = Container();
if (label != null) {
TextStyle _labelStyle = labelStyle ?? TextStyle();
if (_disabledTextColor != null) {
_labelStyle = _labelStyle.copyWith(color: _disabledTextColor);
}
_label = Text(
label!,
style: _labelStyle,
);
}
/// generate image
Widget _image = Container();
if (image != null) {
_image = image!;
if (_disabledImageColorFilter != null) {
// In this case ColorFilter will ignore transparent areas of your images.
_image = ColorFiltered(
colorFilter: _disabledImageColorFilter,
child: image!,
);
}
}
/// generate button
Widget toolBarButton = InkResponse(
onTap: onTap,
canRequestFocus: onTap != null,
hoverColor: hoverColor ?? theme.hoverColor,
highlightColor: highlightColor ?? theme.highlightColor,
mouseCursor: mouseCursor,
enableFeedback: enableFeedback,
radius: radius,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: [
_icon,
_image,
_label,
],
),
);
/// conditionally wrap with tooltip
if (toolTip != null) {
toolBarButton = Tooltip(
message: toolTip!,
preferBelow: false,
child: toolBarButton,
);
}
return toolBarButton;
}
}