您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

351 行
13 KiB

using System;
using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler2;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace Unity.UIWidgets.material {
static class SnackBarUtils {
public const float _singleLineVerticalPadding = 14.0f;
public static readonly TimeSpan _snackBarTransitionDuration = new TimeSpan(0, 0, 0, 0, 250);
public static readonly TimeSpan _snackBarDisplayDuration = new TimeSpan(0, 0, 0, 0, 4000);
public static readonly Curve _snackBarHeightCurve = Curves.fastOutSlowIn;
public static readonly Curve _snackBarFadeInCurve = new Interval(0.45f, 1.0f, curve: Curves.fastOutSlowIn);
public static readonly Curve _snackBarFadeOutCurve = new Interval(0.72f, 1.0f, curve: Curves.fastOutSlowIn);
}
public enum SnackBarClosedReason {
action,
dismiss,
swipe,
hide,
remove,
timeout
}
public class SnackBarAction : StatefulWidget {
public SnackBarAction(
Key key = null,
Color textColor = null,
Color disabledTextColor = null,
string label = null,
VoidCallback onPressed = null
) : base(key: key) {
D.assert(label != null);
D.assert(onPressed != null);
this.textColor = textColor;
this.disabledTextColor = disabledTextColor;
this.label = label;
this.onPressed = onPressed;
}
public readonly Color textColor;
public readonly Color disabledTextColor;
public readonly string label;
public readonly VoidCallback onPressed;
public override State createState() {
return new _SnackBarActionState();
}
}
class _SnackBarActionState : State<SnackBarAction> {
bool _haveTriggeredAction = false;
void _handlePressed() {
if (_haveTriggeredAction) {
return;
}
setState(() => { _haveTriggeredAction = true; });
widget.onPressed();
Scaffold.of(context).hideCurrentSnackBar(reason: SnackBarClosedReason.action);
}
public override Widget build(BuildContext context) {
SnackBarThemeData snackBarTheme = Theme.of(context).snackBarTheme;
Color textColor = widget.textColor ?? snackBarTheme.actionTextColor;
Color disabledTextColor = widget.disabledTextColor ?? snackBarTheme.disabledActionTextColor;
return new FlatButton(
onPressed: _haveTriggeredAction ? (VoidCallback) null : _handlePressed,
child: new Text(widget.label),
textColor: textColor,
disabledTextColor: disabledTextColor
);
}
}
public class SnackBar : StatefulWidget {
public SnackBar(
Key key = null,
Widget content = null,
Color backgroundColor = null,
float? elevation = null,
ShapeBorder shape = null,
SnackBarBehavior? behavior = null,
SnackBarAction action = null,
TimeSpan? duration = null,
Animation<float> animation = null,
VoidCallback onVisible = null
) : base(key: key) {
duration = duration ?? SnackBarUtils._snackBarDisplayDuration;
D.assert(content != null);
D.assert(elevation == null || elevation >= 0.0);
this.content = content;
this.backgroundColor = backgroundColor;
this.elevation = elevation;
this.shape = shape;
this.behavior = behavior;
this.action = action;
this.duration = duration.Value;
this.animation = animation;
this.onVisible = onVisible;
}
public readonly Widget content;
public readonly Color backgroundColor;
public readonly float? elevation;
public readonly ShapeBorder shape;
public readonly SnackBarBehavior? behavior;
public readonly SnackBarAction action;
public readonly TimeSpan duration;
public readonly Animation<float> animation;
public readonly VoidCallback onVisible;
internal static AnimationController createAnimationController(TickerProvider vsync) {
return new AnimationController(
duration: SnackBarUtils._snackBarTransitionDuration,
debugLabel: "SnackBar",
vsync: vsync
);
}
internal SnackBar withAnimation(Animation<float> newAnimation, Key fallbackKey = null) {
return new SnackBar(
key: key ?? fallbackKey,
content: content,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
behavior: behavior,
action: action,
duration: duration,
animation: newAnimation,
onVisible: onVisible
);
}
public override State createState() {
return new _SnackBarState();
}
}
class _SnackBarState : State<SnackBar> {
bool _wasVisible = false;
public override void initState() {
base.initState();
widget.animation.addStatusListener(_onAnimationStatusChanged);
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
var _oldWidget = (SnackBar) oldWidget;
if (widget.animation != _oldWidget.animation) {
_oldWidget.animation.removeStatusListener(_onAnimationStatusChanged);
widget.animation.addStatusListener(_onAnimationStatusChanged);
}
base.didUpdateWidget(oldWidget);
}
public override void dispose() {
widget.animation.removeStatusListener(_onAnimationStatusChanged);
base.dispose();
}
void _onAnimationStatusChanged(AnimationStatus animationStatus) {
switch (animationStatus) {
case AnimationStatus.dismissed:
case AnimationStatus.forward:
case AnimationStatus.reverse:
break;
case AnimationStatus.completed:
if (widget.onVisible != null && !_wasVisible) {
widget.onVisible();
}
_wasVisible = true;
break;
}
}
public override Widget build(BuildContext context) {
MediaQueryData mediaQueryData = MediaQuery.of(context);
D.assert(widget.animation != null);
ThemeData theme = Theme.of(context);
ColorScheme colorScheme = theme.colorScheme;
SnackBarThemeData snackBarTheme = theme.snackBarTheme;
bool isThemeDark = theme.brightness == Brightness.dark;
Brightness brightness = isThemeDark ? Brightness.light : Brightness.dark;
Color themeBackgroundColor = isThemeDark
? colorScheme.onSurface
: Color.alphaBlend(colorScheme.onSurface.withOpacity(0.80f), colorScheme.surface);
ThemeData inverseTheme = new ThemeData(
brightness: brightness,
backgroundColor: themeBackgroundColor,
colorScheme: new ColorScheme(
primary: colorScheme.onPrimary,
primaryVariant: colorScheme.onPrimary,
secondary: isThemeDark ? colorScheme.primaryVariant : colorScheme.secondary,
secondaryVariant: colorScheme.onSecondary,
surface: colorScheme.onSurface,
background: themeBackgroundColor,
error: colorScheme.onError,
onPrimary: colorScheme.primary,
onSecondary: colorScheme.secondary,
onSurface: colorScheme.surface,
onBackground: colorScheme.background,
onError: colorScheme.error,
brightness: brightness
),
snackBarTheme: snackBarTheme
);
TextStyle contentTextStyle = snackBarTheme.contentTextStyle ?? inverseTheme.textTheme.subtitle1;
SnackBarBehavior snackBarBehavior = widget.behavior ?? snackBarTheme.behavior ?? SnackBarBehavior.fix;
bool isFloatingSnackBar = snackBarBehavior == SnackBarBehavior.floating;
float snackBarPadding = isFloatingSnackBar ? 16.0f : 24.0f;
CurvedAnimation heightAnimation =
new CurvedAnimation(parent: widget.animation, curve: SnackBarUtils._snackBarHeightCurve);
CurvedAnimation fadeInAnimation =
new CurvedAnimation(parent: widget.animation, curve: SnackBarUtils._snackBarFadeInCurve);
CurvedAnimation fadeOutAnimation = new CurvedAnimation(
parent: widget.animation,
curve: SnackBarUtils._snackBarFadeOutCurve,
reverseCurve: new Threshold(0.0f)
);
var childrenList = new List<Widget>() {
new SizedBox(width: snackBarPadding),
new Expanded(
child: new Container(
padding: EdgeInsets.symmetric(vertical: SnackBarUtils._singleLineVerticalPadding),
child: new DefaultTextStyle(
style: contentTextStyle,
child: widget.content
)
)
)
};
if (widget.action != null) {
childrenList.Add(new ButtonTheme(
textTheme: ButtonTextTheme.accent,
minWidth: 64.0f,
padding: EdgeInsets.symmetric(horizontal: snackBarPadding),
child: widget.action
));
}
else {
childrenList.Add(new SizedBox(width: snackBarPadding));
}
Widget snackBar = new SafeArea(
top: false,
bottom: !isFloatingSnackBar,
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: childrenList
)
);
float elevation = widget.elevation ?? snackBarTheme.elevation ?? 6.0f;
Color backgroundColor =
widget.backgroundColor ?? snackBarTheme.backgroundColor ?? inverseTheme.backgroundColor;
ShapeBorder shape = widget.shape
?? snackBarTheme.shape
?? (isFloatingSnackBar
? new RoundedRectangleBorder(borderRadius: BorderRadius.circular(4.0f))
: null);
snackBar = new Material(
shape: shape,
elevation: elevation,
color: backgroundColor,
child: new Theme(
data: inverseTheme,
child: mediaQueryData.accessibleNavigation
? snackBar
: new FadeTransition(
opacity: fadeOutAnimation,
child: snackBar
)
)
);
if (isFloatingSnackBar) {
snackBar = new Padding(
padding: EdgeInsets.fromLTRB(15.0f, 5.0f, 15.0f, 10.0f),
child: snackBar
);
}
snackBar = new Dismissible(
key: Key.key("dismissible"),
direction: DismissDirection.down,
resizeDuration: null,
onDismissed: (DismissDirection? direction) => {
Scaffold.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.swipe);
},
child: snackBar
);
Widget snackBarTransition = null;
if (mediaQueryData.accessibleNavigation) {
snackBarTransition = snackBar;
}
else if (isFloatingSnackBar) {
snackBarTransition = new FadeTransition(
opacity: fadeInAnimation,
child: snackBar
);
}
else {
snackBarTransition = new AnimatedBuilder(
animation: heightAnimation,
builder: (BuildContext subContext, Widget subChild) => {
return new Align(
alignment: AlignmentDirectional.topStart,
heightFactor: heightAnimation.value,
child: subChild
);
},
child: snackBar
);
}
return new ClipRect(child: snackBarTransition);
}
}
}