Skip to content

Button

Flutter 提供了多种按钮组件,适用于不同场景。Material 3 风格下主要有四种按钮:

按钮用途特点
ElevatedButton主要操作有阴影/高度感,视觉最突出
FilledButton主要操作(M3 推荐)纯色填充,无阴影
OutlinedButton次要操作有边框,无填充背景
TextButton低优先级操作无边框无填充,最轻量
IconButton图标操作仅图标,无文字

构造函数

ElevatedButton

dart
ElevatedButton({
  Key? key,                                              // 组件标识
  required VoidCallback? onPressed,                       // 点击回调(必填,null 则禁用)
  VoidCallback? onLongPress,                             // 长按回调
  ValueChanged<bool>? onHover,                           // 悬停状态变化回调
  ValueChanged<bool>? onFocusChange,                     // 焦点状态变化回调
  ButtonStyle? style,                                    // 按钮样式
  FocusNode? focusNode,                                  // 焦点控制节点
  bool autofocus = false,                                // 是否自动获取焦点
  Clip clipBehavior = Clip.none,                         // 裁剪行为
  MaterialStatesController? statesController,            // 状态控制器
  Widget? child,                                         // 子组件(通常为 Text)
})

ElevatedButton.icon({                                    // 带图标的构造函数
  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 icon,                                  // 图标(必填)
  required Widget label,                                 // 文字标签(必填)
})

FilledButton

dart
FilledButton({                                            // M3 推荐的主要按钮
  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,            // 状态控制器
  Widget? child,                                         // 子组件
})

FilledButton.icon({                                      // 带图标版本
  ...同上...
  required Widget icon,                                  // 图标(必填)
  required Widget label,                                 // 文字标签(必填)
})

OutlinedButton

dart
OutlinedButton({                                          // 边框按钮
  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,            // 状态控制器
  Widget? child,                                         // 子组件
})

OutlinedButton.icon({
  ...同上...
  required Widget icon,
  required Widget label,
})

TextButton

dart
TextButton({                                              // 文字按钮
  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,            // 状态控制器
  Widget? child,                                         // 子组件
})

TextButton.icon({
  ...同上...
  required Widget icon,
  required Widget label,
})

IconButton

dart
IconButton({                                              // 图标按钮
  Key? key,                                              // 组件标识
  double? iconSize,                                      // 图标大小(默认 24)
  VisualDensity? visualDensity,                          // 视觉密度
  EdgeInsetsGeometry padding = const EdgeInsets.all(8),  // 内边距
  AlignmentGeometry alignment = Alignment.center,       // 图标对齐方式
  bool enableFeedback = true,                           // 是否启用触觉反馈
  double? splashRadius,                                 // 水波纹半径
  Color? color,                                         // 图标颜色
  Color? focusColor,                                    // 焦点颜色
  Color? hoverColor,                                    // 悬停颜色
  Color? highlightColor,                                // 高亮颜色
  Color? splashColor,                                   // 水波纹颜色
  Color? disabledColor,                                 // 禁用颜色
  MouseCursor? mouseCursor,                             // 鼠标指针样式
  FocusNode? focusNode,                                 // 焦点节点
  bool autofocus = false,                               // 自动焦点
  String? tooltip,                                      // 长按提示文字
  bool? isSelected,                                     // 是否选中(用于切换按钮)
  ValueChanged<bool>? onPressed,                        // 选中状态变化回调
  required Widget icon,                                 // 图标组件(必填)
})

Floating Action Button (FAB)

