Flutter自定义弹窗Dialog效果

Butterfly ·
更新时间:2024-11-10
· 491 次阅读

本文实例为大家分享了Flutter自定义弹窗Dialog效果的具体代码,供大家参考,具体内容如下

主要是基于系统的dialog机制做一些使用限制和自定义UI的优化

核心代码:

class CustomDialog {   static void show(BuildContext context, Widget Function(BuildContext ctx, void Function() dismiss)builder, {bool cancellable = false}) {     showDialog(       context: context,       barrierDismissible: cancellable,       builder: (ctx) {         return WillPopScope(           child: Dialog(             child: builder(ctx, () => Navigator.of(ctx).pop()),             backgroundColor: Colors.transparent,             shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(0.0))),             elevation: 0,             alignment: Alignment.center,           ),           onWillPop: () async => cancellable,         );       },     );   }   static void showBottomSheet(BuildContext context, Widget Function(BuildContext ctx, void Function() dismiss)builder, {bool cancellable = true}) {     showModalBottomSheet(       context: context,       isDismissible: cancellable,       enableDrag: cancellable,       isScrollControlled: true,       builder: (BuildContext ctx) {         return WillPopScope(           child: builder(ctx, () => Navigator.of(ctx).pop()),           onWillPop: () async => cancellable,         );       },       //不设置会默认使用屏幕最大宽度而不是子组件宽度       constraints: const BoxConstraints(minWidth: 0, minHeight: 0, maxWidth: double.infinity, maxHeight: double.infinity),       backgroundColor: Colors.transparent,     );   } }

使用:

import 'dart:async'; import 'package:flutter/material.dart'; class DialogTestPage extends StatefulWidget {   const DialogTestPage({Key? key}) : super(key: key);   @override   State<StatefulWidget> createState() => _DialogTestState(); } class _DialogTestState extends State<DialogTestPage> {   @override   Widget build(BuildContext context) {     return Scaffold(       body: Column(children: [         const SizedBox(height: 0, width: double.infinity,),         TextButton(           child: const Text("show dialog"),           onPressed: () => showCustomDialog(),         ),         TextButton(           child: const Text("show delay dialog"),           onPressed: () => showDelayDialog(),         ),         TextButton(           child: const Text("show sheet"),           onPressed: () => showSheetDialog(),         ),       ], mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center,),     );   }   void showCustomDialog() {     CustomDialog.show(context, (context, dismiss) {       return Container(         width: 200,         height: 100,         color: Colors.white,         child: Center(child: TextButton(onPressed: () => dismiss(), child: const Text("POP")),),       );     });   }   void showSheetDialog() {     CustomDialog.showBottomSheet(context, (ctx, dismiss) {       return Container(         height: 300,         color: Colors.white,         child: Center(child: TextButton(onPressed: () => dismiss(), child: const Text("POP")),),         margin: const EdgeInsets.all(20),       );     });   }   void showDelayDialog() {     CustomDialog.show(context, (context, dismiss) {       //延时关闭       Timer(const Duration(seconds: 2), () => dismiss());       return Container(         width: 200,         height: 100,         color: Colors.yellow,         child: const Center(child: Text("等待"),),       );     }, cancellable: true);   } }

其中show方法中使用到的Dialog默认使用material组件库的,如果觉得有不合理的尺寸约束,可替换我修改过的Dialog组件,有其他需求也可在此定制,为什么不直接放弃使用此组件?主要涉及到其路由跳转中的一些动画布局之类的。

class Dialog extends StatelessWidget {   const Dialog({     Key? key,     this.backgroundColor,     this.elevation,     this.insetAnimationDuration = const Duration(milliseconds: 100),     this.insetAnimationCurve = Curves.decelerate,     this.insetPadding = const EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0),     this.clipBehavior = Clip.none,     this.shape,     this.alignment,     this.child,   }) : super(key: key);   final Color? backgroundColor;   final double? elevation;   final Duration insetAnimationDuration;   final Curve insetAnimationCurve;   final EdgeInsets? insetPadding;   final Clip clipBehavior;   final ShapeBorder? shape;   final AlignmentGeometry? alignment;   final Widget? child;   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);     final EdgeInsets effectivePadding = MediaQuery.of(context).viewInsets + (insetPadding ?? EdgeInsets.zero);     return AnimatedPadding(       padding: effectivePadding,       duration: insetAnimationDuration,       curve: insetAnimationCurve,       child: MediaQuery.removeViewInsets(         removeLeft: true,         removeTop: true,         removeRight: true,         removeBottom: true,         context: context,         child: Align(           alignment: alignment ?? dialogTheme.alignment ?? Alignment.center,           child: Material(             color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor,             elevation: elevation ?? dialogTheme.elevation ?? _defaultElevation,             shape: shape ?? dialogTheme.shape ?? _defaultDialogShape,             type: MaterialType.card,             clipBehavior: clipBehavior,             child: child,           ),         ),       ),     );   } }



dialog flutter

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章