一、源碼解讀
// ElevatedButton 繼承于 ButtonStyleButton
class ElevatedButton extends ButtonStyleButton {
// 創建一個按鈕
const ElevatedButton({
Key? key, // 標識
required VoidCallback? onPressed, // 按鈕的按壓事件的回調方法
VoidCallback? onLongPress, // 按鈕長按事件回調方法
ValueChanged<bool>? onHover, // 鼠標懸停事件的回調方法
ValueChanged<bool>? onFocusChange, // 按鈕焦點的變化回調事件方法
ButtonStyle? style, // 按鈕的樣式
FocusNode? focusNode, // 按鈕的焦點
bool autofocus = false, // 是否自動獲取焦點
Clip clipBehavior = Clip.none, // 按鈕的裁剪形式
required Widget? child, // 按鈕的子組件對象
}) : super(
key: key,
onPressed: onPressed,
onLongPress: onLongPress,
onHover: onHover,
onFocusChange: onFocusChange,
style: style,
focusNode: focusNode,
autofocus: autofocus,
clipBehavior: clipBehavior,
child: child,
);
/// 生成一個圖標和文字一排的按鈕
factory ElevatedButton.icon({
Key? key,
required VoidCallback? onPressed,
VoidCallback? onLongPress,
ValueChanged<bool>? onHover,
ValueChanged<bool>? onFocusChange,
ButtonStyle? style,
FocusNode? focusNode,
bool? autofocus,
Clip? clipBehavior,
required Widget icon, // 按鈕的圖標
required Widget label, // 按鈕的文字
}) = _ElevatedButtonWithIcon;
// 在給定值得情況下,便捷獲取按鈕樣式的方法
static ButtonStyle styleFrom({
Color? primary, // 按鈕的基本顏色
Color? onPrimary, // 按鈕獲取焦點的基本顏色
Color? onSurface, // 按鈕獲取焦點表面顏色
Color? shadowColor, // 按鈕陰影顏色
double? elevation, // 陰影 Z 軸大小設置
TextStyle? textStyle, // 按鈕文字樣式
EdgeInsetsGeometry? padding, // 按鈕的內邊距大小
Size? minimumSize, // 按鈕的最小尺寸
Size? fixedSize, // 按鈕的固定尺寸
Size? maximumSize, // 按鈕的最大尺寸
BorderSide? side, // 按鈕的邊框邊對象
OutlinedBorder? shape, // 按鈕輪廓邊框樣式
MouseCursor? enabledMouseCursor, // 啟用鼠標光標
MouseCursor? disabledMouseCursor, // 關閉鼠標光標
VisualDensity? visualDensity, // 按鈕的視覺密度
MaterialTapTargetSize? tapTargetSize, // 按鈕觸控區域大小
Duration? animationDuration, // 動畫時長
bool? enableFeedback, // 是否啟動反饋
AlignmentGeometry? alignment, // 按鈕的子組件的位置
InteractiveInkFeatureFactory? splashFactory, // 水波紋效果的設置
}) {
// 按鈕的背景色
final MaterialStateProperty<Color?>? backgroundColor = (onSurface == null && primary == null)
? null
: _ElevatedButtonDefaultBackground(primary, onSurface);
// 按鈕的前景色
final MaterialStateProperty<Color?>? foregroundColor = (onSurface == null && onPrimary == null)
? null
: _ElevatedButtonDefaultForeground(onPrimary, onSurface);
// 按鈕的疊加色
final MaterialStateProperty<Color?>? overlayColor = (onPrimary == null)
? null
: _ElevatedButtonDefaultOverlay(onPrimary);
// 按鈕 Z 軸陰影大小
final MaterialStateProperty<double>? elevationValue = (elevation == null)
? null
: _ElevatedButtonDefaultElevation(elevation);
// 光標的狀態
final MaterialStateProperty<MouseCursor?>? mouseCursor = (enabledMouseCursor == null && disabledMouseCursor == null)
? null
: _ElevatedButtonDefaultMouseCursor(enabledMouseCursor, disabledMouseCursor);
return ButtonStyle(
textStyle: MaterialStateProperty.all<TextStyle?>(textStyle),
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
overlayColor: overlayColor,
shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
elevation: elevationValue,
padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
fixedSize: ButtonStyleButton.allOrNull<Size>(fixedSize),
maximumSize: ButtonStyleButton.allOrNull<Size>(maximumSize),
side: ButtonStyleButton.allOrNull<BorderSide>(side),
shape: ButtonStyleButton.allOrNull<OutlinedBorder>(shape),
mouseCursor: mouseCursor,
visualDensity: visualDensity,
tapTargetSize: tapTargetSize,
animationDuration: animationDuration,
enableFeedback: enableFeedback,
alignment: alignment,
splashFactory: splashFactory,
);
}
/// 定義按鈕的默認外觀,重寫 ButtonStyleButton 的 defaultStyleOf方法
@override
ButtonStyle defaultStyleOf(BuildContext context) {
// 獲取系統主題
final ThemeData theme = Theme.of(context);
// 獲取系統主題顏色方案
final ColorScheme colorScheme = theme.colorScheme;
// 按鈕內邊距縮放填充
final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
const EdgeInsets.symmetric(horizontal: 16),
const EdgeInsets.symmetric(horizontal: 8),
const EdgeInsets.symmetric(horizontal: 4),
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1, // 系統文字縮放因子
);
return styleFrom(
primary: colorScheme.primary,
onPrimary: colorScheme.onPrimary,
onSurface: colorScheme.onSurface,
shadowColor: theme.shadowColor,
elevation: 2,
textStyle: theme.textTheme.button,
padding: scaledPadding,
minimumSize: const Size(64, 36),
maximumSize: Size.infinite,
// 圓角為4的矩形
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
enabledMouseCursor: SystemMouseCursors.click, // 啟用
disabledMouseCursor: SystemMouseCursors.forbidden, // 禁用
visualDensity: theme.visualDensity,
tapTargetSize: theme.materialTapTargetSize,
animationDuration: kThemeChangeDuration,
enableFeedback: true,
alignment: Alignment.center,
splashFactory: InkRipple.splashFactory,
);
}
/// 獲取 ElevatedButtonTheme 主題的樣式
@override
ButtonStyle? themeStyleOf(BuildContext context) {
return ElevatedButtonTheme.of(context).style;
}
}
二、實例
// 基本按鈕
ElevatedButton(
onPressed: () {},
child: Text('ElevatedButton 測試'),
)
// 圖片 + 文字按鈕 或者 文字 + 圖片
ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.abc),
label: Text('ElevatedButton 測試'),
)