dart
FloatingActionButton({                                   // 浮动操作按钮
  Key? key,
  Widget? child,                                         // 子组件(通常为 Icon)
  String? tooltip,                                       // 长按提示文字
  Color? foregroundColor,                                // 前景色(图标颜色)
  Color? backgroundColor,                                // 背景色
  Color? focusColor,                                     // 焦点颜色
  Color? hoverColor,                                    // 悬停颜色
  Color? splashColor,                                   // 水波纹颜色
  Object? heroTag,                                       // Hero 动画标签
  double? elevation,                                    // 阴影高度
  double? focusElevation,                               // 焦点阴影高度
  double? hoverElevation,                               // 悬停阴影高度
  double? highlightElevation,                           // 高亮阴影高度
  double? disabledElevation,                             // 禁用阴影高度
  required VoidCallback? onPressed,                      // 点击回调(必填)
  ShapeBorder shape = const CircleBorder(),             // 形状
  bool mini = false,                                    // 是否为迷你尺寸
  Clip clipBehavior = Clip.none,                         // 裁剪行为
  FocusNode? focusNode,                                 // 焦点节点
  bool autofocus = false,                               // 自动焦点
  MaterialTapTargetSize? materialTapTargetSize,         // 触摸目标大小
  bool isExtended = false,                              // 是否为扩展模式
})

FloatingActionButton.extended({                          // 带 label 的扩展 FAB
  Key? key,
  required Widget icon,                                  // 图标(必填)
  required Widget label,                                 // 文字标签(必填)
  String? tooltip,
  Color? foregroundColor,
  Color? backgroundColor,
  Color? focusColor,
  Color? hoverColor,
  Color? splashColor,
  Object? heroTag,
  double? elevation,
  double? focusElevation,
  double? hoverElevation,
  required VoidCallback? onPressed,
  ShapeBorder shape = const StadiumBorder(),
  Clip clipBehavior = Clip.none,
  FocusNode? focusNode,
  bool autofocus = false,
  MaterialTapTargetSize? materialTapTargetSize,
})

属性速查

通用属性(ElevatedButton / FilledButton / OutlinedButton / TextButton 共有)

