Flutter 如何在小吃条上添加边距或填充?
我一直致力于Snackbar,并在我的项目中取得了成功。然而,有一点我想添加到Snackbar中,那就是Flutter 如何在小吃条上添加边距或填充?,flutter,material-design,snackbar,Flutter,Material Design,Snackbar,我一直致力于Snackbar,并在我的项目中取得了成功。然而,有一点我想添加到Snackbar中,那就是边距。我在这个链接中看到: 我真的希望我的Snackbar像这样: 我现在得到的是: 我的代码是: final snackBar = SnackBar( content: Text("Feild(s) are empty!"), duration: new Duration(seconds: 1), backgroundColor: Theme.
边距。我在这个链接中看到:
我真的希望我的Snackbar像这样:
我现在得到的是:
我的代码是:
final snackBar = SnackBar(
content: Text("Feild(s) are empty!"),
duration: new Duration(seconds: 1),
backgroundColor: Theme.of(context).primaryColor,
);
Scaffold.of(context).showSnackBar(snackBar);
}
遗憾的是,我还没有找到任何选项或可能性,由flift提供,来实现一个圆形的SnackBar
如果您确实需要/想要圆角和间距,您可以复制SnackBar
的源代码,并对副本进行调整。记住将实现SnackBar
添加到类定义中
我已经开始实施并添加了圆角。您只需为iPhone等手机添加底部填充物,底部有元素,遮挡了视图。(要获得底部间距,可以使用MediaQuery.of(context.viewInsets.bottom
)
您可以复制的独立示例:
main.dart
import 'package:flutter/material.dart';
import 'package:your_app_name/my_snack.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MyBody()
),
);
}
}
class MyBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(onPressed: () {
Scaffold.of(context).showSnackBar(MySnack(content: Text('MySnack!')));
}),
);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
const double _kSnackBarPadding = 24.0;
const double _kSingleLineVerticalPadding = 14.0;
const Color _kSnackBackground = Color(0xFF323232);
// TODO(ianh): We should check if the given text and actions are going to fit on
// one line or not, and if they are, use the single-line layout, and if not, use
// the multiline layout. See link above.
// TODO(ianh): Implement the Tablet version of snackbar if we're "on a tablet".
const Duration _kSnackBarTransitionDuration = Duration(milliseconds: 250);
const Duration _kSnackBarDisplayDuration = Duration(milliseconds: 4000);
const Curve _snackBarHeightCurve = Curves.fastOutSlowIn;
const Curve _snackBarFadeCurve = Interval(0.72, 1.0, curve: Curves.fastOutSlowIn);
/// Specify how a [SnackBar] was closed.
///
/// The [ScaffoldState.showSnackBar] function returns a
/// [ScaffoldFeatureController]. The value of the controller's closed property
/// is a Future that resolves to a SnackBarClosedReason. Applications that need
/// to know how a snackbar was closed can use this value.
///
/// Example:
///
/// ```dart
/// Scaffold.of(context).showSnackBar(
/// SnackBar( ... )
/// ).closed.then((SnackBarClosedReason reason) {
/// ...
/// });
/// ```
/// A button for a [SnackBar], known as an "action".
///
/// Snack bar actions are always enabled. If you want to disable a snack bar
/// action, simply don't include it in the snack bar.
///
/// Snack bar actions can only be pressed once. Subsequent presses are ignored.
///
/// See also:
///
/// * [SnackBar]
/// * <https://material.io/design/components/snackbars.html>
class _SnackBarActionState extends State<SnackBarAction> {
bool _haveTriggeredAction = false;
void _handlePressed() {
if (_haveTriggeredAction)
return;
setState(() {
_haveTriggeredAction = true;
});
widget.onPressed();
Scaffold.of(context).hideCurrentSnackBar(reason: SnackBarClosedReason.action);
}
@override
Widget build(BuildContext context) {
return FlatButton(
onPressed: _haveTriggeredAction ? null : _handlePressed,
child: Text(widget.label),
textColor: widget.textColor,
disabledTextColor: widget.disabledTextColor,
);
}
}
/// A lightweight message with an optional action which briefly displays at the
/// bottom of the screen.
///
/// To display a snack bar, call `Scaffold.of(context).showSnackBar()`, passing
/// an instance of [SnackBar] that describes the message.
///
/// To control how long the [SnackBar] remains visible, specify a [duration].
///
/// A SnackBar with an action will not time out when TalkBack or VoiceOver are
/// enabled. This is controlled by [AccessibilityFeatures.accessibleNavigation].
///
/// See also:
///
/// * [Scaffold.of], to obtain the current [ScaffoldState], which manages the
/// display and animation of snack bars.
/// * [ScaffoldState.showSnackBar], which displays a [SnackBar].
/// * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the currently
/// displayed snack bar, if any, and allows the next to be displayed.
/// * [SnackBarAction], which is used to specify an [action] button to show
/// on the snack bar.
/// * <https://material.io/design/components/snackbars.html>
class MySnack extends StatelessWidget implements SnackBar {
/// Creates a snack bar.
///
/// The [content] argument must be non-null.
const MySnack({
Key key,
@required this.content,
this.backgroundColor,
this.action,
this.duration = _kSnackBarDisplayDuration,
this.animation,
}) : assert(content != null),
assert(duration != null),
super(key: key);
/// The primary content of the snack bar.
///
/// Typically a [Text] widget.
final Widget content;
/// The Snackbar's background color. By default the color is dark grey.
final Color backgroundColor;
/// (optional) An action that the user can take based on the snack bar.
///
/// For example, the snack bar might let the user undo the operation that
/// prompted the snackbar. Snack bars can have at most one action.
///
/// The action should not be "dismiss" or "cancel".
final SnackBarAction action;
/// The amount of time the snack bar should be displayed.
///
/// Defaults to 4.0s.
///
/// See also:
///
/// * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the
/// currently displayed snack bar, if any, and allows the next to be
/// displayed.
/// * <https://material.io/design/components/snackbars.html>
final Duration duration;
/// The animation driving the entrance and exit of the snack bar.
final Animation<double> animation;
@override
Widget build(BuildContext context) {
final MediaQueryData mediaQueryData = MediaQuery.of(context);
assert(animation != null);
final ThemeData theme = Theme.of(context);
final ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
accentColor: theme.accentColor,
accentColorBrightness: theme.accentColorBrightness,
);
final List<Widget> children = <Widget>[
const SizedBox(width: _kSnackBarPadding),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(vertical: _kSingleLineVerticalPadding),
child: DefaultTextStyle(
style: darkTheme.textTheme.subhead,
child: content,
),
),
),
];
if (action != null) {
children.add(ButtonTheme.bar(
padding: const EdgeInsets.symmetric(horizontal: _kSnackBarPadding),
textTheme: ButtonTextTheme.accent,
child: action,
));
} else {
children.add(const SizedBox(width: _kSnackBarPadding));
}
final CurvedAnimation heightAnimation = CurvedAnimation(parent: animation, curve: _snackBarHeightCurve);
final CurvedAnimation fadeAnimation = CurvedAnimation(parent: animation, curve: _snackBarFadeCurve, reverseCurve: const Threshold(0.0));
Widget snackbar = SafeArea(
bottom: false,
top: false,
child: Row(
children: children,
crossAxisAlignment: CrossAxisAlignment.center,
),
);
snackbar = Semantics(
container: true,
liveRegion: true,
onDismiss: () {
Scaffold.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.dismiss);
},
child: Dismissible(
key: const Key('dismissible'),
direction: DismissDirection.down,
resizeDuration: null,
onDismissed: (DismissDirection direction) {
Scaffold.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.swipe);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: backgroundColor ?? _kSnackBackground,
borderRadius: BorderRadius.circular(8.0)
),
child: Material(
elevation: 6.0,
color: Colors.transparent,
child: Theme(
data: darkTheme,
child: mediaQueryData.accessibleNavigation ? snackbar : FadeTransition(
opacity: fadeAnimation,
child: snackbar,
),
),
),
),
),
),
);
return ClipRect(
child: mediaQueryData.accessibleNavigation ? snackbar : AnimatedBuilder(
animation: heightAnimation,
builder: (BuildContext context, Widget child) {
return Align(
alignment: AlignmentDirectional.topStart,
heightFactor: heightAnimation.value,
child: child,
);
},
child: snackbar,
),
);
}
// API for Scaffold.addSnackBar():
/// Creates an animation controller useful for driving a snack bar's entrance and exit animation.
static AnimationController createAnimationController({ @required TickerProvider vsync }) {
return AnimationController(
duration: _kSnackBarTransitionDuration,
debugLabel: 'SnackBar',
vsync: vsync,
);
}
/// Creates a copy of this snack bar but with the animation replaced with the given animation.
///
/// If the original snack bar lacks a key, the newly created snack bar will
/// use the given fallback key.
SnackBar withAnimation(Animation<double> newAnimation, { Key fallbackKey }) {
return MySnack(
key: key ?? fallbackKey,
content: content,
backgroundColor: backgroundColor,
action: action,
duration: duration,
animation: newAnimation,
);
}
}
我的零食。飞镖
import 'package:flutter/material.dart';
import 'package:your_app_name/my_snack.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MyBody()
),
);
}
}
class MyBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(onPressed: () {
Scaffold.of(context).showSnackBar(MySnack(content: Text('MySnack!')));
}),
);
}
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
const double _kSnackBarPadding = 24.0;
const double _kSingleLineVerticalPadding = 14.0;
const Color _kSnackBackground = Color(0xFF323232);
// TODO(ianh): We should check if the given text and actions are going to fit on
// one line or not, and if they are, use the single-line layout, and if not, use
// the multiline layout. See link above.
// TODO(ianh): Implement the Tablet version of snackbar if we're "on a tablet".
const Duration _kSnackBarTransitionDuration = Duration(milliseconds: 250);
const Duration _kSnackBarDisplayDuration = Duration(milliseconds: 4000);
const Curve _snackBarHeightCurve = Curves.fastOutSlowIn;
const Curve _snackBarFadeCurve = Interval(0.72, 1.0, curve: Curves.fastOutSlowIn);
/// Specify how a [SnackBar] was closed.
///
/// The [ScaffoldState.showSnackBar] function returns a
/// [ScaffoldFeatureController]. The value of the controller's closed property
/// is a Future that resolves to a SnackBarClosedReason. Applications that need
/// to know how a snackbar was closed can use this value.
///
/// Example:
///
/// ```dart
/// Scaffold.of(context).showSnackBar(
/// SnackBar( ... )
/// ).closed.then((SnackBarClosedReason reason) {
/// ...
/// });
/// ```
/// A button for a [SnackBar], known as an "action".
///
/// Snack bar actions are always enabled. If you want to disable a snack bar
/// action, simply don't include it in the snack bar.
///
/// Snack bar actions can only be pressed once. Subsequent presses are ignored.
///
/// See also:
///
/// * [SnackBar]
/// * <https://material.io/design/components/snackbars.html>
class _SnackBarActionState extends State<SnackBarAction> {
bool _haveTriggeredAction = false;
void _handlePressed() {
if (_haveTriggeredAction)
return;
setState(() {
_haveTriggeredAction = true;
});
widget.onPressed();
Scaffold.of(context).hideCurrentSnackBar(reason: SnackBarClosedReason.action);
}
@override
Widget build(BuildContext context) {
return FlatButton(
onPressed: _haveTriggeredAction ? null : _handlePressed,
child: Text(widget.label),
textColor: widget.textColor,
disabledTextColor: widget.disabledTextColor,
);
}
}
/// A lightweight message with an optional action which briefly displays at the
/// bottom of the screen.
///
/// To display a snack bar, call `Scaffold.of(context).showSnackBar()`, passing
/// an instance of [SnackBar] that describes the message.
///
/// To control how long the [SnackBar] remains visible, specify a [duration].
///
/// A SnackBar with an action will not time out when TalkBack or VoiceOver are
/// enabled. This is controlled by [AccessibilityFeatures.accessibleNavigation].
///
/// See also:
///
/// * [Scaffold.of], to obtain the current [ScaffoldState], which manages the
/// display and animation of snack bars.
/// * [ScaffoldState.showSnackBar], which displays a [SnackBar].
/// * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the currently
/// displayed snack bar, if any, and allows the next to be displayed.
/// * [SnackBarAction], which is used to specify an [action] button to show
/// on the snack bar.
/// * <https://material.io/design/components/snackbars.html>
class MySnack extends StatelessWidget implements SnackBar {
/// Creates a snack bar.
///
/// The [content] argument must be non-null.
const MySnack({
Key key,
@required this.content,
this.backgroundColor,
this.action,
this.duration = _kSnackBarDisplayDuration,
this.animation,
}) : assert(content != null),
assert(duration != null),
super(key: key);
/// The primary content of the snack bar.
///
/// Typically a [Text] widget.
final Widget content;
/// The Snackbar's background color. By default the color is dark grey.
final Color backgroundColor;
/// (optional) An action that the user can take based on the snack bar.
///
/// For example, the snack bar might let the user undo the operation that
/// prompted the snackbar. Snack bars can have at most one action.
///
/// The action should not be "dismiss" or "cancel".
final SnackBarAction action;
/// The amount of time the snack bar should be displayed.
///
/// Defaults to 4.0s.
///
/// See also:
///
/// * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the
/// currently displayed snack bar, if any, and allows the next to be
/// displayed.
/// * <https://material.io/design/components/snackbars.html>
final Duration duration;
/// The animation driving the entrance and exit of the snack bar.
final Animation<double> animation;
@override
Widget build(BuildContext context) {
final MediaQueryData mediaQueryData = MediaQuery.of(context);
assert(animation != null);
final ThemeData theme = Theme.of(context);
final ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
accentColor: theme.accentColor,
accentColorBrightness: theme.accentColorBrightness,
);
final List<Widget> children = <Widget>[
const SizedBox(width: _kSnackBarPadding),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(vertical: _kSingleLineVerticalPadding),
child: DefaultTextStyle(
style: darkTheme.textTheme.subhead,
child: content,
),
),
),
];
if (action != null) {
children.add(ButtonTheme.bar(
padding: const EdgeInsets.symmetric(horizontal: _kSnackBarPadding),
textTheme: ButtonTextTheme.accent,
child: action,
));
} else {
children.add(const SizedBox(width: _kSnackBarPadding));
}
final CurvedAnimation heightAnimation = CurvedAnimation(parent: animation, curve: _snackBarHeightCurve);
final CurvedAnimation fadeAnimation = CurvedAnimation(parent: animation, curve: _snackBarFadeCurve, reverseCurve: const Threshold(0.0));
Widget snackbar = SafeArea(
bottom: false,
top: false,
child: Row(
children: children,
crossAxisAlignment: CrossAxisAlignment.center,
),
);
snackbar = Semantics(
container: true,
liveRegion: true,
onDismiss: () {
Scaffold.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.dismiss);
},
child: Dismissible(
key: const Key('dismissible'),
direction: DismissDirection.down,
resizeDuration: null,
onDismissed: (DismissDirection direction) {
Scaffold.of(context).removeCurrentSnackBar(reason: SnackBarClosedReason.swipe);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
color: backgroundColor ?? _kSnackBackground,
borderRadius: BorderRadius.circular(8.0)
),
child: Material(
elevation: 6.0,
color: Colors.transparent,
child: Theme(
data: darkTheme,
child: mediaQueryData.accessibleNavigation ? snackbar : FadeTransition(
opacity: fadeAnimation,
child: snackbar,
),
),
),
),
),
),
);
return ClipRect(
child: mediaQueryData.accessibleNavigation ? snackbar : AnimatedBuilder(
animation: heightAnimation,
builder: (BuildContext context, Widget child) {
return Align(
alignment: AlignmentDirectional.topStart,
heightFactor: heightAnimation.value,
child: child,
);
},
child: snackbar,
),
);
}
// API for Scaffold.addSnackBar():
/// Creates an animation controller useful for driving a snack bar's entrance and exit animation.
static AnimationController createAnimationController({ @required TickerProvider vsync }) {
return AnimationController(
duration: _kSnackBarTransitionDuration,
debugLabel: 'SnackBar',
vsync: vsync,
);
}
/// Creates a copy of this snack bar but with the animation replaced with the given animation.
///
/// If the original snack bar lacks a key, the newly created snack bar will
/// use the given fallback key.
SnackBar withAnimation(Animation<double> newAnimation, { Key fallbackKey }) {
return MySnack(
key: key ?? fallbackKey,
content: content,
backgroundColor: backgroundColor,
action: action,
duration: duration,
animation: newAnimation,
);
}
}
//Chromium作者版权所有。版权所有。
//此源代码的使用受BSD样式许可证的约束,该许可证可以
//在许可证文件中找到。
导入“package:flatter/rendering.dart”;
导入“package:flatter/widgets.dart”;
进口“包装:颤振/材料.省道”;
常数double _kSnackBarPadding=24.0;
常数double _kSingleLineVerticalPadding=14.0;
const Color _kSnackBackground=Color(0xFF323232);
//TODO(ianh):我们应该检查给定的文本和操作是否适合
//是否为单线,如果为单线布局,则使用单线布局;如果不是单线布局,则使用单线布局
//多行布局。见上面的链接。
//TODO(ianh):如果我们“在平板电脑上”,就实现snackbar的平板电脑版本。
const Duration _kSnackBarTransitionDuration=持续时间(毫秒:250);
const Duration _kSnackBarDisplayDuration=持续时间(毫秒:4000);
常数曲线_snackBarHeightCurve=曲线.fastoutswowin;
常数曲线_snackBarFadeCurve=区间(0.72,1.0,曲线:Curves.fastoutswowin);
///指定[SnackBar]是如何关闭的。
///
///[ScaffoldState.showSnackBar]函数返回一个
///[脚手架功能控制器]。控制器的closed属性的值
///这是一个注定要失败的未来。需要
///要知道snackbar是如何关闭的,可以使用此值。
///
///例如:
///
///“飞镖
///Scaffold.of(上下文).showSnackBar(
///SnackBar(…)
///)。关闭。然后((SnackBarClosedReason原因){
/// ...
/// });
/// ```
///一个[快捷键]的按钮,称为“动作”。
///
///快餐店操作始终处于启用状态。如果你想禁用快餐店
///行动,只是不包括在快餐店。
///
///快餐店操作只能按一次。随后的压力机将被忽略。
///
///另见:
///
///*[SnackBar]
/// *
类_SnackBarActionState扩展状态{
bool _haveTriggeredAction=false;
有扶手的{
如果(_haveTriggeredAction)
返回;
设置状态(){
_haveTriggeredAction=true;
});
onPressed();
Scaffold.of(context).hideCurrentSnackBar(原因:SnackBarClosedReason.action);
}
@凌驾
小部件构建(构建上下文){
返回按钮(
onPressed:\u haveTriggeredAction?null:\u handlePressed,
子项:文本(widget.label),
textColor:widget.textColor,
disabledTextColor:widget.disabledTextColor,
);
}
}
///带有可选操作的轻量级消息,在
///屏幕底部。
///
///要显示快餐店,请调用`Scaffold.of(context).showSnackBar()`,传递
///描述消息的[SnackBar]实例。
///
///要控制[SnackBar]保持可见的时间,请指定[duration]。
///
///当使用对讲或画外音时,带有动作的SnackBar不会超时
///启用。这由[AccessibilityFeatures.AccessibileEnableAgation]控制。
///
///另见:
///
///*[Scaffold.of],以获取当前的[ScaffoldState],该状态管理
///小吃店的展示和动画。
///*[ScaffoldState.showSnackBar],其中显示一个[SnackBar]。
///*[ScaffoldState.removeCurrentSnackBar],它会突然隐藏当前
///显示的快餐店(如果有),并允许显示下一个。
///*[SnackBarAction],用于指定要显示的[action]按钮
///在快餐店。
/// *
类MySnack扩展无状态widget实现SnackBar{
///创建一个快餐店。
///
///[content]参数必须为非null。
康斯特迈斯纳克({
关键点,
@需要这个内容,
这个背景色,
这个行动,,
this.duration=\u ksnackbardisplayeduration,
这个,动画,
}):assert(内容!=null),
断言(持续时间!=null),
超级(键:键);
///小吃店的主要内容。
///
///通常是[文本]小部件。
最终小部件内容;
///Snackbar的背景色。默认情况下,颜色为深灰色。
最终颜色背景色;
///(可选)用户可以基于快餐店执行的操作。
///
///例如,快餐店可能允许用户撤消以下操作:
///提示小吃店。小吃店最多只能有一个操作。
///
///操作不应为“驳回”或“取消”。
最后的蛇行动;
///快餐店应显示的时间量。
///
///默认值为4.0s。
///
///另见:
///
///*[ScaffoldState.removeCurrentSnackBar],它会突然隐藏
///当前显示的快餐店(如果有),并允许下一个
///显示。
/// *
最后期限;
///驱动快餐店入口和出口的动画。
最终动画;
@凌驾
小部件构建(构建上下文){
final MediaQueryData MediaQueryData=MediaQuery.of(上下文);
final snackBar = SnackBar(
elevation: 6.0,
backgroundColor: Configs.current.COLORS_PRIMARY,
behavior: SnackBarBehavior.floating,
content: Text(
"Snack bar test",
style: TextStyle(color: Colors.white),
),
);
var snackbar = SnackBar(
content: Text('Hello World!'),
margin: EdgeInsets.all(20),
behavior: SnackBarBehavior.floating,
);
Scaffold.of(context).showSnackBar(snackbar);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Builder(builder: (context) {
return RaisedButton(
onPressed: () {
var snackbar = SnackBar(
content: Text('Hello World!'),
margin: EdgeInsets.all(20),
behavior: SnackBarBehavior.floating,
);
Scaffold.of(context).showSnackBar(snackbar);
},
child: Text('Show SnackBar'),
);
}),
),
);
}