簡體   English   中英

Flutter:如何更改 AlertDialog 的寬度?

[英]Flutter: How to change the width of an AlertDialog?

我想知道如何更改AlertDialog的默認寬度,我只成功更改了邊框半徑:

這是我的代碼:

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

預期結果:

在此處輸入圖像描述 任何想法?

從 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)
      )
    ],
  )
));

結果是:

對話框示例

這比其他答案要簡單得多。 只需使用構建器來更改正在構建的對話框的大小(構建,用其他語言實例化)。 這意味着您還可以查詢屏幕尺寸並根據所述屏幕尺寸決定您想要多少空間。 例如,平板電腦上的空間比手機上的空間大。 如果您需要 App bar 和其他功能,可以將 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,
        );
      },
    ),
  )
);

不同尺寸的示例:

在此處輸入圖像描述

在此處輸入圖像描述

在此處輸入圖像描述

可以選擇添加這些以刪除不需要的內部/外部邊界空間。

          insetPadding: EdgeInsets.zero,
          contentPadding: EdgeInsets.zero,
          clipBehavior: Clip.antiAliasWithSaveLayer,

使用內置對話框:

  • 要增加寬度:

     AlertDialog( title: Text("AlertDialog"), insetPadding: EdgeInsets.zero, )
  • 要減小寬度:

     AlertDialog( title: Text("AlertDialog"), insetPadding: EdgeInsets.symmetric(horizontal: 100), )

使用自定義對話框:

在此處輸入圖像描述

調用這個方法:

showGeneralDialog(
  context: context,
  barrierColor: Colors.black.withOpacity(0.5),
  pageBuilder: (_, __, ___) {
    return Material(
      color: Colors.transparent,
      child: Center(
        child: Container(
          color: Colors.white, // Dialog background
          width: 120, // Dialog width
          height: 50, // Dialog height
          child: SingleChildScrollView(
            child: Column(
              children: [
                Text('I am a small Dialog'),
              ],
            ),
          ),
        ),
      ),
    );
  },
);

我不知道如何更改AlertDialog的默認寬度,我僅成功更改了邊框半徑:

這是我的代碼:

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

預期結果:

在此處輸入圖片說明 任何的想法?

您可以嘗試按照此處的建議使用 ConstrainedBox 小部件包裝您的 AlertDialog 小部件,並為 maxWidth 參數設置所需的值。

更新

我剛剛查看了 AlertDialog 小部件的父級代碼,它是 Dialog 小部件,發現它用 minWidth 為 280 像素的 ConstrainedBox 小部件包裝了它的子級。 這就是我們不能改變 AlertDialog 小部件寬度的原因。

幸運的是,我們可以做兩件事。 第一個選項是更改 dialog.dart 文件中 Dialog Widget 的默認 minWidth。 請注意,更改此設置會影響所有使用 Dialog 小部件的顫振項目。

//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,
      )
    )
 );

使用填充小部件

 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,
                )
            ))

我的解決方案是將 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),
    ),
    // Edited! barrierDismissible: barrierDismissible = true,
    barrierDismissible: barrierDismissible,
  );
}

從 Flutter 1.8.3 開始為我工作。 YMMV

使用對話框()

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

我終於找到了改變 AlertDialog 寬度的方法。 只需用容器包裝“內容”,並將寬度設置為它。

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

寬度已修改的 AlertDialog

您可以更改 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,
            ),
          ),
        ),
      ),
    );
  }

與 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),
        ),
      );
    });

上述代碼的結果

請參考此代碼。 您可以通過設置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),),
        ],
      ),
    ),
  ),
);

 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),你可以給它一個自定義高度

您好,您實際上可以使用 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

像這樣添加 InsetPadding 屬性

     insetPadding: EdgeInsets.zero




  AlertDialog(
      title: Center(child: Text("$title")),
------------------------->Here we added the property
      insetPadding: EdgeInsets.zero,
      titlePadding: EdgeInsets.only(top: 14.0, bottom: 4),
      content: Container(
        height: 50,
        child: TextFormField(
          controller: find_controller,
          decoration: InputDecoration(
            suffixIcon: context.watch<MediaProvider>().isChangeDialog
                ? IconButton(
                    onPressed: () {
                      clearController(find_controller);
                    },
                    icon: Icon(Icons.clear))
                : null,
            border: OutlineInputBorder(
                borderSide: BorderSide(color: Colors.deepPurpleAccent)),
            hintText: 'Id',
          ),
          onChanged: (val) {
            if (val.isNotEmpty)
              context.read<MediaProvider>().isChangeDialog = true;
            else
              context.read<MediaProvider>().isChangeDialog = false;
          },
        ),
      ),
      actions: [
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.all(4.0),
              child: OutlinedButton(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Align(
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 12.0),
                          child: Icon(Icons.clear),
                        ),
                      ),
                      Text("Cancel")
                    ],
                  ),
                  onPressed: () {
                    context.read<MediaProvider>().isChangeDialog = false;
                    Navigator.of(context).pop();
                  }),
            ),
            Padding(
              padding: const EdgeInsets.all(4.0),
              child: ElevatedButton(
                  onPressed: context.watch<MediaProvider>().isChangeDialog
                      ? () {
                          context.read<MediaProvider>().isChangeDialog = false;
                          okCallback;
                        }
                      : null,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Align(
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 12.0),
                          child: Icon(Icons.check),
                        ),
                      ),
                      Text("OK")
                    ],
                  )),
            )
          ],
        ),
      ],
    );


