我们如何在警告对话框中使用渐变颜色背景和固定宽度
How can we have Gradient Color background in alert dialog box and a fixed Width
我尝试使用
backgroundColor
但是我需要渐变色
showAlertDialog(BuildContext context) {
// set up the AlertDialog
AlertDialog alert = AlertDialog(
backgroundColor: Colors.indigo,
title: Text("Verify",
textAlign: TextAlign.center, style: TextStyle(color: Colors.white)),
content: Text("You have successfully verified your mobile number",
textAlign: TextAlign.center, style: TextStyle(color: Colors.white)),
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
我需要 backgroundColor 是线性方向颜色 #4a00e0 到 #8e2de2 的渐变
是这样的吗?
class SO extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return Dialog(
child: DecoratedBox(
decoration: BoxDecoration(
gradient:LinearGradient(
colors: [
Colors.red,
Colors.blue
]
)
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(title: Text("Title")),
ListTile(title: Text("Lorem ipsum dolor sit amet, consectetur adipisicing elit.")),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(icon: Icon(Icons.cancel), onPressed: () {},),
IconButton(icon: Icon(Icons.done), onPressed: () {},),
],
),
],
),
),
);
});
},
),
);
}
}
在 Material 对话框上应用渐变是最奇怪的想法,但如果确实需要的话
我认为最好的选择是将 dialog.dart 代码复制粘贴到自定义 class 中并修改它
所以结果,你可以通过任何渐变
如何使用示例
import 'package:flutter/material.dart';
import 'package:flutter_app/weird_alert_dialog.dart' show UnicornAlertDialog;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('AppBar')),
body: Content(),
),
);
}
}
class Content extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () => _showDialod(context),
child: Text('PRESS ME'),
),
);
}
_showDialod(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return UnicornAlertDialog(
title: Text('Title'),
gradient: LinearGradient(
colors: [Colors.purpleAccent, Colors.blue],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
actions: <Widget>[
FlatButton(child: Text('Action 1', style: TextStyle(color: Colors.white)), onPressed: () {}),
FlatButton(child: Text('Action 2', style: TextStyle(color: Colors.white)), onPressed: () {}),
],
);
},
);
}
}
并修改了 AlertDialog class 本身
这里没有什么特别的,我只是从文件中删除了所有评论并对其进行了一些修改 - 将渐变作为参数传递并使用带有渐变装饰的 Container 包装对话框子小部件
weird_alert_dialog.dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Dialog extends StatelessWidget {
const Dialog({
Key key,
this.gradient,
this.backgroundColor,
this.elevation,
this.insetAnimationDuration = const Duration(milliseconds: 100),
this.insetAnimationCurve = Curves.decelerate,
this.shape,
this.child,
}) : super(key: key);
final Color backgroundColor;
final double elevation;
final Duration insetAnimationDuration;
final Curve insetAnimationCurve;
final ShapeBorder shape;
final Widget child;
final Gradient gradient;
static const RoundedRectangleBorder _defaultDialogShape =
RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0)));
static const double _defaultElevation = 24.0;
@override
Widget build(BuildContext context) {
final DialogTheme dialogTheme = DialogTheme.of(context);
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets + const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
duration: insetAnimationDuration,
curve: insetAnimationCurve,
child: MediaQuery.removeViewInsets(
removeLeft: true,
removeTop: true,
removeRight: true,
removeBottom: true,
context: context,
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 280.0),
child: Material(
color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor,
elevation: elevation ?? dialogTheme.elevation ?? _defaultElevation,
shape: shape ?? dialogTheme.shape ?? _defaultDialogShape,
type: MaterialType.card,
child: ClipRRect(
borderRadius: _defaultDialogShape.borderRadius,
child: Container(
decoration: BoxDecoration(
gradient: gradient
),
child: child,
),
),
),
),
),
),
);
}
}
class UnicornAlertDialog extends StatelessWidget {
const UnicornAlertDialog({
Key key,
@required this.gradient,
this.title,
this.titlePadding,
this.titleTextStyle,
this.content,
this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
this.contentTextStyle,
this.actions,
this.backgroundColor,
this.elevation,
this.semanticLabel,
this.shape,
}) : assert(contentPadding != null),
super(key: key);
final Gradient gradient;
final Widget title;
final EdgeInsetsGeometry titlePadding;
final TextStyle titleTextStyle;
final Widget content;
final EdgeInsetsGeometry contentPadding;
final TextStyle contentTextStyle;
final List<Widget> actions;
final Color backgroundColor;
final double elevation;
final String semanticLabel;
final ShapeBorder shape;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context);
final DialogTheme dialogTheme = DialogTheme.of(context);
final List<Widget> children = <Widget>[];
String label = semanticLabel;
if (title != null) {
children.add(Padding(
padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
child: DefaultTextStyle(
style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title,
child: Semantics(
child: title,
namesRoute: true,
container: true,
),
),
));
} else {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
label = semanticLabel;
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
label = semanticLabel ?? MaterialLocalizations.of(context)?.alertDialogLabel;
}
}
if (content != null) {
children.add(Flexible(
child: Padding(
padding: contentPadding,
child: DefaultTextStyle(
style: contentTextStyle ?? dialogTheme.contentTextStyle ?? theme.textTheme.subhead,
child: content,
),
),
));
}
if (actions != null) {
children.add(ButtonTheme.bar(
child: ButtonBar(
children: actions,
),
));
}
Widget dialogChild = IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children,
),
);
if (label != null)
dialogChild = Semantics(
namesRoute: true,
label: label,
child: dialogChild,
);
return Dialog(
backgroundColor: backgroundColor,
gradient: gradient,
elevation: elevation,
shape: shape,
child: dialogChild,
);
}
}
class SimpleDialogOption extends StatelessWidget {
const SimpleDialogOption({
Key key,
this.onPressed,
this.child,
}) : super(key: key);
final VoidCallback onPressed;
final Widget child;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onPressed,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0),
child: child,
),
);
}
}
class SimpleDialog extends StatelessWidget {
const SimpleDialog({
Key key,
this.title,
this.gradient,
this.titlePadding = const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
this.children,
this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0),
this.backgroundColor,
this.elevation,
this.semanticLabel,
this.shape,
}) : assert(titlePadding != null),
assert(contentPadding != null),
super(key: key);
final Widget title;
final EdgeInsetsGeometry titlePadding;
final List<Widget> children;
final EdgeInsetsGeometry contentPadding;
final Color backgroundColor;
final double elevation;
final String semanticLabel;
final ShapeBorder shape;
final Gradient gradient;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final List<Widget> body = <Widget>[];
String label = semanticLabel;
if (title != null) {
body.add(Padding(
padding: titlePadding,
child: DefaultTextStyle(
style: Theme.of(context).textTheme.title,
child: Semantics(namesRoute: true, child: title),
),
));
} else {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
label = semanticLabel;
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
label = semanticLabel ?? MaterialLocalizations.of(context)?.dialogLabel;
}
}
if (children != null) {
body.add(Flexible(
child: SingleChildScrollView(
padding: contentPadding,
child: ListBody(children: children),
),
));
}
Widget dialogChild = IntrinsicWidth(
stepWidth: 56.0,
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 280.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: body,
),
),
);
if (label != null)
dialogChild = Semantics(
namesRoute: true,
label: label,
child: dialogChild,
);
return Dialog(
backgroundColor: backgroundColor,
gradient: gradient,
elevation: elevation,
shape: shape,
child: dialogChild,
);
}
}
Widget _buildMaterialDialogTransitions(
BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
}
Future<T> showDialog<T>({
@required
BuildContext context,
bool barrierDismissible = true,
@Deprecated('Instead of using the "child" argument, return the child from a closure '
'provided to the "builder" argument. This will ensure that the BuildContext '
'is appropriate for widgets built in the dialog.')
Widget child,
WidgetBuilder builder,
}) {
assert(child == null || builder == null);
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context, shadowThemeOnly: true);
return showGeneralDialog(
context: context,
pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) {
final Widget pageChild = child ?? Builder(builder: builder);
return SafeArea(
child: Builder(builder: (BuildContext context) {
return theme != null ? Theme(data: theme, child: pageChild) : pageChild;
}),
);
},
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Colors.black54,
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: _buildMaterialDialogTransitions,
);
}
我尝试使用
backgroundColor
但是我需要渐变色
showAlertDialog(BuildContext context) {
// set up the AlertDialog
AlertDialog alert = AlertDialog(
backgroundColor: Colors.indigo,
title: Text("Verify",
textAlign: TextAlign.center, style: TextStyle(color: Colors.white)),
content: Text("You have successfully verified your mobile number",
textAlign: TextAlign.center, style: TextStyle(color: Colors.white)),
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
我需要 backgroundColor 是线性方向颜色 #4a00e0 到 #8e2de2 的渐变
是这样的吗?
class SO extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return Dialog(
child: DecoratedBox(
decoration: BoxDecoration(
gradient:LinearGradient(
colors: [
Colors.red,
Colors.blue
]
)
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(title: Text("Title")),
ListTile(title: Text("Lorem ipsum dolor sit amet, consectetur adipisicing elit.")),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(icon: Icon(Icons.cancel), onPressed: () {},),
IconButton(icon: Icon(Icons.done), onPressed: () {},),
],
),
],
),
),
);
});
},
),
);
}
}
在 Material 对话框上应用渐变是最奇怪的想法,但如果确实需要的话 我认为最好的选择是将 dialog.dart 代码复制粘贴到自定义 class 中并修改它
所以结果,你可以通过任何渐变
如何使用示例
import 'package:flutter/material.dart';
import 'package:flutter_app/weird_alert_dialog.dart' show UnicornAlertDialog;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('AppBar')),
body: Content(),
),
);
}
}
class Content extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () => _showDialod(context),
child: Text('PRESS ME'),
),
);
}
_showDialod(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return UnicornAlertDialog(
title: Text('Title'),
gradient: LinearGradient(
colors: [Colors.purpleAccent, Colors.blue],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
actions: <Widget>[
FlatButton(child: Text('Action 1', style: TextStyle(color: Colors.white)), onPressed: () {}),
FlatButton(child: Text('Action 2', style: TextStyle(color: Colors.white)), onPressed: () {}),
],
);
},
);
}
}
并修改了 AlertDialog class 本身 这里没有什么特别的,我只是从文件中删除了所有评论并对其进行了一些修改 - 将渐变作为参数传递并使用带有渐变装饰的 Container 包装对话框子小部件
weird_alert_dialog.dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Dialog extends StatelessWidget {
const Dialog({
Key key,
this.gradient,
this.backgroundColor,
this.elevation,
this.insetAnimationDuration = const Duration(milliseconds: 100),
this.insetAnimationCurve = Curves.decelerate,
this.shape,
this.child,
}) : super(key: key);
final Color backgroundColor;
final double elevation;
final Duration insetAnimationDuration;
final Curve insetAnimationCurve;
final ShapeBorder shape;
final Widget child;
final Gradient gradient;
static const RoundedRectangleBorder _defaultDialogShape =
RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0)));
static const double _defaultElevation = 24.0;
@override
Widget build(BuildContext context) {
final DialogTheme dialogTheme = DialogTheme.of(context);
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets + const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),
duration: insetAnimationDuration,
curve: insetAnimationCurve,
child: MediaQuery.removeViewInsets(
removeLeft: true,
removeTop: true,
removeRight: true,
removeBottom: true,
context: context,
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 280.0),
child: Material(
color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor,
elevation: elevation ?? dialogTheme.elevation ?? _defaultElevation,
shape: shape ?? dialogTheme.shape ?? _defaultDialogShape,
type: MaterialType.card,
child: ClipRRect(
borderRadius: _defaultDialogShape.borderRadius,
child: Container(
decoration: BoxDecoration(
gradient: gradient
),
child: child,
),
),
),
),
),
),
);
}
}
class UnicornAlertDialog extends StatelessWidget {
const UnicornAlertDialog({
Key key,
@required this.gradient,
this.title,
this.titlePadding,
this.titleTextStyle,
this.content,
this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
this.contentTextStyle,
this.actions,
this.backgroundColor,
this.elevation,
this.semanticLabel,
this.shape,
}) : assert(contentPadding != null),
super(key: key);
final Gradient gradient;
final Widget title;
final EdgeInsetsGeometry titlePadding;
final TextStyle titleTextStyle;
final Widget content;
final EdgeInsetsGeometry contentPadding;
final TextStyle contentTextStyle;
final List<Widget> actions;
final Color backgroundColor;
final double elevation;
final String semanticLabel;
final ShapeBorder shape;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context);
final DialogTheme dialogTheme = DialogTheme.of(context);
final List<Widget> children = <Widget>[];
String label = semanticLabel;
if (title != null) {
children.add(Padding(
padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
child: DefaultTextStyle(
style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title,
child: Semantics(
child: title,
namesRoute: true,
container: true,
),
),
));
} else {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
label = semanticLabel;
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
label = semanticLabel ?? MaterialLocalizations.of(context)?.alertDialogLabel;
}
}
if (content != null) {
children.add(Flexible(
child: Padding(
padding: contentPadding,
child: DefaultTextStyle(
style: contentTextStyle ?? dialogTheme.contentTextStyle ?? theme.textTheme.subhead,
child: content,
),
),
));
}
if (actions != null) {
children.add(ButtonTheme.bar(
child: ButtonBar(
children: actions,
),
));
}
Widget dialogChild = IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children,
),
);
if (label != null)
dialogChild = Semantics(
namesRoute: true,
label: label,
child: dialogChild,
);
return Dialog(
backgroundColor: backgroundColor,
gradient: gradient,
elevation: elevation,
shape: shape,
child: dialogChild,
);
}
}
class SimpleDialogOption extends StatelessWidget {
const SimpleDialogOption({
Key key,
this.onPressed,
this.child,
}) : super(key: key);
final VoidCallback onPressed;
final Widget child;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onPressed,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0),
child: child,
),
);
}
}
class SimpleDialog extends StatelessWidget {
const SimpleDialog({
Key key,
this.title,
this.gradient,
this.titlePadding = const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
this.children,
this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0),
this.backgroundColor,
this.elevation,
this.semanticLabel,
this.shape,
}) : assert(titlePadding != null),
assert(contentPadding != null),
super(key: key);
final Widget title;
final EdgeInsetsGeometry titlePadding;
final List<Widget> children;
final EdgeInsetsGeometry contentPadding;
final Color backgroundColor;
final double elevation;
final String semanticLabel;
final ShapeBorder shape;
final Gradient gradient;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final List<Widget> body = <Widget>[];
String label = semanticLabel;
if (title != null) {
body.add(Padding(
padding: titlePadding,
child: DefaultTextStyle(
style: Theme.of(context).textTheme.title,
child: Semantics(namesRoute: true, child: title),
),
));
} else {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
label = semanticLabel;
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
label = semanticLabel ?? MaterialLocalizations.of(context)?.dialogLabel;
}
}
if (children != null) {
body.add(Flexible(
child: SingleChildScrollView(
padding: contentPadding,
child: ListBody(children: children),
),
));
}
Widget dialogChild = IntrinsicWidth(
stepWidth: 56.0,
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 280.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: body,
),
),
);
if (label != null)
dialogChild = Semantics(
namesRoute: true,
label: label,
child: dialogChild,
);
return Dialog(
backgroundColor: backgroundColor,
gradient: gradient,
elevation: elevation,
shape: shape,
child: dialogChild,
);
}
}
Widget _buildMaterialDialogTransitions(
BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
}
Future<T> showDialog<T>({
@required
BuildContext context,
bool barrierDismissible = true,
@Deprecated('Instead of using the "child" argument, return the child from a closure '
'provided to the "builder" argument. This will ensure that the BuildContext '
'is appropriate for widgets built in the dialog.')
Widget child,
WidgetBuilder builder,
}) {
assert(child == null || builder == null);
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context, shadowThemeOnly: true);
return showGeneralDialog(
context: context,
pageBuilder: (BuildContext buildContext, Animation<double> animation, Animation<double> secondaryAnimation) {
final Widget pageChild = child ?? Builder(builder: builder);
return SafeArea(
child: Builder(builder: (BuildContext context) {
return theme != null ? Theme(data: theme, child: pageChild) : pageChild;
}),
);
},
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Colors.black54,
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: _buildMaterialDialogTransitions,
);
}