show static method
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>
show(
- BuildContext context, {
- required String title,
- String? subtitle,
- Color? background,
- Gradient? gradient,
- Duration? duration,
- IconData? icon,
- Color? iconColor,
- VoidCallback? onActionPressed,
- String? actionLabel,
- SnackbarType? type,
- SnackbarPosition? position,
- SnackbarAnimation? animation,
- SnackbarAnimationDirection? startAnimation,
- SnackbarAnimationDirection? endAnimation,
- bool? showProgressIndicator,
- bool hideLikeCircle = false,
- bool? dismissible,
- bool? enableHapticFeedback,
- bool? dismissOnTap,
- double? maxWidth,
- EdgeInsets? margin,
- BorderRadius? borderRadius,
- Color? borderColor,
- double? borderWidth,
- VoidCallback? onDismissed,
- VoidCallback? onTap,
- ContentDesignStyle? designStyle,
- double? blur,
- ImageFilter? backdropFilter,
Shows a modern floating snackbar with enhanced features.
Returns a ScaffoldFeatureController that can be used to programmatically dismiss the snackbar.
Throws an AssertionError if title is empty.
Example:
final controller = SavePointsSnackbar.show(
context,
title: 'Notification',
subtitle: 'This is a snackbar',
type: SnackbarType.info,
);
Implementation
static ScaffoldFeatureController<SnackBar, SnackBarClosedReason> show(
BuildContext context, {
required String title,
String? subtitle,
Color? background,
Gradient? gradient,
Duration? duration,
IconData? icon,
Color? iconColor,
VoidCallback? onActionPressed,
String? actionLabel,
SnackbarType? type,
SnackbarPosition? position,
SnackbarAnimation? animation, // For backward compatibility
SnackbarAnimationDirection? startAnimation,
SnackbarAnimationDirection? endAnimation,
bool? showProgressIndicator,
bool hideLikeCircle = false,
bool? dismissible,
bool? enableHapticFeedback,
bool? dismissOnTap,
double? maxWidth,
EdgeInsets? margin,
BorderRadius? borderRadius,
Color? borderColor,
double? borderWidth,
VoidCallback? onDismissed,
VoidCallback? onTap,
/// Design style: [ContentDesignStyle.solid] (filled) or [ContentDesignStyle.outlined] (light bg + border).
ContentDesignStyle? designStyle,
/// Optional blur sigma for glassmorphism behind the snackbar. When null, no blur is applied.
double? blur,
/// Optional custom [ImageFilter] for the backdrop. When set, overrides [blur].
ImageFilter? backdropFilter,
}) {
// Validate required parameters
assert(title.isNotEmpty, 'Title cannot be empty');
final config = SnackDiaBottomConfig().snackbar;
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
final finalType = type ?? config.defaultType;
final finalDesignStyle = designStyle ?? config.defaultDesignStyle;
final colorConfig = SnackbarColorConfig(
theme: theme,
isDark: isDark,
background: background,
gradient: gradient,
iconColor: iconColor,
type: finalType,
config: config,
designStyle: finalDesignStyle,
);
final finalIcon = icon ?? colorConfig.defaultIcon;
final finalIconColor = iconColor ?? colorConfig.iconColor;
final finalPosition = position ?? config.defaultPosition;
// Use new animation system if startAnimation or endAnimation is provided
final finalAnimation = (startAnimation == null && endAnimation == null)
? (animation ?? config.defaultAnimation)
: null;
final finalDuration = duration ?? config.defaultDuration;
final finalMargin =
margin ?? config.defaultMargin ?? _getMargin(context, finalPosition);
final finalBorderRadius =
borderRadius ??
config.defaultBorderRadius ??
BorderRadius.circular(SnackbarConstants.borderRadius);
final finalMaxWidth =
maxWidth ?? config.maxWidth ?? SnackbarConstants.maxWidth;
final finalShowProgressIndicator =
showProgressIndicator ?? config.defaultShowProgressIndicator;
final finalDismissible = dismissible ?? config.defaultDismissible;
final finalEnableHapticFeedback =
enableHapticFeedback ?? config.defaultEnableHapticFeedback;
final finalDismissOnTap = dismissOnTap ?? config.defaultDismissOnTap;
final finalBorderWidth = borderWidth ?? config.defaultBorderWidth;
final finalBorderColor =
borderColor ??
config.defaultBorderColor ??
finalIconColor.withValues(alpha: 0.3);
if (finalEnableHapticFeedback) {
HapticFeedback.lightImpact();
}
// Use overlay for top position (SnackBar doesn't support top positioning well)
if (finalPosition == SnackbarPosition.top) {
TopSnackbarOverlay.show(
context,
title: title,
subtitle: subtitle,
icon: finalIcon,
iconColor: finalIconColor,
backgroundColor: colorConfig.backgroundColor,
gradient: colorConfig.gradient,
duration: finalDuration,
animation: finalAnimation,
startAnimation: startAnimation,
endAnimation: endAnimation,
type: finalType,
dismissible: finalDismissible,
dismissOnTap: finalDismissOnTap,
showProgressIndicator: finalShowProgressIndicator,
borderRadius: finalBorderRadius,
maxWidth: finalMaxWidth,
borderColor: finalDesignStyle == ContentDesignStyle.outlined
? colorConfig.borderColor
: (finalBorderWidth > 0 ? finalBorderColor : null),
borderWidth: finalDesignStyle == ContentDesignStyle.outlined
? 2
: finalBorderWidth,
onTap: onTap,
onDismissed: onDismissed,
blur: blur,
backdropFilter: backdropFilter,
designStyle: finalDesignStyle,
titleColor: colorConfig.titleColor,
subtitleColor: colorConfig.subtitleColor,
showCloseButton:
finalDesignStyle == ContentDesignStyle.outlined ||
finalDesignStyle == ContentDesignStyle.leftAccent ||
finalDesignStyle == ContentDesignStyle.tonal ||
finalDismissible,
);
// Return a dummy controller for top position. The overlay shows the real
// toast at top; we show a minimal SnackBar on-screen (required by Flutter
// to avoid "Floating SnackBar presented off screen") with 1ms duration
// so it dismisses immediately and is barely visible.
final dummyMargin = _getMargin(context, SnackbarPosition.bottom);
return ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const SizedBox.shrink(),
duration: const Duration(milliseconds: 1),
behavior: SnackBarBehavior.floating,
backgroundColor: Colors.transparent,
elevation: 0,
margin: dummyMargin,
),
);
}
// Remove any existing snackbar before showing a new one
final scaffoldMessenger = ScaffoldMessenger.of(context);
scaffoldMessenger.hideCurrentSnackBar();
// Use standard SnackBar for bottom position
final controller = scaffoldMessenger.showSnackBar(
SnackBar(
behavior: .floating,
duration: finalDuration,
margin: finalMargin,
shape: RoundedRectangleBorder(
borderRadius: finalBorderRadius,
side:
finalDesignStyle != ContentDesignStyle.outlined &&
finalBorderWidth > 0
? BorderSide(color: finalBorderColor, width: finalBorderWidth)
: BorderSide.none,
),
backgroundColor: Colors.transparent,
elevation: 0,
dismissDirection: finalDismissible
? DismissDirection.horizontal
: DismissDirection.none,
content: ModernSnackbarContent(
title: title,
subtitle: subtitle,
icon: finalIcon,
iconColor: finalIconColor,
backgroundColor: colorConfig.backgroundColor,
gradient: colorConfig.gradient,
showProgressIndicator: finalShowProgressIndicator,
duration: finalDuration,
type: finalType,
position: finalPosition,
animation: finalAnimation ?? SnackbarAnimation.fadeSlide,
borderRadius: finalBorderRadius,
maxWidth: finalMaxWidth,
dismissOnTap: finalDismissOnTap,
onTap: onTap,
blur: blur,
backdropFilter: backdropFilter,
designStyle: finalDesignStyle,
titleColor: colorConfig.titleColor,
subtitleColor: colorConfig.subtitleColor,
borderColor: finalDesignStyle == ContentDesignStyle.outlined
? colorConfig.borderColor
: null,
showCloseButton:
finalDesignStyle == ContentDesignStyle.outlined ||
finalDesignStyle == ContentDesignStyle.leftAccent ||
finalDesignStyle == ContentDesignStyle.tonal ||
finalDismissible,
),
action: onActionPressed != null && actionLabel != null
? SnackBarAction(
label: actionLabel.toUpperCase(),
textColor: Colors.white,
onPressed: () {
if (finalEnableHapticFeedback) {
HapticFeedback.mediumImpact();
}
ScaffoldMessenger.of(context).hideCurrentSnackBar();
onActionPressed();
},
)
: null,
),
);
controller.closed.then((reason) {
onDismissed?.call();
});
return controller;
}