如何自定义对话框的位置、大小和背景?
How to customize a dialog's position, size and background?
我有一个带有 FAB 的主屏幕,按下它时我想显示一个对话框供用户输入。
目前我正在使用 showDialog()
和 SimpleDialog。
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: NormalText('New Counter Item'),
contentPadding: EdgeInsets.fromLTRB(24.0, 0.0, 24.0, 24.0),
children: <Widget>[
Container(
...
)
],
);
}
);
但是,我似乎无法用它自定义几乎任何东西(更小、弯曲的角和位于屏幕下方的位置)。 AlertDialog
好像是一样的
是否可以自定义这些属性?
没有。这些不是设计为可定制的。它们是为了尊重 Material 设计原则而设计的。
如果您想要定制设计,您可以根据 Align
and/or DecoratedBox
制作自己的模态
SimpleDialog
和 AlertDialog
旨在满足一组特定的需求。它们具有一定程度的自定义,但最终它们只是为了显示简单的 pop-up 对话框,为用户提供一些信息并提示对话响应(即 "Yes"、"No"、"Cancel", "Save", 等等).
如果您想要自定义程度更高的 pop-up 对话框,您需要创建自己的对话框。不过,从好的方面来说,它真的很简单。将 showDialog
return 中的构建器与 child 的 Dialog
小部件设置为您想要的任何值:
showDialog(
context: context,
builder: (BuildContext cxt) {
return Dialog(
child: Container(
...
),
);
},
);
显然,您需要重新创建标题栏和操作栏等内容,但您可以破解 SimpleDialog
和 AlertDialog
的源代码并复制其中的内容,或者你可以推出自己的解决方案。
它并没有你想象的那么可怕。
您只需要克隆 Dialog.dart,然后
用对齐替换中心小部件。
当然也要重命名东西;例如MyDialog、myShowDialog、MySimpleDialog。
是的,就这么简单。
而且,如果您正在滚动,如何添加对齐小部件的对齐参数作为额外...
return showDialog<void>(
barrierDismissible: true,
context: context,
builder: (BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(0),
child: new Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.purple,
child: new Column(
children: <Widget>[
new Text(
'custom dialog text',
style: new TextStyle(
fontSize: 14,
color: Colors.white,
),
),
],
),
),
)
],
);
},
);
希望这对您有所帮助,
谢谢
这是一个干净的解决方案,如果由于某种原因你有一个 TextField
/TextFormField
并且在那里你有一个 onsubmit
属性 那么你可以按照:
onSubmit: () {
showDialog(
context: context,
builder: (context){
return WillPopScope(
onWillPop: () { return Future(() => false); }, // this will prevent going back
child: AlertDialog(
content: Row(
children: [
progressWidget(),
Container(margin: EdgeInsets.only(left: 10.0),child:Text("Loading" )),
],),
)
);
}
);
yourCallToMethod.whenComplete((){
Navigator.of(context).pop();
});
},
好处?
当显示 showAlert
时,如果有人随意或粗暴地点击屏幕,屏幕就会返回。这可以防止这种行为,并且仅在您的函数完成时关闭 showAlert
。
您实际上可以通过在构建器中添加一个 SingleChildScrollView()
+ 一个填充(用于距顶部的偏移量)来修改它的位置(仅高度),如下所示:
showDialog<String>(
context: context,
builder: (ctxDialog) =>
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(top: 150.0),
child: AlertDialog()
)
)
);
不管接受的答案是什么;有多种方法可以按照您要求的方式自定义 SimpleDialog。
尺码
SimpleDialog 将在 width/height 中增长,具体取决于子项及其填充方式。下面的代码将生成一个宽度为 336,高度为 300 的对话框:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
insetPadding: EdgeInsets.zero,
titlePadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
children: [
Container(
width: 300,
height: 300,
),
],
);
},
);
不确定在宽度上增加的 36 像素是多少;但这表明尺寸 可以 定制。
角落
可以使用 shape
属性 自定义角。下面的代码显示了一个带有 4 像素圆边的绿色边框:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4.0),
side: BorderSide(
color: Colors.green,
),
),
/* ... */
);
},
);
位置
我发现我可以使用 insetPadding
属性 在页面上上下移动对话框。这定义了屏幕边缘和对话框之间所需的最小 space 量。虽然有点麻烦,但如果你知道屏幕的大小和对话框的大小,你可以用一些简单的数学来微调对话框的位置。
给定 1920 像素的屏幕高度和 300 像素的对话框高度,下面的代码应将您的对话框放置在距离屏幕顶部边缘 100 像素的位置,而不是在中心爆炸:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
insetPadding: EdgeInsets.only(bottom: 1520),
/* ... */
);
},
);
这是因为我要求屏幕底部边缘和对话框之间的间距最小;在这个规定下,对话框唯一存在的位置是靠近顶部。
:- 我们可以通过给底部改变对话框的垂直位置
insetPadding 喜欢
insetPadding: EdgeInsets.only(bottom: XX);
:- 和水平位置由水平填充或左
insetPadding: EdgeInsets.symmetric(horizontal:XX);
or
insetPadding: EdgeInsets.only(left: XX,right:YY);
解决了在 Stack
和 Positioned
中包装对话框主体的问题
Stack(
children: [
Positioned(
left: 100, // left coordinate
top: 100, // top coordinate
child: YOUR_DIALOG....
我有一个带有 FAB 的主屏幕,按下它时我想显示一个对话框供用户输入。
目前我正在使用 showDialog()
和 SimpleDialog。
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: NormalText('New Counter Item'),
contentPadding: EdgeInsets.fromLTRB(24.0, 0.0, 24.0, 24.0),
children: <Widget>[
Container(
...
)
],
);
}
);
但是,我似乎无法用它自定义几乎任何东西(更小、弯曲的角和位于屏幕下方的位置)。 AlertDialog
好像是一样的
是否可以自定义这些属性?
没有。这些不是设计为可定制的。它们是为了尊重 Material 设计原则而设计的。
如果您想要定制设计,您可以根据 Align
and/or DecoratedBox
SimpleDialog
和 AlertDialog
旨在满足一组特定的需求。它们具有一定程度的自定义,但最终它们只是为了显示简单的 pop-up 对话框,为用户提供一些信息并提示对话响应(即 "Yes"、"No"、"Cancel", "Save", 等等).
如果您想要自定义程度更高的 pop-up 对话框,您需要创建自己的对话框。不过,从好的方面来说,它真的很简单。将 showDialog
return 中的构建器与 child 的 Dialog
小部件设置为您想要的任何值:
showDialog(
context: context,
builder: (BuildContext cxt) {
return Dialog(
child: Container(
...
),
);
},
);
显然,您需要重新创建标题栏和操作栏等内容,但您可以破解 SimpleDialog
和 AlertDialog
的源代码并复制其中的内容,或者你可以推出自己的解决方案。
它并没有你想象的那么可怕。 您只需要克隆 Dialog.dart,然后 用对齐替换中心小部件。
当然也要重命名东西;例如MyDialog、myShowDialog、MySimpleDialog。
是的,就这么简单。
而且,如果您正在滚动,如何添加对齐小部件的对齐参数作为额外...
return showDialog<void>(
barrierDismissible: true,
context: context,
builder: (BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(0),
child: new Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.purple,
child: new Column(
children: <Widget>[
new Text(
'custom dialog text',
style: new TextStyle(
fontSize: 14,
color: Colors.white,
),
),
],
),
),
)
],
);
},
);
希望这对您有所帮助, 谢谢
这是一个干净的解决方案,如果由于某种原因你有一个 TextField
/TextFormField
并且在那里你有一个 onsubmit
属性 那么你可以按照:
onSubmit: () {
showDialog(
context: context,
builder: (context){
return WillPopScope(
onWillPop: () { return Future(() => false); }, // this will prevent going back
child: AlertDialog(
content: Row(
children: [
progressWidget(),
Container(margin: EdgeInsets.only(left: 10.0),child:Text("Loading" )),
],),
)
);
}
);
yourCallToMethod.whenComplete((){
Navigator.of(context).pop();
});
},
好处?
当显示 showAlert
时,如果有人随意或粗暴地点击屏幕,屏幕就会返回。这可以防止这种行为,并且仅在您的函数完成时关闭 showAlert
。
您实际上可以通过在构建器中添加一个 SingleChildScrollView()
+ 一个填充(用于距顶部的偏移量)来修改它的位置(仅高度),如下所示:
showDialog<String>(
context: context,
builder: (ctxDialog) =>
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(top: 150.0),
child: AlertDialog()
)
)
);
不管接受的答案是什么;有多种方法可以按照您要求的方式自定义 SimpleDialog。
尺码
SimpleDialog 将在 width/height 中增长,具体取决于子项及其填充方式。下面的代码将生成一个宽度为 336,高度为 300 的对话框:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
insetPadding: EdgeInsets.zero,
titlePadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
children: [
Container(
width: 300,
height: 300,
),
],
);
},
);
不确定在宽度上增加的 36 像素是多少;但这表明尺寸 可以 定制。
角落
可以使用 shape
属性 自定义角。下面的代码显示了一个带有 4 像素圆边的绿色边框:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4.0),
side: BorderSide(
color: Colors.green,
),
),
/* ... */
);
},
);
位置
我发现我可以使用 insetPadding
属性 在页面上上下移动对话框。这定义了屏幕边缘和对话框之间所需的最小 space 量。虽然有点麻烦,但如果你知道屏幕的大小和对话框的大小,你可以用一些简单的数学来微调对话框的位置。
给定 1920 像素的屏幕高度和 300 像素的对话框高度,下面的代码应将您的对话框放置在距离屏幕顶部边缘 100 像素的位置,而不是在中心爆炸:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
insetPadding: EdgeInsets.only(bottom: 1520),
/* ... */
);
},
);
这是因为我要求屏幕底部边缘和对话框之间的间距最小;在这个规定下,对话框唯一存在的位置是靠近顶部。
:- 我们可以通过给底部改变对话框的垂直位置 insetPadding 喜欢
insetPadding: EdgeInsets.only(bottom: XX);
:- 和水平位置由水平填充或左
insetPadding: EdgeInsets.symmetric(horizontal:XX);
or
insetPadding: EdgeInsets.only(left: XX,right:YY);
解决了在 Stack
和 Positioned
Stack(
children: [
Positioned(
left: 100, // left coordinate
top: 100, // top coordinate
child: YOUR_DIALOG....