前


[2]:https://i.stack.imgur.com/pzYK6.png

獲取屏幕尺寸:

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

然后用容器包裹。 像這樣使用Container width屬性:

width: screenSize.width / 2,

將2更改為另一個值以調整屏幕。

如果你想要你可以這樣做

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;
   });
  }

作為一種解決方法,您可以使用對話框標題,在大多數情況下,對話框將水平擴展以適應標題。 因此,您可以創建大標題以確保對話框將采用最大寬度。 顯然你不能只放長標題,但你可以建立兩個文本小部件的標題,其中一個具有文本顏色匹配背景。 對於不應顯示標題的情況:

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(),
        )
);
return Dialog(
      insetPadding: EdgeInsets.symmetric(
        horizontal: X,
      ),
);

我找到了最簡單的方法......只需添加insetPadding: EdgeInsets.zero,它將擴展到最大尺寸寬度:

 showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Center(child: Text("Send Message", style: TextStyle(
                  color: Colors.white, fontWeight: FontWeight.bold),)),
              backgroundColor: Colors.indigo[700],
              insetPadding: EdgeInsets.zero,
              content:

我正在使用get包,它很棒。 使用它的對話框,很容易調整大小

Get.generalDialog(pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation,) {
      return SimpleDialog(
        shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(Constants.padding), ),
        elevation: 0, backgroundColor: Colors.transparent,
        children: [Center(child: Stack(
          children: <Widget>[
            Container(width: Get.width * 0.95,
              padding: const EdgeInsets.only(left: Constants.padding,top: Constants.avatarRadius
                  + Constants.padding, right: Constants.padding,bottom: Constants.padding
              ),
              margin: const EdgeInsets.only(top: Constants.avatarRadius),
              decoration: BoxDecoration(
                shape: BoxShape.rectangle,
                color: Get.theme.scaffoldBackgroundColor,
                borderRadius: BorderRadius.circular(Constants.padding),
                boxShadow: const [
                  BoxShadow(color: Colors.black,offset: Offset(0,10), blurRadius: 10 ),
                ]
              ),
              child: Text('body'),
            ),
            Positioned(
              left: Constants.padding, right: Constants.padding,
              child: CircleAvatar(
                backgroundColor: Colors.blueAccent, radius: Constants.avatarRadius,
                child: ClipRRect(
                  borderRadius: const BorderRadius.all(Radius.circular(Constants.avatarRadius)),
                  child: Icon(Icons.done, size: 24, color: Colors.white,)
                ),
              ),
            ),
            Positioned(
              left: 0,
              //right: Constants.padding,
              child: CircleAvatar(
                backgroundColor: Colors.blueAccent, radius: Constants.avatarRadius,
                child: ClipRRect(
                  borderRadius: const BorderRadius.all(Radius.circular(Constants.avatarRadius)),
                  child: InkWell(child: const Icon(Icons.close, size: 24, color: Colors.white,), onTap: (){Get.back();},)
                ),
              ),
            ),
          ],
        ))],
      );
    }, barrierDismissible: true, barrierLabel: '');

/// 這對我有用,經過你的身體,看看結果

未來 _showDialog() async { return showDialog( context: context,

barrierDismissible: true,
builder: (BuildContext context) {
  return Center(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Material(
          color: Colors.transparent,
          child: Container(
            padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(5),
            ),
            alignment: Alignment.center,
            width: MediaQuery.of(context).size.width,
            margin: EdgeInsets.all(10),
            /// paste your item body 
            child:body,
          ),
        ),
      ],
    ),
  );
},

); }

使用width: MediaQuery.of(context).size.width增加警報的寬度

示例

return AlertDialog(
      title: Text("Select Birth Date"),
      content: Container(
        width: MediaQuery.of(context).size.width,
        height: 300,
        child: CupertinoDatePicker(
          mode: CupertinoDatePickerMode.date,
          initialDateTime: DateTime(1969, 1, 1),
          onDateTimeChanged: (DateTime newDateTime) {
            // Do something
           
          },
        ),
      ),
      actions: <Widget>[
        FlatButton(
          child: Text("Select"),
          onPressed: () {
            widget.onSelected(selectedDate);
            Navigator.pop(context);
            //.....
          },
        ),
      ],
    );

就我而言,我在對話框中使用了 listview,所以我沒有在 ListView 中使用收縮包裝,希望這會對某人有所幫助。

ListView.builder(
shrinkWrap : true...
...
};

對我有用的解決方案。

設置 AlertDialog 的 insetPadding。

另外,將內容包裝在 SizedBox 中並將寬度設置為MediaQuery.of(context).size.width

return AlertDialog(
  content: SizedBox(
    width: MediaQuery.of(context).size.width,
    child: const Text("Content"),
  ),
  insetPadding: const EdgeInsets.all(10),
);

僅設置 insetPadding 不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM