Flutter:更改AlertDialog的宽度

时间:2018-12-24 12:02:58

标签: dart flutter

我想知道如何更改AlertDialog的默认宽度,但我仅成功更改了边框半径:

这是我的代码:

showDialog(
       context: context,
       builder: (_) =>
            new AlertDialog(
               shape: RoundedRectangleBorder(
                   borderRadius: BorderRadius.all(Radius.circular(10.0))
               ),
               content: ProductPreviewScreen(),
            )
    );

预期结果:

enter image description here 有想法吗?

17 个答案:

答案 0 :(得分:26)

从2020年5月开始,如果要更改对话框的插入填充,您所需要做的就是使用Dialog类并覆盖'insetPadding'属性。如果需要,可以使对话框一直延伸到屏幕边缘。

您还可以通过使对话框表面本身透明然后添加所需的任何小部件来制作一些很酷的自定义对话框。例如:

showDialog(Dialog(
  backgroundColor: Colors.transparent,
  insetPadding: EdgeInsets.all(10),
  child: Stack(
    overflow: Overflow.visible,
    alignment: Alignment.center,
    children: <Widget>[
      Container(
        width: double.infinity,
        height: 200,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          color: Colors.lightBlue
        ),
        padding: EdgeInsets.fromLTRB(20, 50, 20, 20),
        child: Text("You can make cool stuff!",
          style: TextStyle(fontSize: 24),
          textAlign: TextAlign.center
        ),
      ),
      Positioned(
        top: -100,
        child: Image.network("https://i.imgur.com/2yaf2wb.png", width: 150, height: 150)
      )
    ],
  )
));

结果:

Dialog example

答案 1 :(得分:5)

使用填充小部件

 Padding(
   padding: EdgeInsets.only(left: 50.0, right: 50.0),
   child://AlertDialog or any other Dialog you can use
         Dialog(
                elevation: 0.0,
                backgroundColor: Colors.transparent,
                child: Container(
                  width: 10.0,
                  height: 50.0,
                  color: Colors.red,
                )
            ))

答案 2 :(得分:3)

我的解决方案是将Dialog封装在一个小部件中,该小部件通过修改MediaQueryData来克服Dialog类添加的额外填充。

import 'package:myapp/widgets/dialog_inset_defeat.dart';
...

showDialog(
    context: context,
    builder: (_) => DialogInsetDefeat(
      context: context,
      child: SimpleDialog(...),
    )
);

...或使用showDialogWithInsets()作为自定义值:

showDialogWithInsets(
    context: context,
    edgeInsets: EdgeInsets.symmetric(horizontal: 8),
    builder: (_) => SimpleDialog(...),
    )
);

文件dialog_inset_defeat.dart

   import 'package:flutter/material.dart';

/// A widget to defeat the hard coded insets of the [Dialog] class which
/// are [EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0)].
///
/// See also:
///
///  * [Dialog], for dialogs that have a message and some buttons.
///  * [showDialog], which actually displays the dialog and returns its result.
///  * <https://material.io/design/components/dialogs.html>
///  * <https://stackoverflow.com/questions/53913192/flutter-change-the-width-of-an-alertdialog>
class DialogInsetDefeat extends StatelessWidget {
  final BuildContext context;
  final Widget child;
  final deInset = EdgeInsets.symmetric(horizontal: -40, vertical: -24);
  final EdgeInsets edgeInsets;

  DialogInsetDefeat({@required this.context, @required this.child, this.edgeInsets});

  @override
  Widget build(BuildContext context) {
    var netEdgeInsets = deInset + (edgeInsets ?? EdgeInsets.zero);
    return MediaQuery(
      data: MediaQuery.of(context).copyWith(viewInsets: netEdgeInsets),
      child: child,
    );
  }
}

/// Displays a Material dialog using the above DialogInsetDefeat class.
/// Meant to be a drop-in replacement for showDialog().
///
/// See also:
///
///  * [Dialog], on which [SimpleDialog] and [AlertDialog] are based.
///  * [showDialog], which allows for customization of the dialog popup.
///  * <https://material.io/design/components/dialogs.html>
Future<T> showDialogWithInsets<T>({
  @required BuildContext context,
  bool barrierDismissible = true,
  @required WidgetBuilder builder,
  EdgeInsets edgeInsets,
}) {
  return showDialog(
    context: context,
    builder: (_) => DialogInsetDefeat(
      context: context,
      edgeInsets: edgeInsets,
      child: Builder(builder: builder),
    ),
    barrierDismissible: barrierDismissible = true,
  );
}

从Flutter 1.8.3开始为我工作。 YMMV

答案 3 :(得分:3)

参考此代码。您可以通过设置 insetPadding 来更改对话框的宽度和高度,因为它采用默认填充,因此我们需要像这样更改。

showDialog(
  context: context,
  builder: (_) =>
   Dialog(
     insetPadding: EdgeInsets.symmetric(horizontal: 2.0, vertical: 2.0),
     backgroundColor: Colors.transparent,
    child: Container(
      width: double.infinity,
      height: MediaQuery.of(context).size.height*0.7 ,
      decoration: BoxDecoration(
        color: Colors.grey[900],
      ),
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(10.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                GestureDetector(
                  onTap: (){
                    Navigator.pop(context);
                  },
                    child: Icon(Icons.close,color: Colors.grey,)),
              ],
            ),
          ),
          Text("select your avatar",style: TextStyle(color: white,fontWeight: FontWeight.bold),),
        ],
      ),
    ),
  ),
);

答案 4 :(得分:3)

您可以更改AlertDialog属性insetPadding,这对您来说是一种简单的方法。

 void alertBox() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        insetPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
        // (horizontal:10 = left:10, right:10)(vertical:10 = top:10, bottom:10)
        contentPadding: EdgeInsets.zero,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
        content: Container(
          width: MediaQuery.of(context).size.width - 20,
          // width = device width minus insetPadding = deviceWidth - 20  (left:10, right:10 = 20)
          height: MediaQuery.of(context).size.height - 20,
          // height = device height minus insetPadding = deviceHeight - 20  (top:10, bottom:10 = 20)
          child: ClipRRect(
            borderRadius: BorderRadius.circular(10),
            child: Card(
              margin: EdgeInsets.zero,
              color: Colors.amber,
            ),
          ),
        ),
      ),
    );
  }

答案 5 :(得分:2)

我终于找到了改变 AlertDialog 宽度的方法。 只需用容器包裹“内容”,并为其设置宽度。

return AlertDialog(
...
content: Container(
   width: MediaQuery.of(context).size.width*0.45,
   child: ...

AlertDialog with width modified

答案 6 :(得分:2)

您可以尝试按照here中的建议用ConstrainedBox小部件包装AlertDialog小部件,并为maxWidth参数设置所需的值。

已更新

我只是查看了AlertDialog小部件(即Dialog小部件)的父级代码,发现它用minWidth为280像素的ConstrainedBox小部件包装了其子级。这就是为什么我们无法更改AlertDialog小部件的宽度的原因。

幸运的是,我们可以做两件事。第一种选择是更改dialog.dart文件中“对话框”小组件的默认minWidth。请注意,更改此设置将影响使用Dialog小部件的所有flutter项目。

//inside dialog.dart

class Dialog extends StatelessWidget {

...

@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), // You can set your desired value for minWidth here
          child: Material(
            elevation: 24.0,

            ...

然后您可以像这样使用AlertDialog:

showDialog(
  context: context,
  builder: (_) => AlertDialog(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(10.0))
      ),
    contentPadding: EdgeInsets.all(0.0),
    content: ProductPreviewScreen(),
    )
  )
);

另一种方法是创建我们自己的自定义对话框。

showDialog(
  context: context,
  builder: (_) => Center( // Aligns the container to center
    child: Container( // A simplified version of dialog. 
      width: 100.0,
      height: 56.0,
      color: Colors.pink,
      )
    )
 );

答案 7 :(得分:2)

使用 insetWidth 和 future builder 等对我不起作用 - 只是编辑内容道具的宽度效果很好。

showDialog(
    context: context,
    builder: (context) {
      Future.delayed(Duration(seconds: 1000), () {
        Navigator.of(context).pop(true);
      });
      return AlertDialog(
        insetPadding: EdgeInsets.all(8.0),
        title: Text(
          "Time to go pro!",
          textAlign: TextAlign.center,
        ),
        content: Container(
          width: MediaQuery.of(context).size.width,
          child: BuySheet(
              applePayEnabled: applePayEnabled,
              googlePayEnabled: googlePayEnabled,
              applePayMerchantId: applePayMerchantId,
              squareLocationId: squareLocationId),
        ),
      );
    });

Result of the above code

答案 8 :(得分:2)

使用Dialog()

Dialog(
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
  insetPadding: EdgeInsets.all(15),
  child: SingleChildScrollView(
    child: Container(),
    ),
  ),
);

答案 9 :(得分:1)

您好,您实际上可以使用 insetPadding 并在内容中使用一列包含 SizedBox(width:MediaQuery.of(context).size.width)。唯一的区别是我使用了 AlertDialog。波纹管是它对我有用的方式。您可以通过更改 insetPadding 内的填充来设置对话框宽度。希望我有所帮助:)