属性类型默认值说明
onPressedVoidCallback?必填点击回调,null 时按钮禁用
onLongPressVoidCallback?null长按回调
onHoverValueChanged<bool>?null悬停状态变化回调
onFocusChangeValueChanged<bool>?null焦点状态变化回调
styleButtonStyle?null按钮样式(颜色、形状、大小等)
focusNodeFocusNode?null焦点控制节点
autofocusboolfalse是否自动获取焦点
clipBehaviorClipClip.none裁剪行为
childWidget?必填子组件(通常为 Text

IconButton 专属属性

属性类型默认值说明
iconWidget必填图标组件
iconSizedouble?24图标大小
colorColor?主题色图标颜色
paddingEdgeInsetsGeometryEdgeInsets.all(8)内边距
alignmentAlignmentGeometryAlignment.center图标对齐方式
tooltipString?null长按提示文字
splashRadiusdouble?null水波纹半径
isSelectedbool?null是否选中(切换按钮)

FloatingActionButton 专属属性

属性类型默认值说明
childWidget?必填子组件(通常为 Icon
backgroundColorColor?主题色背景色
foregroundColorColor?白色前景色(图标颜色)
elevationdouble?6阴影高度
shapeShapeBorderCircleBorder()形状
heroTagObject?默认自动Hero 动画标签(同一页面多个 FAB 需设不同值)
miniboolfalse是否为迷你尺寸(40x40)
isExtendedboolfalse是否为扩展模式(带文字)

ButtonStyle 速查

ButtonStyle 是按钮自定义的核心,通过 MaterialStateProperty 实现不同状态下的样式。

dart
ButtonStyle({
  MaterialStateProperty<TextStyle?>? textStyle,          // 文字样式
  MaterialStateProperty<Color?>? backgroundColor,       // 背景色
  MaterialStateProperty<Color?>? foregroundColor,        // 前景色(文字/图标)
  MaterialStateProperty<Color?>? overlayColor,            // 覆盖色(水波纹/高亮)
  MaterialStateProperty<double?>? elevation,             // 阴影高度
  MaterialStateProperty<Color?>? shadowColor,            // 阴影颜色
  MaterialStateProperty<double?>? padding,               // 内边距
  MaterialStateProperty<Size?>? minimumSize,             // 最小尺寸
  MaterialStateProperty<Size?>? fixedSize,               // 固定尺寸
  MaterialStateProperty<Size?>? maximumSize,             // 最大尺寸
  MaterialStateProperty<BorderSide?>? side,              // 边框
  MaterialStateProperty<OutlinedBorder?>? shape,         // 形状(圆角等)
  MaterialStateProperty<MouseCursor?>? mouseCursor,      // 鼠标指针
  MaterialStateProperty<VisualDensity?>? visualDensity,  // 视觉密度
  MaterialTapTargetSize? tapTargetSize,                   // 触摸目标大小
  MaterialStateProperty<AlignmentGeometry?>? alignment,  // 子组件对齐
  MaterialStateProperty<EdgeInsetsGeometry?>? iconSize,   // 图标间距
})

ButtonStyle 快捷设置方式

dart
// 方式1:使用 styleFrom 快捷方法(推荐)
ElevatedButton.styleFrom(
  backgroundColor: Colors.blue,        // 背景色
  foregroundColor: Colors.white,       // 文字/图标颜色
  elevation: 4,                        // 阴影高度
  padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),  // 内边距
  shape: RoundedRectangleBorder(       // 形状
    borderRadius: BorderRadius.circular(8),
  ),
  textStyle: TextStyle(fontSize: 16),  // 文字样式
  side: BorderSide(color: Colors.blue, width: 2),  // 边框(OutlinedButton 常用)
)

// 方式2:直接构造 ButtonStyle(适合按状态区分样式)
ButtonStyle(
  backgroundColor: MaterialStateProperty.resolveWith((states) {
    if (states.contains(MaterialState.disabled)) return Colors.grey;
    if (states.contains(MaterialState.pressed)) return Colors.blue[700];
    return Colors.blue;
  }),
)

styleFrom 方法速查

方法适用按钮说明
ElevatedButton.styleFrom()ElevatedButton有阴影的按钮样式
FilledButton.styleFrom()FilledButton纯色填充样式
OutlinedButton.styleFrom()OutlinedButton边框按钮样式
TextButton.styleFrom()TextButton文字按钮样式

styleFrom 常用参数

参数类型说明
backgroundColorColor?背景色
foregroundColorColor?前景色(文字、图标、水波纹)
disabledBackgroundColorColor?禁用状态背景色
disabledForegroundColorColor?禁用状态前景色
elevationdouble?阴影高度
paddingEdgeInsetsGeometry?内边距
shapeOutlinedBorder?形状
sideBorderSide?边框
textStyleTextStyle?文字样式
minimumSizeSize?最小尺寸
fixedSizeSize?固定尺寸
maximumSizeSize?最大尺寸
shadowColorColor?阴影颜色
visualDensityVisualDensity?视觉密度(紧凑/标准/舒适)

按钮类型对比速查

特性ElevatedButtonFilledButtonOutlinedButtonTextButtonIconButton
背景有(带阴影)有(纯色填充)
边框
视觉权重
典型场景CTA/确认CTA/确认次要操作对话框/工具栏工具栏/卡片
M3 推荐-✅ 主要操作✅ 次要操作✅ 低优先级✅ 图标操作

快速示例

以下示例都需要在文件顶部添加 import 'package:flutter/material.dart';

基本按钮

dart
import 'package:flutter/material.dart';

class ButtonTypesExample extends StatelessWidget {
  const ButtonTypesExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('按钮类型')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 主要操作按钮
            // ─── ★ 各按钮类型 ──────────────
            ElevatedButton(
              onPressed: () {},
              child: const Text('Elevated'),
            ),
            // ─── ☆ 各按钮类型 ──────────────
            const SizedBox(height: 12),
            // M3 推荐的主要按钮
            FilledButton(
              onPressed: () {},
              child: const Text('Filled'),
            ),
            const SizedBox(height: 12),
            // 次要操作按钮
            OutlinedButton(
              onPressed: () {},
              child: const Text('Outlined'),
            ),
            const SizedBox(height: 12),
            // 文字按钮
            TextButton(
              onPressed: () {},
              child: const Text('Text'),
            ),
          ],
        ),
      ),
    );
  }
}