dialog(){
TextEditingController controller = TextEditingController();

return showDialog(
  context: context,
  barrierDismissible: true,
  builder: (_) => AlertDialog(
    insetPadding:  EdgeInsets.symmetric(
        horizontal: MediaQuery.of(context).size.width * 0.08),
    content: SingleChildScrollView(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(
            height: 16,
            width: MediaQuery.of(context).size.width,
          ),
          Text(
            'Hello',
          ),
          SizedBox(
            height: 15,
          ),
          Text(
            'Description',
          ),
          TextField(
            controller: controller,
            style: TextStyle(
              color: Colors.black,
            ),
          ),
        ],
      ),
    ),
    actions: [
      FlatButton(
        child: Text("Close"),
        onPressed: () {
          Navigator.of(context).pop();
        },
      ),
    ],
  ),
);

}

这是它的样子 https://i.stack.imgur.com/bvKpP.png

答案 10 :(得分:1)

 return Dialog(

  backgroundColor: Colors.white,
  insetPadding: EdgeInsets.all(10.0),
  child: Container(
   
    width: double.infinity,

在返回 Dialog 的地方使用 insetpadding 并给它一个 double 值,就我而言,我给它一个 10.0 insetPadding: E​​dgeInsets.all(10.0),你可以给它自定义高度

答案 11 :(得分:0)

作为一种解决方法,您可以使用对话框标题进行播放,在大多数情况下,对话框会水平扩展以容纳标题。因此,您可以创建大标题以确保对话框采用最大宽度。显然,您不能只放置长标题,而是可以构建两个文本小部件的标题,其中一个窗口小部件具有与文本颜色匹配的背景。对于不显示标题的情况:

showDialog(
   context: context,
   builder: (_) =>
        new AlertDialog(
           title: Text('hidden title, just set font text to the same as background.',
                 style: TextStyle(color: Colors.white)),
           shape: RoundedRectangleBorder(
               borderRadius: BorderRadius.all(Radius.circular(10.0))
           ),
           content: ProductPreviewScreen(),
        )
);

答案 12 :(得分:0)

这比其他答案更简单。只需使用构建器来更改对话框的大小即可(正在构建,以其他语言实例化)。这意味着您还可以查询屏幕尺寸,并根据屏幕尺寸决定所需的空间。例如,平板电脑上的空间要大于电话上的空间。如果需要应用程序栏和其他功能,可以将Scaffold设为Container的子代。

showDialog(
  context: context,
      builder: (_) => new AlertDialog(
          shape: RoundedRectangleBorder(
              borderRadius:
                  BorderRadius.all(
                      Radius.circular(10.0))),
                          content: Builder(
                            builder: (context) {

// Get available height and width of the build area of this widget. Make a choice depending on the size.                              
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;

return Container(
           height: height - 400,
           width: width - 400,
                              );
                            },
                          ),
                        ));

不同大小的示例:

enter image description here

enter image description here

enter image description here

答案 13 :(得分:0)

我认为另一个答案是有问题的,因为:

  1. 动态更新可能会破坏您的应用。
  2. 您可能会破坏应用程序中已经存在的对话框。
  3. 与其他开发人员通过gitlab / github / etc共享代码将是有问题的。

这就是我所做的:

第1步。

从“ dialog.dart”中复制代码,并将其粘贴到新文件中,例如:lib> custom_flutter> custom_dialog.dart。

第2步。

这将产生一些导入错误,删除这些导入,然后添加以下行:

import 'package:flutter/material.dart';

第3步。

在新文件“ custom_dialog.dart”中找到Dialog类。并替换:

padding: MediaQuery.of(context).viewInsets + const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),

与此:

padding: MediaQuery.of(context).viewInsets + const EdgeInsets.symmetric(horizontal: 0.0, vertical: 24.0),

第4步。

现在,无论您想在哪里使用此对话框,请添加以下导入语句:

import 'package:my_app_name/custom_flutter/custom_dialog.dart' as customDialog;

第5步。

如果要使用不受限制的对话框,请使用:

customDialog.AlertDialog() //Unrestricted dialog

如果没有,那就继续使用常规的:

AlertDialog() //Restricted dialog

答案 14 :(得分:0)

获取屏幕尺寸:

final screenSize = MediaQuery.of(context).size;

然后用容器包装。像这样使用Container width属性:

width: screenSize.width / 2,

用另一个值更改2以调整屏幕。

答案 15 :(得分:-1)

如果需要,您可以这样做

void show(){
    var alert=  SingleChildScrollView(
      padding: EdgeInsets.only(top:10),
         child: Card(
           child: Column(
             children: <Widget>[
                  ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                 leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
               ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
                ListTile(
                   title: Text("akshesafdadsaasfsafafafafasfay"),
                   leading: Icon(Icons.print),
                 ),
             ],
           ),
         ),
   );

   showDialog(context: context,builder: (context){
     return alert;
   });
  }

答案 16 :(得分:-1)

return Dialog(
      insetPadding: EdgeInsets.symmetric(
        horizontal: X,
      ),
);