带图标的按钮

dart
import 'package:flutter/material.dart';

class IconButtonExample extends StatelessWidget {
  const IconButtonExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('带图标按钮')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 方式1:使用 .icon 构造函数
            ElevatedButton.icon(
              onPressed: () {},
              icon: const Icon(Icons.add),
              label: const Text('添加'),
            ),
            const SizedBox(height: 12),
            // 图标按钮
            IconButton(
              onPressed: () {},
              icon: const Icon(Icons.favorite),
              color: Colors.red,
              tooltip: '收藏',
              iconSize: 28,
            ),
          ],
        ),
      ),
    );
  }
}

浮动操作按钮 (FAB)

dart
import 'package:flutter/material.dart';

class FabExample extends StatelessWidget {
  const FabExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('FAB 示例')),
      body: const Center(child: Text('FAB 示例')),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    );
  }
}

自定义样式

dart
import 'package:flutter/material.dart';

class CustomStyleButtonExample extends StatelessWidget {
  const CustomStyleButtonExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('自定义按钮样式')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {},
          // ─── ★ styleFrom 自定义样式 ──────────────
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.deepPurple,
            foregroundColor: Colors.white,
            elevation: 8,
            padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
            textStyle: const TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          // ─── ☆ styleFrom 自定义样式 ──────────────
          child: const Text('自定义按钮'),
        ),
      ),
    );
  }
}

禁用状态

dart
import 'package:flutter/material.dart';

class DisabledButtonExample extends StatefulWidget {
  const DisabledButtonExample({super.key});

  @override
  State<DisabledButtonExample> createState() => _DisabledButtonExampleState();
}

class _DisabledButtonExampleState extends State<DisabledButtonExample> {
  bool _isEnabled = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('按钮禁用状态')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              // ─── ★ null 禁用按钮 ──────────────
              onPressed: _isEnabled ? () => print('提交') : null,
              // ─── ☆ null 禁用按钮 ──────────────
              child: const Text('提交'),
            ),
            const SizedBox(height: 16),
            SwitchListTile(
              title: const Text('启用按钮'),
              value: _isEnabled,
              onChanged: (value) => setState(() => _isEnabled = value),
            ),
          ],
        ),
      ),
    );
  }
}

常见错误

1. 按钮无限宽度

dart
// ❌ 错误:按钮默认会撑满可用宽度(在 Row 中不会,在 Column 中可能)
Column(
  children: [
    ElevatedButton(...),  // 可能撑满宽度
  ],
)

// ✅ 修复:使用 Align 或 SizedBox 限制宽度
Column(
  children: [
    SizedBox(
      width: double.infinity,
      child: ElevatedButton(...),
    ),
  ],
)

2. Row 中多个按钮溢出

dart
// ❌ 错误:Row 中多个按钮未用 Expanded 包裹
Row(
  children: [
    ElevatedButton(...),
    ElevatedButton(...),  // 可能溢出
  ],
)

// ✅ 修复:使用 Expanded
Row(
  children: [
    Expanded(child: ElevatedButton(...)),
    SizedBox(width: 16),
    Expanded(child: ElevatedButton(...)),
  ],
)

3. 同一页面多个 FAB 的 heroTag 冲突

dart
// ❌ 错误:同一页面多个 FAB 未设置 heroTag,导航时会报错
FloatingActionButton(onPressed: () {}, child: Icon(Icons.add)),
FloatingActionButton(onPressed: () {}, child: Icon(Icons.edit)),

// ✅ 修复:为每个 FAB 设置不同的 heroTag
FloatingActionButton(
  heroTag: 'add',
  onPressed: () {},
  child: Icon(Icons.add),
),
FloatingActionButton(
  heroTag: 'edit',
  onPressed: () {},
  child: Icon(Icons.edit),
),

基于 Flutter 官方文档整理